Skip to content

Commit 01f143e

Browse files
Merge pull request RustPython#832 from RustPython/joey/proper-titlecase
str: proper titlecase support
2 parents de3900b + ae8ea1d commit 01f143e

File tree

3 files changed

+18
-3
lines changed

3 files changed

+18
-3
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vm/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,8 @@ unicode-segmentation = "1.2.1"
2727
lazy_static = "^1.0.1"
2828
lexical = "2.0.0"
2929
itertools = "^0.8.0"
30+
31+
# TODO: release and publish to crates.io
32+
[dependencies.unicode-casing]
33+
git = "https://github.com/OddCoincidence/unicode-casing"
34+
rev = "90d6d1f02b9cc04ffb55a5f1c3fa1455a84231fb"

vm/src/obj/objstr.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use std::str::FromStr;
55
use std::string::ToString;
66

77
use num_traits::ToPrimitive;
8+
use unicode_casing::CharExt;
89
use unicode_segmentation::UnicodeSegmentation;
910

1011
use crate::format::{FormatParseError, FormatPart, FormatString};
@@ -413,12 +414,12 @@ impl PyString {
413414
for c in self.value.chars() {
414415
if c.is_lowercase() {
415416
if !previous_is_cased {
416-
title.extend(c.to_uppercase());
417+
title.extend(c.to_titlecase());
417418
} else {
418419
title.push(c);
419420
}
420421
previous_is_cased = true;
421-
} else if c.is_uppercase() {
422+
} else if c.is_uppercase() || c.is_titlecase() {
422423
if previous_is_cased {
423424
title.extend(c.to_lowercase());
424425
} else {
@@ -652,7 +653,7 @@ impl PyString {
652653
let mut cased = false;
653654
let mut previous_is_cased = false;
654655
for c in self.value.chars() {
655-
if c.is_uppercase() {
656+
if c.is_uppercase() || c.is_titlecase() {
656657
if previous_is_cased {
657658
return false;
658659
}
@@ -1050,6 +1051,7 @@ mod tests {
10501051
("Format,This-As*Title;String", "fOrMaT,thIs-aS*titLe;String"),
10511052
("Getint", "getInt"),
10521053
("Greek Ωppercases ...", "greek ωppercases ..."),
1054+
("Greek ῼitlecases ...", "greek ῳitlecases ..."),
10531055
];
10541056
for (title, input) in tests {
10551057
assert_eq!(PyString::from(input).title(&vm).as_str(), title);
@@ -1066,6 +1068,7 @@ mod tests {
10661068
"A\nTitlecased Line",
10671069
"A Titlecased, Line",
10681070
"Greek Ωppercases ...",
1071+
"Greek ῼitlecases ...",
10691072
];
10701073

10711074
for s in pos {

0 commit comments

Comments
 (0)