/rust/registry/src/index.crates.io-1949cf8c6b5b557f/argh_shared-0.1.10/src/lib.rs
Line | Count | Source |
1 | | // Copyright (c) 2020 Google LLC All rights reserved. |
2 | | // Use of this source code is governed by a BSD-style |
3 | | // license that can be found in the LICENSE file. |
4 | | |
5 | | //! Shared functionality between argh_derive and the argh runtime. |
6 | | //! |
7 | | //! This library is intended only for internal use by these two crates. |
8 | | |
9 | | /// Information about a particular command used for output. |
10 | | pub struct CommandInfo<'a> { |
11 | | /// The name of the command. |
12 | | pub name: &'a str, |
13 | | /// A short description of the command's functionality. |
14 | | pub description: &'a str, |
15 | | } |
16 | | |
17 | | pub const INDENT: &str = " "; |
18 | | const DESCRIPTION_INDENT: usize = 20; |
19 | | const WRAP_WIDTH: usize = 80; |
20 | | |
21 | | /// Write command names and descriptions to an output string. |
22 | 0 | pub fn write_description(out: &mut String, cmd: &CommandInfo<'_>) { |
23 | 0 | let mut current_line = INDENT.to_string(); |
24 | 0 | current_line.push_str(cmd.name); |
25 | | |
26 | 0 | if cmd.description.is_empty() { |
27 | 0 | new_line(&mut current_line, out); |
28 | 0 | return; |
29 | 0 | } |
30 | | |
31 | 0 | if !indent_description(&mut current_line) { |
32 | 0 | // Start the description on a new line if the flag names already |
33 | 0 | // add up to more than DESCRIPTION_INDENT. |
34 | 0 | new_line(&mut current_line, out); |
35 | 0 | } |
36 | | |
37 | 0 | let mut words = cmd.description.split(' ').peekable(); |
38 | 0 | while let Some(first_word) = words.next() { |
39 | 0 | indent_description(&mut current_line); |
40 | 0 | current_line.push_str(first_word); |
41 | | |
42 | 0 | 'inner: while let Some(&word) = words.peek() { |
43 | 0 | if (char_len(¤t_line) + char_len(word) + 1) > WRAP_WIDTH { |
44 | 0 | new_line(&mut current_line, out); |
45 | 0 | break 'inner; |
46 | 0 | } else { |
47 | 0 | // advance the iterator |
48 | 0 | let _ = words.next(); |
49 | 0 | current_line.push(' '); |
50 | 0 | current_line.push_str(word); |
51 | 0 | } |
52 | | } |
53 | | } |
54 | 0 | new_line(&mut current_line, out); |
55 | 0 | } |
56 | | |
57 | | // Indent the current line in to DESCRIPTION_INDENT chars. |
58 | | // Returns a boolean indicating whether or not spacing was added. |
59 | 0 | fn indent_description(line: &mut String) -> bool { |
60 | 0 | let cur_len = char_len(line); |
61 | 0 | if cur_len < DESCRIPTION_INDENT { |
62 | 0 | let num_spaces = DESCRIPTION_INDENT - cur_len; |
63 | 0 | line.extend(std::iter::repeat(' ').take(num_spaces)); |
64 | 0 | true |
65 | | } else { |
66 | 0 | false |
67 | | } |
68 | 0 | } |
69 | | |
70 | 0 | fn char_len(s: &str) -> usize { |
71 | 0 | s.chars().count() |
72 | 0 | } |
73 | | |
74 | | // Append a newline and the current line to the output, |
75 | | // clearing the current line. |
76 | 0 | fn new_line(current_line: &mut String, out: &mut String) { |
77 | 0 | out.push('\n'); |
78 | 0 | out.push_str(current_line); |
79 | 0 | current_line.truncate(0); |
80 | 0 | } |