@@ -51,14 +51,26 @@ fn format_line_flowed(line: &str, prefix: &str) -> String {
51
51
result + & buffer
52
52
}
53
53
54
- fn format_flowed_prefix ( text : & str , prefix : & str ) -> String {
54
+ /// Returns text formatted according to RFC 3767 (format=flowed).
55
+ ///
56
+ /// This function accepts text separated by LF, but returns text
57
+ /// separated by CRLF.
58
+ ///
59
+ /// RFC 2646 technique is used to insert soft line breaks, so DelSp
60
+ /// SHOULD be set to "no" when sending.
61
+ pub ( crate ) fn format_flowed ( text : & str ) -> String {
55
62
let mut result = String :: new ( ) ;
56
63
57
64
for line in text. split ( '\n' ) {
58
65
if !result. is_empty ( ) {
59
66
result += "\r \n " ;
60
67
}
61
- let line = line. trim_end ( ) ;
68
+
69
+ let line_no_prefix = line. strip_prefix ( '>' ) ;
70
+ let is_quote = line_no_prefix. is_some ( ) ;
71
+ let line = line_no_prefix. unwrap_or ( line) . trim ( ) ;
72
+ let prefix = if is_quote { "> " } else { "" } ;
73
+
62
74
if prefix. len ( ) + line. len ( ) > 78 {
63
75
result += & format_line_flowed ( line, prefix) ;
64
76
} else {
@@ -70,23 +82,23 @@ fn format_flowed_prefix(text: &str, prefix: &str) -> String {
70
82
result += line;
71
83
}
72
84
}
73
- result
74
- }
75
85
76
- /// Returns text formatted according to RFC 3767 (format=flowed).
77
- ///
78
- /// This function accepts text separated by LF, but returns text
79
- /// separated by CRLF.
80
- ///
81
- /// RFC 2646 technique is used to insert soft line breaks, so DelSp
82
- /// SHOULD be set to "no" when sending.
83
- pub fn format_flowed ( text : & str ) -> String {
84
- format_flowed_prefix ( text, "" )
86
+ result
85
87
}
86
88
87
89
/// Same as format_flowed(), but adds "> " prefix to each line.
88
90
pub fn format_flowed_quote ( text : & str ) -> String {
89
- format_flowed_prefix ( text, "> " )
91
+ let mut result = String :: new ( ) ;
92
+
93
+ for line in text. split ( '\n' ) {
94
+ if !result. is_empty ( ) {
95
+ result += "\n " ;
96
+ }
97
+ result += "> " ;
98
+ result += line;
99
+ }
100
+
101
+ format_flowed ( & result)
90
102
}
91
103
92
104
/// Joins lines in format=flowed text.
@@ -129,6 +141,7 @@ pub fn unformat_flowed(text: &str, delsp: bool) -> String {
129
141
#[ cfg( test) ]
130
142
mod tests {
131
143
use super :: * ;
144
+ use crate :: test_utils:: TestContext ;
132
145
133
146
#[ test]
134
147
fn test_format_flowed ( ) {
@@ -144,18 +157,18 @@ mod tests {
144
157
client and enter the setup code presented on the generating device.";
145
158
assert_eq ! ( format_flowed( text) , expected) ;
146
159
147
- let text = "> Not a quote" ;
148
- assert_eq ! ( format_flowed( text) , " > Not a quote" ) ;
160
+ let text = "> A quote" ;
161
+ assert_eq ! ( format_flowed( text) , "> A quote" ) ;
149
162
150
163
// Test space stuffing of wrapped lines
151
164
let text = "> This is the Autocrypt Setup Message used to transfer your key between clients.\n \
152
165
> \n \
153
166
> To decrypt and use your key, open the message in an Autocrypt-compliant client and enter the setup code presented on the generating device.";
154
- let expected = "\x20 > This is the Autocrypt Setup Message used to transfer your key between \r \n \
155
- clients.\r \n \
156
- \x20 > \r \n \
157
- \x20 > To decrypt and use your key, open the message in an Autocrypt-compliant \r \n \
158
- client and enter the setup code presented on the generating device.";
167
+ let expected = "> This is the Autocrypt Setup Message used to transfer your key between \r \n \
168
+ > clients.\r \n \
169
+ > \r \n \
170
+ > To decrypt and use your key, open the message in an Autocrypt-compliant \r \n \
171
+ > client and enter the setup code presented on the generating device.";
159
172
assert_eq ! ( format_flowed( text) , expected) ;
160
173
}
161
174
@@ -175,6 +188,10 @@ mod tests {
175
188
let expected = "> this is a quoted line" ;
176
189
assert_eq ! ( format_flowed_quote( quote) , expected) ;
177
190
191
+ let quote = "first quoted line\n second quoted line" ;
192
+ let expected = "> first quoted line\r \n > second quoted line" ;
193
+ assert_eq ! ( format_flowed_quote( quote) , expected) ;
194
+
178
195
let quote = "> foo bar baz" ;
179
196
let expected = "> > foo bar baz" ;
180
197
assert_eq ! ( format_flowed_quote( quote) , expected) ;
@@ -185,4 +202,25 @@ mod tests {
185
202
> unwrapped on the receiver";
186
203
assert_eq ! ( format_flowed_quote( quote) , expected) ;
187
204
}
205
+
206
+ #[ async_std:: test]
207
+ async fn test_send_quotes ( ) -> anyhow:: Result < ( ) > {
208
+ let alice = TestContext :: new_alice ( ) . await ;
209
+ let bob = TestContext :: new_bob ( ) . await ;
210
+ let chat = alice. create_chat ( & bob) . await ;
211
+
212
+ let sent = alice. send_text ( chat. id , "> First quote" ) . await ;
213
+ let received = bob. recv_msg ( & sent) . await ;
214
+ assert_eq ! ( received. text. as_deref( ) , Some ( "> First quote" ) ) ;
215
+ assert ! ( received. quoted_text( ) . is_none( ) ) ;
216
+ assert ! ( received. quoted_message( & bob) . await ?. is_none( ) ) ;
217
+
218
+ let sent = alice. send_text ( chat. id , "> Second quote" ) . await ;
219
+ let received = bob. recv_msg ( & sent) . await ;
220
+ assert_eq ! ( received. text. as_deref( ) , Some ( "> Second quote" ) ) ;
221
+ assert ! ( received. quoted_text( ) . is_none( ) ) ;
222
+ assert ! ( received. quoted_message( & bob) . await ?. is_none( ) ) ;
223
+
224
+ Ok ( ( ) )
225
+ }
188
226
}
0 commit comments