tangled
alpha
login
or
join now
eldridge.cam
/
paper-terminal
0
fork
atom
Print Markdown to a paper in your terminal
0
fork
atom
overview
issues
pulls
pipelines
Handle wide characters better
eldridge.cam
5 years ago
40d6a707
a6186503
+161
-99
6 changed files
expand all
collapse all
unified
split
Cargo.lock
Cargo.toml
src
main.rs
printer.rs
table.rs
words.rs
+1
Cargo.lock
···
437
"structopt",
438
"syncat-stylesheet",
439
"terminal_size",
0
440
]
441
442
[[package]]
···
437
"structopt",
438
"syncat-stylesheet",
439
"terminal_size",
440
+
"unicode-width",
441
]
442
443
[[package]]
+1
Cargo.toml
···
25
console = "0.13"
26
directories-next = "2.0"
27
syncat-stylesheet = { version = "2.1.4", features = ["ansi_term"] }
0
···
25
console = "0.13"
26
directories-next = "2.0"
27
syncat-stylesheet = { version = "2.1.4", features = ["ansi_term"] }
28
+
unicode-width = "0.1"
+15
-4
src/main.rs
···
8
use structopt::StructOpt;
9
use syncat_stylesheet::Stylesheet;
10
use terminal_size::{terminal_size, Width};
0
11
12
mod dirs;
13
mod printer;
···
17
18
use printer::Printer;
19
use words::Words;
0
0
0
0
0
0
0
20
21
/// Prints papers in your terminal
22
#[derive(StructOpt, Debug)]
···
113
return;
114
}
115
116
-
let centering = " ".repeat((terminal_width - width) / 2);
117
118
let stylesheet = Stylesheet::from_file(dirs::active_color().join("paper.syncat"))
119
.unwrap_or_else(|_| {
···
153
let mut buffer = String::new();
154
let mut indent = None;
155
for word in Words::preserving_whitespace(line) {
156
-
if buffer.chars().count() + word.chars().count() > available_width {
157
println!(
158
"{}{}{}{}{}{}",
159
centering,
160
margin,
161
paper_style.paint(&buffer),
162
-
paper_style.paint(" ".repeat(available_width - buffer.chars().count())),
0
0
163
margin,
164
shadow_style.paint(" "),
165
);
···
182
centering,
183
margin,
184
paper_style.paint(&buffer),
185
-
paper_style.paint(" ".repeat(available_width - buffer.chars().count())),
0
186
margin,
187
shadow_style.paint(" "),
188
);
···
8
use structopt::StructOpt;
9
use syncat_stylesheet::Stylesheet;
10
use terminal_size::{terminal_size, Width};
11
+
use unicode_width::UnicodeWidthChar;
12
13
mod dirs;
14
mod printer;
···
18
19
use printer::Printer;
20
use words::Words;
21
+
22
+
fn str_width(s: &str) -> usize {
23
+
strip_ansi_codes(s)
24
+
.chars()
25
+
.flat_map(UnicodeWidthChar::width)
26
+
.sum()
27
+
}
28
29
/// Prints papers in your terminal
30
#[derive(StructOpt, Debug)]
···
121
return;
122
}
123
124
+
let centering = " ".repeat((terminal_width.saturating_sub(width)) / 2);
125
126
let stylesheet = Stylesheet::from_file(dirs::active_color().join("paper.syncat"))
127
.unwrap_or_else(|_| {
···
161
let mut buffer = String::new();
162
let mut indent = None;
163
for word in Words::preserving_whitespace(line) {
164
+
if str_width(&buffer) + str_width(&word) > available_width {
165
println!(
166
"{}{}{}{}{}{}",
167
centering,
168
margin,
169
paper_style.paint(&buffer),
170
+
paper_style.paint(
171
+
" ".repeat(available_width.saturating_sub(str_width(&buffer)))
172
+
),
173
margin,
174
shadow_style.paint(" "),
175
);
···
192
centering,
193
margin,
194
paper_style.paint(&buffer),
195
+
paper_style
196
+
.paint(" ".repeat(available_width.saturating_sub(str_width(&buffer)))),
197
margin,
198
shadow_style.paint(" "),
199
);
+46
-26
src/printer.rs
···
0
1
use crate::table::Table;
2
use crate::termpix;
3
use crate::words::Words;
4
use ansi_term::Style;
5
-
use console::{measure_text_width, AnsiCodeIterator};
6
use image::{self, GenericImageView as _};
7
use pulldown_cmark::{Alignment, CodeBlockKind, Event, Tag};
8
use std::convert::{TryFrom, TryInto};
···
189
let mut all_scopes = scopes.clone();
190
all_scopes.append(&mut extra_scopes.unwrap_or(&[]).to_vec());
191
let style = Self::resolve_scopes(&stylesheet, &all_scopes, Some("prefix"));
192
-
Some((format!("{}", style.paint(&prefix)), prefix.chars().count()))
193
})
194
.fold((String::new(), 0), |(s, c), (s2, c2)| (s + &s2, c + c2))
195
}
···
208
let mut all_scopes = scopes.clone();
209
all_scopes.append(&mut extra_scopes.unwrap_or(&[]).to_vec());
210
let style = Self::resolve_scopes(&stylesheet, &all_scopes, Some("suffix"));
211
-
Some((format!("{}", style.paint(&suffix)), suffix.chars().count()))
212
})
213
.fold((String::new(), 0), |(s, c), (s2, c2)| (s2 + &s, c + c2))
214
}
···
272
self.centering,
273
self.margin,
274
prefix,
275
-
self.paper_style()
276
-
.paint(" ".repeat(self.width - prefix_len - suffix_len)),
0
0
0
0
0
277
suffix,
278
self.margin,
279
self.shadow(),
···
289
self.centering,
290
self.margin,
291
prefix,
292
-
self.style()
293
-
.paint("─".repeat(self.width - prefix_len - suffix_len)),
0
0
0
0
0
294
suffix,
295
self.margin,
296
self.shadow(),
···
304
return;
305
};
306
let (heading, rows) = std::mem::replace(&mut self.table, (vec![], vec![]));
307
-
let available_width = self.width - self.prefix_len() - self.suffix_len();
0
0
0
308
let table_str =
309
Table::new(heading, rows, available_width).print(self.paper_style(), alignments);
310
for line in table_str.lines() {
···
317
line,
318
prefix,
319
self.paper_style()
320
-
.paint(" ".repeat(available_width - measure_text_width(line))),
321
suffix,
322
self.margin,
323
self.shadow(),
···
338
let mut first_prefix = Some(self.prefix2(Some(&[&language_context[..]])));
339
let mut first_suffix = Some(self.suffix2(Some(&[&language_context[..]])));
340
341
-
let available_width = self.width
342
-
- first_prefix.as_ref().unwrap().1
343
-
- first_suffix.as_ref().unwrap().1;
0
344
let buffer = std::mem::replace(&mut self.buffer, String::new());
345
let buffer = if self.opts.syncat {
346
let syncat = Command::new("syncat")
···
368
.lines()
369
.map(|mut line| {
370
let mut output = String::new();
371
-
while line.chars().count() > available_width {
372
let prefix = line.chars().take(available_width).collect::<String>();
373
output = format!("{}{}\n", output, prefix);
374
line = &line[prefix.len()..];
···
377
"{}{}{}\n",
378
output,
379
line,
380
-
" ".repeat(available_width - line.chars().count())
381
)
382
})
383
.collect()
···
401
);
402
403
for line in buffer.lines() {
404
-
let width = measure_text_width(line);
405
let (prefix, _) = self.prefix2(Some(&[&language_context[..]]));
406
let (suffix, _) = self.suffix2(Some(&[&language_context[..]]));
407
print!(
···
424
}
425
println!(
426
"{}{}{}{}",
427
-
style.paint(" ".repeat(available_width - width)),
428
suffix,
429
self.margin,
430
self.shadow(),
···
444
prefix,
445
format!(
446
"{}{}",
447
-
style.paint(" ".repeat(available_width - lang.chars().count())),
448
self.style3(Some(&[&language_context[..]]), Some("lang-tag"))
449
.paint(lang)
450
),
···
489
suffix,
490
self.paper_style().paint(
491
" ".repeat(
492
-
self.width - measure_text_width(&self.content) - prefix_len - suffix_len
0
0
0
493
)
494
),
495
self.margin,
···
529
}
530
let style = self.style();
531
for word in Words::new(s) {
532
-
if measure_text_width(&self.content)
533
-
+ word.len()
534
-
+ self.prefix_len()
535
-
+ self.suffix_len()
536
> self.width
537
{
538
self.flush();
···
542
} else {
543
&word
544
};
545
-
let available_len = self.width - self.prefix_len() - self.suffix_len();
546
-
while measure_text_width(&self.content) + word.len() > available_len {
0
0
0
547
let part = word.chars().take(available_len).collect::<String>();
548
self.target().push_str(&format!("{}", style.paint(&part)));
549
word = &word[part.len()..];
···
640
self.flush();
641
642
if !self.opts.no_images {
643
-
let available_width =
644
-
self.width - self.prefix_len() - self.suffix_len();
0
0
645
match image::open(destination.as_ref()) {
646
Ok(image) => {
647
let (mut width, mut height) = image.dimensions();
···
1
+
use crate::str_width;
2
use crate::table::Table;
3
use crate::termpix;
4
use crate::words::Words;
5
use ansi_term::Style;
6
+
use console::AnsiCodeIterator;
7
use image::{self, GenericImageView as _};
8
use pulldown_cmark::{Alignment, CodeBlockKind, Event, Tag};
9
use std::convert::{TryFrom, TryInto};
···
190
let mut all_scopes = scopes.clone();
191
all_scopes.append(&mut extra_scopes.unwrap_or(&[]).to_vec());
192
let style = Self::resolve_scopes(&stylesheet, &all_scopes, Some("prefix"));
193
+
Some((format!("{}", style.paint(&prefix)), str_width(&prefix)))
194
})
195
.fold((String::new(), 0), |(s, c), (s2, c2)| (s + &s2, c + c2))
196
}
···
209
let mut all_scopes = scopes.clone();
210
all_scopes.append(&mut extra_scopes.unwrap_or(&[]).to_vec());
211
let style = Self::resolve_scopes(&stylesheet, &all_scopes, Some("suffix"));
212
+
Some((format!("{}", style.paint(&suffix)), str_width(&suffix)))
213
})
214
.fold((String::new(), 0), |(s, c), (s2, c2)| (s2 + &s, c + c2))
215
}
···
273
self.centering,
274
self.margin,
275
prefix,
276
+
self.paper_style().paint(
277
+
" ".repeat(
278
+
self.width
279
+
.saturating_sub(prefix_len)
280
+
.saturating_sub(suffix_len)
281
+
)
282
+
),
283
suffix,
284
self.margin,
285
self.shadow(),
···
295
self.centering,
296
self.margin,
297
prefix,
298
+
self.style().paint(
299
+
"─".repeat(
300
+
self.width
301
+
.saturating_sub(prefix_len)
302
+
.saturating_sub(suffix_len)
303
+
)
304
+
),
305
suffix,
306
self.margin,
307
self.shadow(),
···
315
return;
316
};
317
let (heading, rows) = std::mem::replace(&mut self.table, (vec![], vec![]));
318
+
let available_width = self
319
+
.width
320
+
.saturating_sub(self.prefix_len())
321
+
.saturating_sub(self.suffix_len());
322
let table_str =
323
Table::new(heading, rows, available_width).print(self.paper_style(), alignments);
324
for line in table_str.lines() {
···
331
line,
332
prefix,
333
self.paper_style()
334
+
.paint(" ".repeat(available_width.saturating_sub(str_width(line)))),
335
suffix,
336
self.margin,
337
self.shadow(),
···
352
let mut first_prefix = Some(self.prefix2(Some(&[&language_context[..]])));
353
let mut first_suffix = Some(self.suffix2(Some(&[&language_context[..]])));
354
355
+
let available_width = self
356
+
.width
357
+
.saturating_sub(first_prefix.as_ref().unwrap().1)
358
+
.saturating_sub(first_suffix.as_ref().unwrap().1);
359
let buffer = std::mem::replace(&mut self.buffer, String::new());
360
let buffer = if self.opts.syncat {
361
let syncat = Command::new("syncat")
···
383
.lines()
384
.map(|mut line| {
385
let mut output = String::new();
386
+
while str_width(&line) > available_width {
387
let prefix = line.chars().take(available_width).collect::<String>();
388
output = format!("{}{}\n", output, prefix);
389
line = &line[prefix.len()..];
···
392
"{}{}{}\n",
393
output,
394
line,
395
+
" ".repeat(available_width.saturating_sub(str_width(&line)))
396
)
397
})
398
.collect()
···
416
);
417
418
for line in buffer.lines() {
419
+
let width = str_width(line);
420
let (prefix, _) = self.prefix2(Some(&[&language_context[..]]));
421
let (suffix, _) = self.suffix2(Some(&[&language_context[..]]));
422
print!(
···
439
}
440
println!(
441
"{}{}{}{}",
442
+
style.paint(" ".repeat(available_width.saturating_sub(width))),
443
suffix,
444
self.margin,
445
self.shadow(),
···
459
prefix,
460
format!(
461
"{}{}",
462
+
style.paint(" ".repeat(available_width.saturating_sub(str_width(&lang)))),
463
self.style3(Some(&[&language_context[..]]), Some("lang-tag"))
464
.paint(lang)
465
),
···
504
suffix,
505
self.paper_style().paint(
506
" ".repeat(
507
+
self.width
508
+
.saturating_sub(str_width(&self.content))
509
+
.saturating_sub(prefix_len)
510
+
.saturating_sub(suffix_len)
511
)
512
),
513
self.margin,
···
547
}
548
let style = self.style();
549
for word in Words::new(s) {
550
+
if str_width(&self.content) + word.len() + self.prefix_len() + self.suffix_len()
0
0
0
551
> self.width
552
{
553
self.flush();
···
557
} else {
558
&word
559
};
560
+
let available_len = self
561
+
.width
562
+
.saturating_sub(self.prefix_len())
563
+
.saturating_sub(self.suffix_len());
564
+
while str_width(&self.content) + str_width(&word) > available_len {
565
let part = word.chars().take(available_len).collect::<String>();
566
self.target().push_str(&format!("{}", style.paint(&part)));
567
word = &word[part.len()..];
···
658
self.flush();
659
660
if !self.opts.no_images {
661
+
let available_width = self
662
+
.width
663
+
.saturating_sub(self.prefix_len())
664
+
.saturating_sub(self.suffix_len());
665
match image::open(destination.as_ref()) {
666
Ok(image) => {
667
let (mut width, mut height) = image.dimensions();
+87
-60
src/table.rs
···
1
-
use std::io::Write;
2
use ansi_term::Style;
3
-
use pulldown_cmark::Alignment;
4
use console::{measure_text_width, strip_ansi_codes};
5
-
use crate::words::Words;
0
6
7
pub struct Table {
8
titles: Vec<String>,
···
20
}
21
22
pub fn print(self, paper_style: Style, alignment: &[Alignment]) -> String {
23
-
let Table { titles, rows, width } = self;
0
0
0
0
24
25
// NOTE: for now, styling is not supported within tables because that gets really hard
26
-
let titles = titles.iter()
0
27
.map(|title| strip_ansi_codes(title).trim().to_string())
28
.collect::<Vec<_>>();
29
-
let rows = rows.iter()
30
-
.map(|row| row.iter()
31
-
.map(|cell| strip_ansi_codes(cell).trim().to_string())
32
-
.collect()
33
-
)
0
0
34
.collect::<Vec<Vec<_>>>();
35
36
let num_cols = usize::max(
37
titles.len(),
38
-
rows.iter()
39
-
.map(|row| row.len())
40
-
.max()
41
-
.unwrap_or(0)
42
);
43
44
-
let mut title_longest_words = titles.iter()
45
-
.map(|title| Words::new(title)
46
-
.map(|word| word.trim().len())
47
-
.max()
48
-
.unwrap_or(0)
49
-
)
50
-
.collect::<Vec<_>>();
51
-
title_longest_words.resize(num_cols, 0);
52
-
let longest_words = rows.iter()
53
-
.map(|row| row
54
-
.iter()
55
-
.map(|cell| Words::new(cell)
56
.map(|word| word.trim().len())
57
.max()
58
.unwrap_or(0)
59
-
)
60
-
.collect::<Vec<_>>()
61
-
)
0
0
0
0
0
0
0
0
0
0
0
0
62
.fold(title_longest_words.clone(), |mut chars, row| {
63
for i in 0..row.len() {
64
chars[i] = usize::max(chars[i], row[i]);
···
66
chars
67
});
68
69
-
let mut title_chars = titles.iter()
70
-
.map(|title| title
71
-
.lines()
72
-
.map(measure_text_width)
73
-
.max()
74
-
.unwrap_or(0)
75
-
)
76
.collect::<Vec<_>>();
77
title_chars.resize(num_cols, 0);
78
-
let max_chars_per_col = rows.iter()
79
-
.map(|row| row
80
-
.iter()
81
-
.map(|cell| cell
82
-
.lines()
83
-
.map(measure_text_width)
84
-
.max()
85
-
.unwrap_or(0)
86
-
)
87
-
.collect::<Vec<_>>()
88
-
)
89
.fold(title_chars.clone(), |mut chars, row| {
90
for i in 0..row.len() {
91
chars[i] = usize::max(1, usize::max(chars[i], row[i]));
···
101
max_chars_per_col
102
.into_iter()
103
.enumerate()
104
-
.map(|(i, chars)| usize::max(longest_words[i], (max_chars_width as f64 * chars as f64 / total_chars as f64) as usize))
0
0
0
0
0
105
.collect()
106
};
107
if col_widths.iter().sum::<usize>() > max_chars_width {
···
127
}
128
}
129
130
-
fn print_row<W: Write>(w: &mut W, cols: &[usize], alignment: &[Alignment], row: &[String], paper_style: Style) {
131
-
let mut row_words = row
132
-
.into_iter()
133
-
.map(|s| Words::new(s))
134
-
.collect::<Vec<_>>();
0
0
0
135
loop {
136
let mut done = true;
137
write!(w, "{}", paper_style.paint("│")).unwrap();
···
139
let mut line = match words.next() {
140
Some(line) => line.trim().to_string(),
141
None => {
142
-
write!(w, "{}", paper_style.paint(format!(" {: <width$} │", " ", width=cols[i]))).unwrap();
0
0
0
0
0
143
continue;
144
}
145
};
···
159
}
160
line = line.trim().to_string();
161
let padded = if alignment[i] == Alignment::Center {
162
-
format!(" {: ^width$} │", line, width=cols[i])
163
} else if alignment[i] == Alignment::Right {
164
-
format!(" {: >width$} │", line, width=cols[i])
165
} else {
166
-
format!(" {: <width$} │", line, width=cols[i])
167
};
168
write!(w, "{}", paper_style.paint(padded)).unwrap();
169
}
···
174
}
175
}
176
177
-
fn print_separator<W: Write>(w: &mut W, cols: &[usize], mid: char, left: char, cross: char, right: char, paper_style: Style) {
178
-
let line = cols.iter()
0
0
0
0
0
0
0
0
0
179
.map(|width| mid.to_string().repeat(*width))
180
.collect::<Vec<_>>()
181
.join(&format!("{}{}{}", mid, cross, mid));
182
-
write!(w, "{}\n", paper_style.paint(format!("{}{}{}{}{}", left, mid, line, mid, right))).unwrap();
0
0
0
0
0
183
}
···
1
+
use crate::words::Words;
2
use ansi_term::Style;
0
3
use console::{measure_text_width, strip_ansi_codes};
4
+
use pulldown_cmark::Alignment;
5
+
use std::io::Write;
6
7
pub struct Table {
8
titles: Vec<String>,
···
20
}
21
22
pub fn print(self, paper_style: Style, alignment: &[Alignment]) -> String {
23
+
let Table {
24
+
titles,
25
+
rows,
26
+
width,
27
+
} = self;
28
29
// NOTE: for now, styling is not supported within tables because that gets really hard
30
+
let titles = titles
31
+
.iter()
32
.map(|title| strip_ansi_codes(title).trim().to_string())
33
.collect::<Vec<_>>();
34
+
let rows = rows
35
+
.iter()
36
+
.map(|row| {
37
+
row.iter()
38
+
.map(|cell| strip_ansi_codes(cell).trim().to_string())
39
+
.collect()
40
+
})
41
.collect::<Vec<Vec<_>>>();
42
43
let num_cols = usize::max(
44
titles.len(),
45
+
rows.iter().map(|row| row.len()).max().unwrap_or(0),
0
0
0
46
);
47
48
+
let mut title_longest_words = titles
49
+
.iter()
50
+
.map(|title| {
51
+
Words::new(title)
0
0
0
0
0
0
0
0
52
.map(|word| word.trim().len())
53
.max()
54
.unwrap_or(0)
55
+
})
56
+
.collect::<Vec<_>>();
57
+
title_longest_words.resize(num_cols, 0);
58
+
let longest_words = rows
59
+
.iter()
60
+
.map(|row| {
61
+
row.iter()
62
+
.map(|cell| {
63
+
Words::new(cell)
64
+
.map(|word| word.trim().len())
65
+
.max()
66
+
.unwrap_or(0)
67
+
})
68
+
.collect::<Vec<_>>()
69
+
})
70
.fold(title_longest_words.clone(), |mut chars, row| {
71
for i in 0..row.len() {
72
chars[i] = usize::max(chars[i], row[i]);
···
74
chars
75
});
76
77
+
let mut title_chars = titles
78
+
.iter()
79
+
.map(|title| title.lines().map(measure_text_width).max().unwrap_or(0))
0
0
0
0
80
.collect::<Vec<_>>();
81
title_chars.resize(num_cols, 0);
82
+
let max_chars_per_col = rows
83
+
.iter()
84
+
.map(|row| {
85
+
row.iter()
86
+
.map(|cell| cell.lines().map(measure_text_width).max().unwrap_or(0))
87
+
.collect::<Vec<_>>()
88
+
})
0
0
0
0
89
.fold(title_chars.clone(), |mut chars, row| {
90
for i in 0..row.len() {
91
chars[i] = usize::max(1, usize::max(chars[i], row[i]));
···
101
max_chars_per_col
102
.into_iter()
103
.enumerate()
104
+
.map(|(i, chars)| {
105
+
usize::max(
106
+
longest_words[i],
107
+
(max_chars_width as f64 * chars as f64 / total_chars as f64) as usize,
108
+
)
109
+
})
110
.collect()
111
};
112
if col_widths.iter().sum::<usize>() > max_chars_width {
···
132
}
133
}
134
135
+
fn print_row<W: Write>(
136
+
w: &mut W,
137
+
cols: &[usize],
138
+
alignment: &[Alignment],
139
+
row: &[String],
140
+
paper_style: Style,
141
+
) {
142
+
let mut row_words = row.into_iter().map(|s| Words::new(s)).collect::<Vec<_>>();
143
loop {
144
let mut done = true;
145
write!(w, "{}", paper_style.paint("│")).unwrap();
···
147
let mut line = match words.next() {
148
Some(line) => line.trim().to_string(),
149
None => {
150
+
write!(
151
+
w,
152
+
"{}",
153
+
paper_style.paint(format!(" {: <width$} │", " ", width = cols[i]))
154
+
)
155
+
.unwrap();
156
continue;
157
}
158
};
···
172
}
173
line = line.trim().to_string();
174
let padded = if alignment[i] == Alignment::Center {
175
+
format!(" {: ^width$} │", line, width = cols[i])
176
} else if alignment[i] == Alignment::Right {
177
+
format!(" {: >width$} │", line, width = cols[i])
178
} else {
179
+
format!(" {: <width$} │", line, width = cols[i])
180
};
181
write!(w, "{}", paper_style.paint(padded)).unwrap();
182
}
···
187
}
188
}
189
190
+
fn print_separator<W: Write>(
191
+
w: &mut W,
192
+
cols: &[usize],
193
+
mid: char,
194
+
left: char,
195
+
cross: char,
196
+
right: char,
197
+
paper_style: Style,
198
+
) {
199
+
let line = cols
200
+
.iter()
201
.map(|width| mid.to_string().repeat(*width))
202
.collect::<Vec<_>>()
203
.join(&format!("{}{}{}", mid, cross, mid));
204
+
write!(
205
+
w,
206
+
"{}\n",
207
+
paper_style.paint(format!("{}{}{}{}{}", left, mid, line, mid, right))
208
+
)
209
+
.unwrap();
210
}
+11
-9
src/words.rs
···
44
self.position += start;
45
if start == chars.len() {
46
if chars.len() == 0 {
47
-
return None
48
} else if self.preserve_whitespace {
49
-
return Some(chars[..].into_iter().collect())
50
} else {
51
-
return Some(" ".to_string())
52
}
53
}
54
let mut len = 0;
55
-
while start+len < chars.len() {
56
-
if chars[start+len] == '-' {
57
len += 1;
58
break;
59
}
60
-
if chars[start+len].is_whitespace() {
61
break;
62
}
63
len += 1;
···
65
self.position += len;
66
if chars[0].is_whitespace() {
67
if self.preserve_whitespace {
68
-
return Some(chars[0..start+len].into_iter().collect::<String>())
69
} else {
70
-
return Some(String::from(" ") + &chars[start..start+len].into_iter().collect::<String>())
0
0
71
}
72
} else {
73
-
return Some(chars[start..start+len].into_iter().collect::<String>())
74
}
75
}
76
}
···
44
self.position += start;
45
if start == chars.len() {
46
if chars.len() == 0 {
47
+
return None;
48
} else if self.preserve_whitespace {
49
+
return Some(chars[..].into_iter().collect());
50
} else {
51
+
return Some(" ".to_string());
52
}
53
}
54
let mut len = 0;
55
+
while start + len < chars.len() {
56
+
if chars[start + len] == '-' {
57
len += 1;
58
break;
59
}
60
+
if chars[start + len].is_whitespace() {
61
break;
62
}
63
len += 1;
···
65
self.position += len;
66
if chars[0].is_whitespace() {
67
if self.preserve_whitespace {
68
+
return Some(chars[0..start + len].into_iter().collect::<String>());
69
} else {
70
+
return Some(
71
+
String::from(" ") + &chars[start..start + len].into_iter().collect::<String>(),
72
+
);
73
}
74
} else {
75
+
return Some(chars[start..start + len].into_iter().collect::<String>());
76
}
77
}
78
}