@@ -234,8 +234,14 @@ impl Person {
234234 /// Formats the given name into initials.
235235 ///
236236 /// For example, `"Judith Beatrice"` would yield `"J. B."` if the
237- /// `delimiter` argument is set to `Some(".")`, `"Klaus-Peter"` would become
238- /// `"K-P"` without a delimiter.
237+ /// `delimiter` argument is set to `Some(". ")`, `"Klaus-Peter"` would
238+ /// become `"K-P"` without a delimiter (or with an empty delimiter).
239+ ///
240+ /// Whitespace at the end of the delimiter is kept when parts are separated
241+ /// by whitespace (as in the first example), but not when parts of a
242+ /// compound given name are separated by hyphens (for example,
243+ /// `"Klaus-Peter"` produces `"K.-P."` instead of `"K. -P."` for a
244+ /// delimiter of `Some(". ")`).
239245 pub fn initials (
240246 & self ,
241247 buf : & mut impl std:: fmt:: Write ,
@@ -253,15 +259,21 @@ impl Person {
253259 if let Some ( c) = gr. chars ( ) . next ( ) {
254260 if c. is_whitespace ( ) || c == '-' {
255261 if !collect {
262+ let hyphenate = with_hyphen && c == '-' ;
256263 if let Some ( delimiter) = delimiter {
257- buf. write_str ( delimiter. trim_end ( ) ) ?;
264+ // Use the given delimiter, including any spaces at
265+ // its end if there was a whitespace, but not if we
266+ // should add a hyphen in a compound given name.
267+ buf. write_str ( if hyphenate {
268+ delimiter. trim_end ( )
269+ } else {
270+ delimiter
271+ } ) ?;
258272 }
259273
260274 collect = true ;
261- if with_hyphen && c == '-' {
262- buf. write_char ( c) ?;
263- } else if delimiter. is_some ( ) {
264- buf. write_char ( ' ' ) ?;
275+ if hyphenate {
276+ buf. write_char ( '-' ) ?;
265277 }
266278 }
267279 continue ;
@@ -277,7 +289,7 @@ impl Person {
277289
278290 if non_empty && !collect {
279291 if let Some ( delim) = delimiter {
280- buf. write_str ( delim) ?;
292+ buf. write_str ( delim. trim_end ( ) ) ?;
281293 }
282294 }
283295
@@ -315,7 +327,7 @@ impl Person {
315327 Ok ( ( ) )
316328 }
317329
318- /// Get the name with the family name fist , the initials
330+ /// Get the name with the family name first , the initials
319331 /// afterwards, separated by a comma.
320332 pub fn name_first ( & self , initials : bool , prefix_given_name : bool ) -> String {
321333 let mut res = if !prefix_given_name {
@@ -331,7 +343,7 @@ impl Person {
331343 if initials {
332344 if self . given_name . is_some ( ) {
333345 res += ", " ;
334- self . initials ( & mut res, Some ( "." ) , true ) . unwrap ( ) ;
346+ self . initials ( & mut res, Some ( ". " ) , true ) . unwrap ( ) ;
335347 }
336348 } else if let Some ( given_name) = & self . given_name {
337349 res += ", " ;
@@ -361,7 +373,7 @@ impl Person {
361373
362374 if initials {
363375 if self . given_name . is_some ( ) {
364- self . initials ( & mut res, Some ( "." ) , true ) . unwrap ( ) ;
376+ self . initials ( & mut res, Some ( ". " ) , true ) . unwrap ( ) ;
365377 res. push ( ' ' ) ;
366378 }
367379 } else if let Some ( given_name) = & self . given_name {
@@ -536,17 +548,62 @@ mod tests {
536548 let mut s = String :: new ( ) ;
537549 let p = Person :: from_strings ( vec ! [ "Dissmer" , "Courtney Deliah" ] ) . unwrap ( ) ;
538550 p. initials ( & mut s, Some ( "." ) , true ) . unwrap ( ) ;
551+ assert_eq ! ( "C.D." , s) ;
552+
553+ let mut s = String :: new ( ) ;
554+ let p = Person :: from_strings ( vec ! [ "Dissmer" , "Courtney Deliah" ] ) . unwrap ( ) ;
555+ p. initials ( & mut s, Some ( ". " ) , true ) . unwrap ( ) ;
539556 assert_eq ! ( "C. D." , s) ;
540557
558+ let mut s = String :: new ( ) ;
559+ let p = Person :: from_strings ( vec ! [ "Dissmer" , "Courtney Deliah" ] ) . unwrap ( ) ;
560+ p. initials ( & mut s, Some ( "" ) , true ) . unwrap ( ) ;
561+ assert_eq ! ( "CD" , s) ;
562+
541563 let mut s = String :: new ( ) ;
542564 let p = Person :: from_strings ( vec ! [ "Dissmer" , "Courtney Deliah" ] ) . unwrap ( ) ;
543565 p. initials ( & mut s, None , true ) . unwrap ( ) ;
544566 assert_eq ! ( "CD" , s) ;
545567
568+ let mut s = String :: new ( ) ;
569+ let p = Person :: from_strings ( vec ! [ "Günther" , "Hans-Joseph" ] ) . unwrap ( ) ;
570+ p. initials ( & mut s, Some ( ". " ) , true ) . unwrap ( ) ;
571+ assert_eq ! ( "H.-J." , s) ;
572+
573+ let mut s = String :: new ( ) ;
574+ let p = Person :: from_strings ( vec ! [ "Günther" , "Hans-Joseph" ] ) . unwrap ( ) ;
575+ p. initials ( & mut s, Some ( "." ) , true ) . unwrap ( ) ;
576+ assert_eq ! ( "H.-J." , s) ;
577+
578+ let mut s = String :: new ( ) ;
579+ let p = Person :: from_strings ( vec ! [ "Günther" , "Hans-Joseph" ] ) . unwrap ( ) ;
580+ p. initials ( & mut s, Some ( "" ) , true ) . unwrap ( ) ;
581+ assert_eq ! ( "H-J" , s) ;
582+
546583 let mut s = String :: new ( ) ;
547584 let p = Person :: from_strings ( vec ! [ "Günther" , "Hans-Joseph" ] ) . unwrap ( ) ;
548585 p. initials ( & mut s, None , true ) . unwrap ( ) ;
549586 assert_eq ! ( "H-J" , s) ;
587+
588+ let mut s = String :: new ( ) ;
589+ let p = Person :: from_strings ( vec ! [ "Günther" , "Hans-Joseph" ] ) . unwrap ( ) ;
590+ p. initials ( & mut s, Some ( ". " ) , false ) . unwrap ( ) ;
591+ assert_eq ! ( "H. J." , s) ;
592+
593+ let mut s = String :: new ( ) ;
594+ let p = Person :: from_strings ( vec ! [ "Günther" , "Hans-Joseph" ] ) . unwrap ( ) ;
595+ p. initials ( & mut s, Some ( "." ) , false ) . unwrap ( ) ;
596+ assert_eq ! ( "H.J." , s) ;
597+
598+ let mut s = String :: new ( ) ;
599+ let p = Person :: from_strings ( vec ! [ "Günther" , "Hans-Joseph" ] ) . unwrap ( ) ;
600+ p. initials ( & mut s, Some ( "" ) , false ) . unwrap ( ) ;
601+ assert_eq ! ( "HJ" , s) ;
602+
603+ let mut s = String :: new ( ) ;
604+ let p = Person :: from_strings ( vec ! [ "Günther" , "Hans-Joseph" ] ) . unwrap ( ) ;
605+ p. initials ( & mut s, None , false ) . unwrap ( ) ;
606+ assert_eq ! ( "HJ" , s) ;
550607 }
551608
552609 #[ test]
@@ -562,4 +619,16 @@ mod tests {
562619 p. first_name_with_delimiter ( & mut s, Some ( "." ) ) . unwrap ( ) ;
563620 assert_eq ! ( "James T." , s) ;
564621 }
622+
623+ #[ test]
624+ fn person_name_retrieval_order ( ) {
625+ let p =
626+ Person :: from_strings ( vec ! [ "van Dissmer" , "Jr." , "Courtney Deliah" ] ) . unwrap ( ) ;
627+ assert_eq ! ( "van Dissmer, Courtney Deliah, Jr." , p. name_first( false , false ) ) ;
628+ assert_eq ! ( "Dissmer, Courtney Deliah van, Jr." , p. name_first( false , true ) ) ;
629+ assert_eq ! ( "van Dissmer, C. D., Jr." , p. name_first( true , false ) ) ;
630+ assert_eq ! ( "Dissmer, C. D. van, Jr." , p. name_first( true , true ) ) ;
631+ assert_eq ! ( "Courtney Deliah van Dissmer Jr." , p. given_first( false ) ) ;
632+ assert_eq ! ( "C. D. van Dissmer Jr." , p. given_first( true ) ) ;
633+ }
565634}
0 commit comments