on master help sign in
Replace tendril with smartstring
f88c077Blaž Hrastnik
Cargo.lock+16−40
@@ -246,16 +246,6 @@ dependencies = [
246 "percent-encoding",
246 "percent-encoding",
247]
247]
248
248
249−[[package]]
250−name = "futf"
251−version = "0.1.5"
252−source = "registry+https://github.com/rust-lang/crates.io-index"
253−checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843"
254−dependencies = [
255− "mac",
256− "new_debug_unreachable",
257−]
258−
259[[package]]
249[[package]]
260name = "futures-core"
250name = "futures-core"
261version = "0.3.21"
251version = "0.3.21"
@@ -383,7 +373,7 @@ dependencies = [
383 "similar",
373 "similar",
384 "slotmap",
374 "slotmap",
385 "smallvec",
375 "smallvec",
386− "tendril",
376+ "smartstring",
387 "toml",
377 "toml",
388 "tree-sitter",
378 "tree-sitter",
389 "unicode-general-category",
379 "unicode-general-category",
@@ -606,12 +596,6 @@ dependencies = [
606 "url",
596 "url",
607]
597]
608
598
609−[[package]]
610−name = "mac"
611−version = "0.1.1"
612−source = "registry+https://github.com/rust-lang/crates.io-index"
613−checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
614−
615[[package]]
599[[package]]
616name = "matches"
600name = "matches"
617version = "0.1.9"
601version = "0.1.9"
@@ -655,12 +639,6 @@ dependencies = [
655 "winapi",
639 "winapi",
656]
640]
657
641
658−[[package]]
659−name = "new_debug_unreachable"
660−version = "1.0.4"
661−source = "registry+https://github.com/rust-lang/crates.io-index"
662−checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
663−
664[[package]]
642[[package]]
665name = "ntapi"
643name = "ntapi"
666version = "0.3.6"
644version = "0.3.6"
@@ -1010,6 +988,21 @@ version = "1.8.0"
1010source = "registry+https://github.com/rust-lang/crates.io-index"
988source = "registry+https://github.com/rust-lang/crates.io-index"
1011checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
989checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
1012
990
991+[[package]]
992+name = "smartstring"
993+version = "0.2.9"
994+source = "registry+https://github.com/rust-lang/crates.io-index"
995+checksum = "31aa6a31c0c2b21327ce875f7e8952322acfcfd0c27569a6e18a647281352c9b"
996+dependencies = [
997+ "static_assertions",
998+]
999+
1000+[[package]]
1001+name = "static_assertions"
1002+version = "1.1.0"
1003+source = "registry+https://github.com/rust-lang/crates.io-index"
1004+checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
1005+
1013[[package]]
1006[[package]]
1014name = "str-buf"
1007name = "str-buf"
1015version = "1.0.5"
1008version = "1.0.5"
@@ -1027,17 +1020,6 @@ dependencies = [
1027 "unicode-xid",
1020 "unicode-xid",
1028]
1021]
1029
1022
1030−[[package]]
1031−name = "tendril"
1032−version = "0.4.2"
1033−source = "registry+https://github.com/rust-lang/crates.io-index"
1034−checksum = "a9ef557cb397a4f0a5a3a628f06515f78563f2209e64d47055d9dc6052bf5e33"
1035−dependencies = [
1036− "futf",
1037− "mac",
1038− "utf-8",
1039−]
1040−
1041[[package]]
1023[[package]]
1042name = "thiserror"
1024name = "thiserror"
1043version = "1.0.30"
1025version = "1.0.30"
@@ -1212,12 +1194,6 @@ dependencies = [
1212 "serde",
1194 "serde",
1213]
1195]
1214
1196
1215−[[package]]
1216−name = "utf-8"
1217−version = "0.7.6"
1218−source = "registry+https://github.com/rust-lang/crates.io-index"
1219−checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
1220−
1221[[package]]
1197[[package]]
1222name = "version_check"
1198name = "version_check"
1223version = "0.9.4"
1199version = "0.9.4"
helix-core/Cargo.toml+1−1
@@ -17,7 +17,7 @@ helix-syntax = { version = "0.6", path = "../helix-syntax" }
17
17
18ropey = "1.3"
18ropey = "1.3"
19smallvec = "1.8"
19smallvec = "1.8"
20−tendril = "0.4.2"
20+smartstring = "0.2.9"
21unicode-segmentation = "1.9"
21unicode-segmentation = "1.9"
22unicode-width = "0.1"
22unicode-width = "0.1"
23unicode-general-category = "0.5"
23unicode-general-category = "0.5"
helix-core/src/auto_pairs.rs+9−5
@@ -214,7 +214,9 @@ fn handle_open(
214 let change = match next_char {
214 let change = match next_char {
215 Some(ch) if !close_before.contains(ch) => {
215 Some(ch) if !close_before.contains(ch) => {
216 len_inserted = open.len_utf8();
216 len_inserted = open.len_utf8();
217− (cursor, cursor, Some(Tendril::from_char(open)))
217+ let mut tendril = Tendril::new();
218+ tendril.push(open);
219+ (cursor, cursor, Some(tendril))
218 }
220 }
219 // None | Some(ch) if close_before.contains(ch) => {}
221 // None | Some(ch) if close_before.contains(ch) => {}
220 _ => {
222 _ => {
@@ -252,7 +254,9 @@ fn handle_close(doc: &Rope, selection: &Selection, _open: char, close: char) ->
252 (cursor, cursor, None) // no-op
254 (cursor, cursor, None) // no-op
253 } else {
255 } else {
254 len_inserted += close.len_utf8();
256 len_inserted += close.len_utf8();
255− (cursor, cursor, Some(Tendril::from_char(close)))
257+ let mut tendril = Tendril::new();
258+ tendril.push(close);
259+ (cursor, cursor, Some(tendril))
256 };
260 };
257
261
258 let next_range = get_next_range(doc, start_range, offs, close, len_inserted);
262 let next_range = get_next_range(doc, start_range, offs, close, len_inserted);
@@ -290,15 +294,15 @@ fn handle_same(
290 // return transaction that moves past close
294 // return transaction that moves past close
291 (cursor, cursor, None) // no-op
295 (cursor, cursor, None) // no-op
292 } else {
296 } else {
293− let mut pair = Tendril::with_capacity(2 * token.len_utf8() as u32);
297+ let mut pair = Tendril::new();
294− pair.push_char(token);
298+ pair.push(token);
295
299
296 // for equal pairs, don't insert both open and close if either
300 // for equal pairs, don't insert both open and close if either
297 // side has a non-pair char
301 // side has a non-pair char
298 if (next_char.is_none() || close_before.contains(next_char.unwrap()))
302 if (next_char.is_none() || close_before.contains(next_char.unwrap()))
299 && (prev_char.is_none() || open_before.contains(prev_char.unwrap()))
303 && (prev_char.is_none() || open_before.contains(prev_char.unwrap()))
300 {
304 {
301− pair.push_char(token);
305+ pair.push(token);
302 }
306 }
303
307
304 len_inserted += pair.len();
308 len_inserted += pair.len();
helix-core/src/increment/date_time.rs+1−1
@@ -451,7 +451,7 @@ mod test {
451 .unwrap()
451 .unwrap()
452 .increment(amount)
452 .increment(amount)
453 .1,
453 .1,
454− expected.into()
454+ Tendril::from(expected)
455 );
455 );
456 }
456 }
457 }
457 }
helix-core/src/increment/number.rs+5−5
@@ -371,7 +371,7 @@ mod test {
371 .unwrap()
371 .unwrap()
372 .increment(amount)
372 .increment(amount)
373 .1,
373 .1,
374− expected.into()
374+ Tendril::from(expected)
375 );
375 );
376 }
376 }
377 }
377 }
@@ -398,7 +398,7 @@ mod test {
398 .unwrap()
398 .unwrap()
399 .increment(amount)
399 .increment(amount)
400 .1,
400 .1,
401− expected.into()
401+ Tendril::from(expected)
402 );
402 );
403 }
403 }
404 }
404 }
@@ -426,7 +426,7 @@ mod test {
426 .unwrap()
426 .unwrap()
427 .increment(amount)
427 .increment(amount)
428 .1,
428 .1,
429− expected.into()
429+ Tendril::from(expected)
430 );
430 );
431 }
431 }
432 }
432 }
@@ -472,7 +472,7 @@ mod test {
472 .unwrap()
472 .unwrap()
473 .increment(amount)
473 .increment(amount)
474 .1,
474 .1,
475− expected.into()
475+ Tendril::from(expected)
476 );
476 );
477 }
477 }
478 }
478 }
@@ -500,7 +500,7 @@ mod test {
500 .unwrap()
500 .unwrap()
501 .increment(amount)
501 .increment(amount)
502 .1,
502 .1,
503− expected.into()
503+ Tendril::from(expected)
504 );
504 );
505 }
505 }
506 }
506 }
helix-core/src/lib.rs+4−1
@@ -212,7 +212,10 @@ use etcetera::base_strategy::{choose_base_strategy, BaseStrategy};
212
212
213pub use ropey::{Rope, RopeBuilder, RopeSlice};
213pub use ropey::{Rope, RopeBuilder, RopeSlice};
214
214
215−pub use tendril::StrTendril as Tendril;
215+// pub use tendril::StrTendril as Tendril;
216+pub use smartstring::SmartString;
217+
218+pub type Tendril = SmartString<smartstring::LazyCompact>;
216
219
217#[doc(inline)]
220#[doc(inline)]
218pub use {regex, tree_sitter};
221pub use {regex, tree_sitter};
helix-core/src/transaction.rs+13−11
@@ -85,7 +85,7 @@ impl ChangeSet {
85
85
86 let new_last = match self.changes.as_mut_slice() {
86 let new_last = match self.changes.as_mut_slice() {
87 [.., Insert(prev)] | [.., Insert(prev), Delete(_)] => {
87 [.., Insert(prev)] | [.., Insert(prev), Delete(_)] => {
88− prev.push_tendril(&fragment);
88+ prev.push_str(&fragment);
89 return;
89 return;
90 }
90 }
91 [.., last @ Delete(_)] => std::mem::replace(last, Insert(fragment)),
91 [.., last @ Delete(_)] => std::mem::replace(last, Insert(fragment)),
@@ -189,7 +189,7 @@ impl ChangeSet {
189 // TODO: cover this with a test
189 // TODO: cover this with a test
190 // figure out the byte index of the truncated string end
190 // figure out the byte index of the truncated string end
191 let (pos, _) = s.char_indices().nth(j).unwrap();
191 let (pos, _) = s.char_indices().nth(j).unwrap();
192− s.pop_front(pos as u32);
192+ s.replace_range(0..pos, "");
193 head_a = Some(Insert(s));
193 head_a = Some(Insert(s));
194 head_b = changes_b.next();
194 head_b = changes_b.next();
195 }
195 }
@@ -211,9 +211,11 @@ impl ChangeSet {
211 Ordering::Greater => {
211 Ordering::Greater => {
212 // figure out the byte index of the truncated string end
212 // figure out the byte index of the truncated string end
213 let (pos, _) = s.char_indices().nth(j).unwrap();
213 let (pos, _) = s.char_indices().nth(j).unwrap();
214− let pos = pos as u32;
214+ let mut before = s;
215+ let after = before.split_off(pos);
216+
215− changes.insert(s.subtendril(0, pos));
217+ changes.insert(before);
216− head_a = Some(Insert(s.subtendril(pos, s.len() as u32 - pos)));
218+ head_a = Some(Insert(after));
217 head_b = changes_b.next();
219 head_b = changes_b.next();
218 }
220 }
219 }
221 }
@@ -277,7 +279,7 @@ impl ChangeSet {
277 }
279 }
278 Delete(n) => {
280 Delete(n) => {
279 let text = Cow::from(original_doc.slice(pos..pos + *n));
281 let text = Cow::from(original_doc.slice(pos..pos + *n));
280− changes.insert(Tendril::from_slice(&text));
282+ changes.insert(Tendril::from(text.as_ref()));
281 pos += n;
283 pos += n;
282 }
284 }
283 Insert(s) => {
285 Insert(s) => {
@@ -710,19 +712,19 @@ mod test {
710 #[test]
712 #[test]
711 fn optimized_composition() {
713 fn optimized_composition() {
712 let mut state = State::new("".into());
714 let mut state = State::new("".into());
713− let t1 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('h'));
715+ let t1 = Transaction::insert(&state.doc, &state.selection, Tendril::from("h"));
714 t1.apply(&mut state.doc);
716 t1.apply(&mut state.doc);
715 state.selection = state.selection.clone().map(t1.changes());
717 state.selection = state.selection.clone().map(t1.changes());
716− let t2 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('e'));
718+ let t2 = Transaction::insert(&state.doc, &state.selection, Tendril::from("e"));
717 t2.apply(&mut state.doc);
719 t2.apply(&mut state.doc);
718 state.selection = state.selection.clone().map(t2.changes());
720 state.selection = state.selection.clone().map(t2.changes());
719− let t3 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
721+ let t3 = Transaction::insert(&state.doc, &state.selection, Tendril::from("l"));
720 t3.apply(&mut state.doc);
722 t3.apply(&mut state.doc);
721 state.selection = state.selection.clone().map(t3.changes());
723 state.selection = state.selection.clone().map(t3.changes());
722− let t4 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('l'));
724+ let t4 = Transaction::insert(&state.doc, &state.selection, Tendril::from("l"));
723 t4.apply(&mut state.doc);
725 t4.apply(&mut state.doc);
724 state.selection = state.selection.clone().map(t4.changes());
726 state.selection = state.selection.clone().map(t4.changes());
725− let t5 = Transaction::insert(&state.doc, &state.selection, Tendril::from_char('o'));
727+ let t5 = Transaction::insert(&state.doc, &state.selection, Tendril::from("o"));
726 t5.apply(&mut state.doc);
728 t5.apply(&mut state.doc);
727 state.selection = state.selection.clone().map(t5.changes());
729 state.selection = state.selection.clone().map(t5.changes());
728
730
helix-lsp/src/client.rs+1−1
@@ -438,7 +438,7 @@ impl Client {
438
438
439 changes.push(lsp::TextDocumentContentChangeEvent {
439 changes.push(lsp::TextDocumentContentChangeEvent {
440 range: Some(lsp::Range::new(start, end)),
440 range: Some(lsp::Range::new(start, end)),
441− text: s.into(),
441+ text: s.to_string(),
442 range_length: None,
442 range_length: None,
443 });
443 });
444 }
444 }
helix-term/src/commands.rs+18−14
@@ -2769,7 +2769,7 @@ pub mod cmd {
2769
2769
2770 let mut fragments: Vec<_> = selection
2770 let mut fragments: Vec<_> = selection
2771 .fragments(text)
2771 .fragments(text)
2772− .map(|fragment| Tendril::from_slice(&fragment))
2772+ .map(|fragment| Tendril::from(fragment.as_ref()))
2773 .collect();
2773 .collect();
2774
2774
2775 fragments.sort_by(match reverse {
2775 fragments.sort_by(match reverse {
@@ -3921,7 +3921,7 @@ fn try_restore_indent(doc: &mut Document, view_id: ViewId) {
3921 if let [Operation::Retain(move_pos), Operation::Insert(ref inserted_str), Operation::Retain(_)] =
3921 if let [Operation::Retain(move_pos), Operation::Insert(ref inserted_str), Operation::Retain(_)] =
3922 changes
3922 changes
3923 {
3923 {
3924− move_pos + inserted_str.len32() as usize == pos
3924+ move_pos + inserted_str.len() == pos
3925 && inserted_str.starts_with('\n')
3925 && inserted_str.starts_with('\n')
3926 && inserted_str.chars().skip(1).all(char_is_whitespace)
3926 && inserted_str.chars().skip(1).all(char_is_whitespace)
3927 && pos == line_end_pos // ensure no characters exists after current position
3927 && pos == line_end_pos // ensure no characters exists after current position
@@ -4513,7 +4513,8 @@ pub mod insert {
4513 #[allow(clippy::unnecessary_wraps)] // need to use Option<> because of the Hook signature
4513 #[allow(clippy::unnecessary_wraps)] // need to use Option<> because of the Hook signature
4514 fn insert(doc: &Rope, selection: &Selection, ch: char) -> Option<Transaction> {
4514 fn insert(doc: &Rope, selection: &Selection, ch: char) -> Option<Transaction> {
4515 let cursors = selection.clone().cursors(doc.slice(..));
4515 let cursors = selection.clone().cursors(doc.slice(..));
4516− let t = Tendril::from_char(ch);
4516+ let mut t = Tendril::new();
4517+ t.push(ch);
4517 let transaction = Transaction::insert(doc, &cursors, t);
4518 let transaction = Transaction::insert(doc, &cursors, t);
4518 Some(transaction)
4519 Some(transaction)
4519 }
4520 }
@@ -5015,12 +5016,12 @@ fn replace_with_yanked(cx: &mut Context) {
5015 let repeat = std::iter::repeat(
5016 let repeat = std::iter::repeat(
5016 values
5017 values
5017 .last()
5018 .last()
5018− .map(|value| Tendril::from_slice(&value.repeat(count)))
5019+ .map(|value| Tendril::from(&value.repeat(count)))
5019 .unwrap(),
5020 .unwrap(),
5020 );
5021 );
5021 let mut values = values
5022 let mut values = values
5022 .iter()
5023 .iter()
5023− .map(|value| Tendril::from_slice(&value.repeat(count)))
5024+ .map(|value| Tendril::from(&value.repeat(count)))
5024 .chain(repeat);
5025 .chain(repeat);
5025 let selection = doc.selection(view.id);
5026 let selection = doc.selection(view.id);
5026 let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
5027 let transaction = Transaction::change_by_selection(doc.text(), selection, |range| {
@@ -5530,7 +5531,7 @@ fn rotate_selection_contents(cx: &mut Context, direction: Direction) {
5530 let selection = doc.selection(view.id);
5531 let selection = doc.selection(view.id);
5531 let mut fragments: Vec<_> = selection
5532 let mut fragments: Vec<_> = selection
5532 .fragments(text)
5533 .fragments(text)
5533− .map(|fragment| Tendril::from_slice(&fragment))
5534+ .map(|fragment| Tendril::from(fragment.as_ref()))
5534 .collect();
5535 .collect();
5535
5536
5536 let group = count
5537 let group = count
@@ -5891,8 +5892,12 @@ fn surround_add(cx: &mut Context) {
5891
5892
5892 let mut changes = Vec::with_capacity(selection.len() * 2);
5893 let mut changes = Vec::with_capacity(selection.len() * 2);
5893 for range in selection.iter() {
5894 for range in selection.iter() {
5894− changes.push((range.from(), range.from(), Some(Tendril::from_char(open))));
5895+ let mut o = Tendril::new();
5895− changes.push((range.to(), range.to(), Some(Tendril::from_char(close))));
5896+ o.push(open);
5897+ let mut c = Tendril::new();
5898+ c.push(close);
5899+ changes.push((range.from(), range.from(), Some(o)));
5900+ changes.push((range.to(), range.to(), Some(c)));
5896 }
5901 }
5897
5902
5898 let transaction = Transaction::change(doc.text(), changes.into_iter());
5903 let transaction = Transaction::change(doc.text(), changes.into_iter());
@@ -5921,11 +5926,9 @@ fn surround_replace(cx: &mut Context) {
5921 let transaction = Transaction::change(
5926 let transaction = Transaction::change(
5922 doc.text(),
5927 doc.text(),
5923 change_pos.iter().enumerate().map(|(i, &pos)| {
5928 change_pos.iter().enumerate().map(|(i, &pos)| {
5924− (
5929+ let mut t = Tendril::new();
5925− pos,
5926− pos + 1,
5927− Some(Tendril::from_char(if i % 2 == 0 { open } else { close })),
5930+ t.push(if i % 2 == 0 { open } else { close });
5928− )
5931+ (pos, pos + 1, Some(t))
5929 }),
5932 }),
5930 );
5933 );
5931 doc.apply(&transaction, view.id);
5934 doc.apply(&transaction, view.id);
@@ -6065,8 +6068,9 @@ fn shell_impl(
6065 log::error!("Shell error: {}", String::from_utf8_lossy(&output.stderr));
6068 log::error!("Shell error: {}", String::from_utf8_lossy(&output.stderr));
6066 }
6069 }
6067
6070
6068− let tendril = Tendril::try_from_byte_slice(&output.stdout)
6071+ let str = std::str::from_utf8(&output.stdout)
6069 .map_err(|_| anyhow!("Process did not output valid UTF-8"))?;
6072 .map_err(|_| anyhow!("Process did not output valid UTF-8"))?;
6073+ let tendril = Tendril::from(str);
6070 Ok((tendril, output.status.success()))
6074 Ok((tendril, output.status.success()))
6071}
6075}
6072
6076
xtask/src/main.rs+1−1
@@ -120,7 +120,7 @@ pub mod md_gen {
120 }
120 }
121
121
122 fn md_table_row(cols: &[String]) -> String {
122 fn md_table_row(cols: &[String]) -> String {
123− "| ".to_owned() + &cols.join(" | ") + " |\n"
123+ format!("| {} |\n", cols.join(" | "))
124 }
124 }
125
125
126 fn md_mono(s: &str) -> String {
126 fn md_mono(s: &str) -> String {