CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Tools/langtool/src/section.rs
Views: 1401
1
// Super simplified ini file processor.
2
// Doesn't even bother with understanding comments.
3
// Just understands section headings and
4
// keys and values, split by ' = '.
5
6
#[derive(Debug, Clone)]
7
pub struct Section {
8
pub name: String,
9
pub title_line: String,
10
pub lines: Vec<String>,
11
}
12
13
impl Section {
14
pub fn remove_line(&mut self, key: &str) -> Option<String> {
15
let mut remove_index = None;
16
for (index, line) in self.lines.iter().enumerate() {
17
let prefix = if let Some(pos) = line.find(" =") {
18
&line[0..pos]
19
} else {
20
continue;
21
};
22
23
if prefix.eq_ignore_ascii_case(key) {
24
remove_index = Some(index);
25
break;
26
}
27
}
28
29
if let Some(remove_index) = remove_index {
30
Some(self.lines.remove(remove_index))
31
} else {
32
None
33
}
34
}
35
36
pub fn get_line(&mut self, key: &str) -> Option<String> {
37
for line in self.lines.iter() {
38
let prefix = if let Some(pos) = line.find(" =") {
39
&line[0..pos]
40
} else {
41
continue;
42
};
43
44
if prefix.eq_ignore_ascii_case(key) {
45
return Some(line.clone());
46
}
47
}
48
None
49
}
50
51
pub fn insert_line_if_missing(&mut self, line: &str) -> bool {
52
let prefix = if let Some(pos) = line.find(" =") {
53
&line[0..pos + 2]
54
} else {
55
return false;
56
};
57
58
// Ignore comments when copying lines.
59
if prefix.starts_with('#') {
60
return false;
61
}
62
// Need to decide a policy for these.
63
if prefix.starts_with("translators") {
64
return false;
65
}
66
let prefix = prefix.to_owned();
67
68
for iter_line in &self.lines {
69
if iter_line.starts_with(&prefix) {
70
// Already have it
71
return false;
72
}
73
}
74
75
// Now try to insert it at an alphabetic-ish location.
76
let prefix = prefix.to_ascii_lowercase();
77
78
// Then, find a suitable insertion spot
79
for (i, iter_line) in self.lines.iter().enumerate() {
80
if iter_line.to_ascii_lowercase() > prefix {
81
println!("Inserting line {} into {}", line, self.name);
82
self.lines.insert(i, line.to_owned());
83
return true;
84
}
85
}
86
87
for i in (0..self.lines.len()).rev() {
88
if self.lines[i].is_empty() {
89
continue;
90
}
91
println!("Inserting line {} into {}", line, self.name);
92
self.lines.insert(i + 1, line.to_owned());
93
return true;
94
}
95
96
println!("failed to insert {}", line);
97
true
98
}
99
100
pub fn rename_key(&mut self, old: &str, new: &str) {
101
let prefix = old.to_owned() + " =";
102
let mut found_index = None;
103
for (index, line) in self.lines.iter().enumerate() {
104
if line.starts_with(&prefix) {
105
found_index = Some(index);
106
}
107
}
108
if let Some(index) = found_index {
109
let line = self.lines.remove(index);
110
let mut right_part = line.strip_prefix(&prefix).unwrap().to_string();
111
if right_part.trim() == old.trim() {
112
// Was still untranslated - replace the translation too.
113
right_part = format!(" {}", new);
114
}
115
let line = new.to_owned() + " =" + &right_part;
116
self.insert_line_if_missing(&line);
117
} else {
118
let name = &self.name;
119
println!("didn't find a line starting with {prefix} in section {name}");
120
}
121
}
122
123
pub fn sort(&mut self) {
124
self.lines.sort();
125
}
126
127
pub fn comment_out_lines_if_not_in(&mut self, other: &Section) {
128
// Brute force (O(n^2)). Bad but not a problem.
129
130
for line in &mut self.lines {
131
let prefix = if let Some(pos) = line.find(" =") {
132
&line[0..pos + 2]
133
} else {
134
// Keep non-key lines.
135
continue;
136
};
137
if prefix.starts_with("Font") || prefix.starts_with('#') {
138
continue;
139
}
140
if !other.lines.iter().any(|line| line.starts_with(prefix)) && !prefix.contains("URL") {
141
println!("Commenting out from {}: {line}", other.name);
142
// Comment out the line.
143
*line = "#".to_owned() + line;
144
}
145
}
146
}
147
148
pub fn remove_lines_if_not_in(&mut self, other: &Section) {
149
// Brute force (O(n^2)). Bad but not a problem.
150
151
self.lines.retain(|line| {
152
let prefix = if let Some(pos) = line.find(" =") {
153
&line[0..pos + 2]
154
} else {
155
// Keep non-key lines.
156
return true;
157
};
158
if prefix.starts_with("Font") || prefix.starts_with('#') {
159
return true;
160
}
161
162
// keeps the line if this expression returns true.
163
other.lines.iter().any(|line| line.starts_with(prefix))
164
});
165
}
166
}
167
168