1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
//! # term-snip //! //! `term-snip` A small utility crate using https://crates.io/crates/console //! to write to stdout but limited to a given number of lines. //! The oldest line is removed when writing a new line. //! //!## Usage //! //!From *examples/five.rs*: //! //!```rust //!use term_snip::TermSnip; //! //!use std::{thread, time}; //! //!/// A simple example writing 15 lines to stdout but only showing //!/// a maximum of five lines. //!fn main() { //! let half_sec = time::Duration::from_millis(500); //! //! let mut term = TermSnip::new(5); //! for n in 1..15 { //! term.write_line(&format!("{} - line number {}", n, n)).unwrap(); //! //! // just to slow down for demonstration //! thread::sleep(half_sec); //! } //!} //! //!``` //! //! //!## Screenshot //! //!Screenshot showing above example in action //! //! //! //!Clearing the written lines afterwards (```cargo run --example clear```) //! //! //! use std::{io, usize}; use console::Term; /// Representation of a terminal. pub struct TermSnip { term: Term, limit: usize, lines: Vec<String>, } impl TermSnip{ /// Creates a TermSnip wich limits output lines to the given limit. /// /// # Example /// /// ```rust /// let mut term = TermSnip::new(5); /// ``` /// pub fn new(limit: usize) -> TermSnip { TermSnip{ term: Term::stdout(), limit, lines: Vec::new()} } /// Writes a line to the terminal (stdout). pub fn write_line(&mut self, text: &str) -> io::Result<()> { // split text into multiple text when it is longer than a line let line_len:usize = self.term.size().1.into(); // if the char count of the text is less than the line length // just write it and return if text.chars().count() < line_len { self.term_write_line(text)?; return Ok(()) } // when this code line is reached the text is larger then the line length // and must be splitted to be written as multiple lines let mut last_text = text; while last_text.chars().count() >= line_len { let (first, last) = last_text.split_at(line_len); last_text = last; self.term_write_line(first)?; } self.term_write_line(last_text)?; Ok(()) } /// Delegates the writing to console::Term and manages the line limit. fn term_write_line(&mut self, text: &str) -> io::Result<()> { self.lines.push(text.to_string()); if self.lines.len() > self.limit { self.term.move_cursor_up(self.limit)?; self.lines.remove(0); for line in &self.lines { self.term.write_line(line)?; } } else { self.term.write_line(text)?; } Ok(()) } /// Clear the lines written with the TermSnip instance pub fn clear_lines(&mut self) -> io::Result<()> { let len = &self.lines.len(); self.term.move_cursor_up(*len)?; for _n in 0..*len { self.term.clear_line()?; self.term.move_cursor_down(1)?; } self.term.move_cursor_up(*len+1)?; self.lines.clear(); self.term.move_cursor_down(1)?; Ok(()) } }