1use linuxutils_common::man::ManContent;
2
3pub const MAN: ManContent = ManContent::empty();
4
5use clap::Parser;
6use std::{
7 io::{self, BufRead, Write},
8 process::ExitCode,
9};
10
11#[derive(Parser)]
13#[command(name = "line", version, about)]
14pub struct Args {}
15
16pub fn run(_args: Args) -> ExitCode {
17 let stdin = io::stdin();
18 let reader = stdin.lock();
19 let mut stdout = io::stdout().lock();
20
21 match line(reader, &mut stdout) {
22 Ok(true) => ExitCode::SUCCESS,
23 Ok(false) => ExitCode::from(1),
24 Err(e) => {
25 eprintln!("line: {e}");
26 ExitCode::FAILURE
27 }
28 }
29}
30
31pub fn line(
35 mut reader: impl BufRead,
36 writer: &mut impl Write,
37) -> io::Result<bool> {
38 let mut buf = String::new();
39 let bytes_read = reader.read_line(&mut buf)?;
40
41 let line = buf.trim_end_matches('\n').trim_end_matches('\r');
43 writeln!(writer, "{line}")?;
44
45 Ok(bytes_read > 0)
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn reads_first_line_only() {
54 let input = b"hello\nworld\n";
55 let mut output = Vec::new();
56 let ok = line(&input[..], &mut output).unwrap();
57 assert!(ok);
58 assert_eq!(output, b"hello\n");
59 }
60
61 #[test]
62 fn eof_returns_false() {
63 let input = b"";
64 let mut output = Vec::new();
65 let ok = line(&input[..], &mut output).unwrap();
66 assert!(!ok);
67 assert_eq!(output, b"\n");
68 }
69
70 #[test]
71 fn line_without_newline() {
72 let input = b"hello";
73 let mut output = Vec::new();
74 let ok = line(&input[..], &mut output).unwrap();
75 assert!(ok);
76 assert_eq!(output, b"hello\n");
77 }
78}