@@ -64,7 +64,8 @@ pub fn typographic_quotes<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
64
64
/// Custom whitespace-detection function, including `,`, `;`, `.`, `!`, `?`, and `:`
65
65
fn is_whitespace ( c : char ) -> bool {
66
66
match c {
67
- ',' | '.' | ';' | '!' | '?' | ':' => true ,
67
+ ',' | '.' | ';' | '!' | '?' | ':' | '"'
68
+ | '(' | ')' => true ,
68
69
_ => c. is_whitespace ( )
69
70
}
70
71
}
@@ -83,27 +84,32 @@ pub fn typographic_quotes<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
83
84
}
84
85
new_s. push_str ( & input[ 0 ..first] ) ;
85
86
let chars = input[ first..] . chars ( ) . collect :: < Vec < _ > > ( ) ;
86
- let mut has_opened_quote = false ;
87
+ let mut closing_quote = None ;
87
88
for i in 0 ..chars. len ( ) {
88
89
let c = chars[ i] ;
90
+ let has_opened_quote = if let Some ( n) = closing_quote {
91
+ i <= n
92
+ } else {
93
+ false
94
+ } ;
89
95
match c {
90
96
'"' => {
91
- if i > 0 && !is_whitespace ( chars[ i - 1 ] ) {
97
+ if i > 0 && !chars[ i- 1 ] . is_whitespace ( ) {
92
98
new_s. push ( '”' ) ;
93
- } else if i < chars. len ( ) - 1 && !is_whitespace ( chars[ i + 1 ] ) {
99
+ } else if i < chars. len ( ) - 1 && !is_whitespace ( chars[ i+ 1 ] ) {
94
100
new_s. push ( '“' ) ;
95
101
} else {
96
102
new_s. push ( '"' ) ;
97
103
}
98
104
} ,
99
105
'\'' => {
100
106
let prev = if i > 0 {
101
- Some ( !is_whitespace ( chars[ i - 1 ] ) )
107
+ Some ( !chars[ i - 1 ] . is_whitespace ( ) )
102
108
} else {
103
109
None
104
110
} ;
105
111
let next = if i < chars. len ( ) - 1 {
106
- Some ( !is_whitespace ( chars[ i + 1 ] ) )
112
+ Some ( !chars[ i+ 1 ] . is_whitespace ( ) )
107
113
} else {
108
114
None
109
115
} ;
@@ -118,26 +124,19 @@ pub fn typographic_quotes<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
118
124
let mut is_next_closing = false ;
119
125
for j in ( i + 1 ) ..chars. len ( ) {
120
126
if chars[ j] == '\'' {
121
- println ! ( "match at {}" , j) ;
122
127
if chars[ j-1 ] . is_whitespace ( ) {
123
- println ! ( "prev is whitespace, not closing quote" ) ;
124
128
continue ;
125
129
} else {
126
130
if j >= chars. len ( ) - 1
127
- || is_whitespace ( chars[ j+1 ] )
128
- || chars[ j+1 ] == '"' {
131
+ || is_whitespace ( chars[ j+1 ] ) {
129
132
is_next_closing = true ;
133
+ closing_quote = Some ( j) ;
130
134
break ;
131
135
}
132
- else {
133
- println ! ( "j: {}, len: {}" , j, chars. len( ) ) ;
134
- }
135
136
}
136
137
}
137
138
}
138
- println ! ( "is_next_closing: {}" , is_next_closing) ;
139
139
if is_next_closing && !has_opened_quote {
140
- has_opened_quote = true ;
141
140
'‘'
142
141
} else {
143
142
'’'
@@ -148,7 +147,6 @@ pub fn typographic_quotes<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> {
148
147
( Some ( true ) , Some ( false ) )
149
148
| ( Some ( true ) , None )
150
149
=> {
151
- has_opened_quote = false ;
152
150
'’'
153
151
} ,
154
152
@@ -230,3 +228,10 @@ fn typographic_quotes_8() {
230
228
let s = typographic_quotes ( "\" I like 'That '70s show'\" , she said" ) ;
231
229
assert_eq ! ( & s, "“I like ‘That ’70s show’”, she said" ) ;
232
230
}
231
+
232
+
233
+ #[ test]
234
+ fn typographic_quotes_9 ( ) {
235
+ let s = typographic_quotes ( "some char: '!', '?', ','" ) ;
236
+ assert_eq ! ( & s, "some char: ‘!’, ‘?’, ‘,’" ) ;
237
+ }
0 commit comments