1use libc;
45use std::collections::VecDeque;
46use std::fs::File;
47use std::io;
48use std::io::{Read, Write};
49use std::os::unix::io::RawFd;
50use std::path::Path;
51use termios::*;
52
53fn get_stdin_fd() -> RawFd {
54 libc::STDIN_FILENO
55}
56
57fn get_stdout_fd() -> RawFd {
58 libc::STDOUT_FILENO
59}
60
61fn get_col() -> u16 {
62 let mut winsize = libc::winsize {
63 ws_row: 0,
64 ws_col: 0,
65 ws_xpixel: 0,
66 ws_ypixel: 0,
67 };
68 if unsafe { libc::ioctl(get_stdout_fd(), libc::TIOCGWINSZ, &mut winsize) } == 0 {
69 winsize.ws_col
70 } else {
71 80
72 }
73}
74
75mod keys {
76 pub(crate) const CTRL_A: u8 = 1;
77 pub(crate) const CTRL_B: u8 = 2;
78 pub(crate) const CTRL_C: u8 = 3;
79 pub(crate) const CTRL_D: u8 = 4;
80 pub(crate) const CTRL_E: u8 = 5;
81 pub(crate) const CTRL_F: u8 = 6;
82 pub(crate) const CTRL_H: u8 = 8;
83 pub(crate) const CTRL_I: u8 = 9;
84 pub(crate) const CTRL_J: u8 = 10;
85 pub(crate) const CTRL_K: u8 = 11;
86 pub(crate) const CTRL_L: u8 = 12;
87 pub(crate) const CTRL_M: u8 = 13;
88 pub(crate) const ESC: u8 = 27;
89 pub(crate) const ONE: u8 = 49;
90 pub(crate) const TWO: u8 = 50;
91 pub(crate) const THREE: u8 = 51;
92 pub(crate) const FOUR: u8 = 52;
93 pub(crate) const FIVE: u8 = 53;
94 pub(crate) const SIX: u8 = 54;
95 pub(crate) const A: u8 = 65;
96 pub(crate) const B: u8 = 66;
97 pub(crate) const C: u8 = 67;
98 pub(crate) const D: u8 = 68;
99 pub(crate) const LEFT_BRACKET: u8 = 91;
101 pub(crate) const BACKSPACE: u8 = 127;
102}
103
104pub type Completion = fn(&Vec<u8>, &mut Vec<Vec<u8>>);
106
107pub struct History {
109 commands: VecDeque<Vec<u8>>,
110 position: usize,
111 limit: usize,
113}
114
115impl History {
116 pub fn new(limit: usize) -> Self {
118 History {
119 commands: VecDeque::new(),
120 position: 0,
121 limit,
122 }
123 }
124
125 pub(crate) fn next(&mut self) -> Option<&Vec<u8>> {
127 if self.commands.len() == 0 || self.position == self.commands.len() {
128 None
129 } else {
130 self.position += 1;
131 self.commands.get(self.position)
132 }
133 }
134
135 pub(crate) fn prev(&mut self) -> Option<&Vec<u8>> {
137 if self.commands.len() == 0 || self.position == 0 {
138 None
139 } else {
140 self.position -= 1;
141 self.commands.get(self.position)
142 }
143 }
144
145 fn _append(&mut self, history: Vec<u8>) {
146 if self.limit > 0 && self.commands.len() == self.limit {
147 self.commands.pop_front();
148 }
149 self.commands.push_back(history);
150 }
151
152 pub fn append(&mut self, history: Vec<u8>) {
154 self._append(history);
155 self.position = self.commands.len();
156 }
157
158 pub fn load<P: AsRef<Path>>(&mut self, file_path: P) -> io::Result<()> {
160 let mut file = match File::open(file_path) {
161 Ok(file) => file,
162 Err(e) if e.kind() == io::ErrorKind::NotFound => return Ok(()),
163 Err(e) => return Err(e),
164 };
165 let mut buffer = vec![0; 4096];
166 let mut cmd = vec![0; 0];
167 loop {
168 let n = file.read(&mut buffer)?;
169 if n == 0 {
170 break;
171 }
172 for c in buffer[..n].iter() {
173 if *c == b'\n' && cmd.len() > 0 {
174 self._append(cmd);
175 cmd = vec![0; 0];
176 continue;
177 }
178 cmd.push(*c);
179 }
180 }
181 if cmd.len() > 0 {
182 self._append(cmd);
183 }
184 if self.commands.len() > 0 {
185 self.position = self.commands.len();
186 }
187 Ok(())
188 }
189
190 pub fn save<P: AsRef<Path>>(&mut self, file_path: P) -> io::Result<()> {
192 File::create(file_path).and_then(|mut file| {
193 for cmd in self.commands.iter() {
194 file.write_all(cmd).and(file.write_all(b"\n"))?;
195 }
196 file.flush()
197 })
198 }
199}
200
201struct Line<'a> {
202 backup: Termios,
203 position: usize,
204 buffer: &'a mut Vec<u8>,
205 prompt: &'a [u8],
206 completion: &'a Option<Completion>,
207 multi: bool,
208 row: usize,
209 history: &'a mut History,
210}
211
212impl<'a> Line<'a> {
213 fn new(
214 buffer: &'a mut Vec<u8>,
215 prompt: &'a [u8],
216 completion: &'a Option<Completion>,
217 multi: bool,
218 history: &'a mut History,
219 ) -> Self {
220 let backup = Termios::from_fd(get_stdin_fd()).unwrap();
221 Line::enable_raw_mode().unwrap();
222 Line {
223 backup,
224 position: 0,
225 buffer,
226 prompt,
227 completion,
228 multi,
229 row: 0,
230 history,
231 }
232 }
233
234 fn enable_raw_mode() -> io::Result<()> {
235 let fd = get_stdin_fd();
236 Termios::from_fd(fd).and_then(|mut termios| {
237 termios.c_iflag &= !(BRKINT | INPCK | ISTRIP | ICRNL | IXON);
238 termios.c_oflag &= !OPOST;
239 termios.c_cflag |= CS8;
240 termios.c_lflag &= !(ECHO | ICANON | IEXTEN | ISIG);
241 termios.c_cc[VMIN] = 1;
242 termios.c_cc[VTIME] = 0;
243 tcsetattr(fd, TCSANOW, &termios).and(tcflush(fd, TCIOFLUSH))
244 })
245 }
246
247 fn disable_raw_mode(&self) -> io::Result<()> {
248 let fd = get_stdin_fd();
249 tcsetattr(fd, TCSANOW, &self.backup).and(tcflush(fd, TCIOFLUSH))
250 }
251
252 fn refresh_single_line(&self) -> io::Result<()> {
253 let mut stdout = io::stdout();
254 stdout
255 .write_all(
256 &[
257 b"\x1b[0G\x1b[K",
258 self.prompt,
259 &self.buffer[..],
260 format!("\r\x1b[{}C", self.position + self.prompt.len()).as_bytes(),
261 ]
262 .concat(),
263 )
264 .and(stdout.flush())
265 }
266
267 fn refresh_multi_line(&mut self) -> io::Result<()> {
268 let col = get_col() as usize;
269 let mut stdout = io::stdout();
270 if self.row == 0 {
271 stdout.write_all(b"\x1b[0G\x1b[J")?;
272 } else {
273 stdout.write_all(format!("\x1b[0G\x1b[{}A\x1b[J", self.row).as_bytes())?;
274 }
275 let mut cnt = 0;
276 let mut row: usize = 0;
277 for c in self.prompt.iter().chain(self.buffer.iter()) {
278 stdout.write_all(&[*c])?;
279 cnt += 1;
280 if cnt == col {
281 stdout.write_all(b"\n\x1b[0G")?;
282 cnt = 0;
283 row += 1;
284 }
285 }
286 stdout.write_all(b"\r")?;
287 if row == 0 {
288 stdout.write_all(b"\x1b[0G")?;
289 } else {
290 stdout.write_all(format!("\x1b[0G\x1b[{}A", row).as_bytes())?;
291 }
292 let pos = self.prompt.len() + self.position;
293 let m = pos % col;
294 self.row = pos / col;
295 if self.row > 0 {
296 stdout.write_all(format!("\x1b[{}B", self.row).as_bytes())?;
297 }
298 if m > 0 {
299 stdout.write_all(format!("\x1b[{}C", m).as_bytes())?;
300 }
301 stdout.flush()?;
302 Ok(())
303 }
304
305 fn refresh_line(&mut self) -> io::Result<()> {
306 if self.multi {
307 self.refresh_multi_line()
308 } else {
309 self.refresh_single_line()
310 }
311 }
312
313 fn completion(&mut self, callback: &Completion) -> io::Result<u8> {
314 let mut completions = Vec::new();
315 callback(self.buffer, &mut completions);
316 if completions.len() == 0 {
317 return Ok(0);
318 }
319 let mut stdin = io::stdin();
320 let bk = self.buffer.clone();
321 let mut buf = vec![0; 1];
322 loop {
323 for comp in completions.iter() {
324 self.buffer.clear();
325 self.buffer.extend(comp);
326 self.position = self.buffer.len();
327 self.refresh_line()?;
328
329 let n = stdin.read(&mut buf)?;
330 assert_eq!(n, 1);
331
332 match buf[0] {
333 keys::CTRL_I => {
334 continue;
335 }
336 keys::ESC => {
337 self.buffer.clear();
338 self.buffer.extend(&bk);
339 self.position = self.buffer.len();
340 self.refresh_line()?;
341 return Ok(buf[0]);
342 }
343 _ => {
344 return Ok(buf[0]);
345 }
346 }
347 }
348 }
349 }
350
351 fn fetch(mut self) -> io::Result<()> {
352 let mut stdin = io::stdin();
353
354 self.refresh_line()?;
355
356 let mut buf = vec![0; 1];
357 let mut tmp = vec![0; 0];
358 let mut used = false;
359 loop {
360 let n = stdin.read(&mut buf)?;
361 assert_eq!(n, 1);
362
363 if buf[0] == keys::ESC {
364 let mut buf2 = vec![0; 3];
365 let n = stdin.read(&mut buf2[0..1])?;
366 assert_eq!(n, 1);
367 match buf2[0] {
368 keys::LEFT_BRACKET => {
370 let n = stdin.read(&mut buf2[1..2])?;
371 assert_eq!(n, 1);
372 match buf2[1] {
373 keys::ONE => {
375 let _ = stdin.read(&mut buf2[2..3])?;
376 buf[0] = keys::CTRL_A;
377 }
378 keys::TWO => {
380 let _ = stdin.read(&mut buf2[2..3])?;
381 continue;
382 }
383 keys::THREE => {
385 let _ = stdin.read(&mut buf2[2..3])?;
386 if self.position < self.buffer.len() {
387 buf[0] = keys::CTRL_D;
388 } else {
389 continue;
390 }
391 }
392 keys::FOUR => {
394 let _ = stdin.read(&mut buf2[2..3])?;
395 buf[0] = keys::CTRL_E;
396 }
397 keys::FIVE => {
399 let _ = stdin.read(&mut buf2[2..3])?;
400 continue;
401 }
402 keys::SIX => {
404 let _ = stdin.read(&mut buf2[2..3])?;
405 continue;
406 }
407 keys::A => match self.history.prev() {
409 Some(cmd) => {
410 if !used {
411 tmp.extend(&self.buffer[..]);
412 used = true;
413 }
414 self.buffer.clear();
415 self.buffer.extend(cmd);
416 self.position = self.buffer.len();
417 self.refresh_line()?;
418 continue;
419 }
420 None => {
421 continue;
422 }
423 },
424 keys::B => match self.history.next() {
426 Some(cmd) => {
427 self.buffer.clear();
428 self.buffer.extend(cmd);
429 self.position = self.buffer.len();
430 self.refresh_line()?;
431 continue;
432 }
433 None => {
434 if used {
435 used = false;
436 self.buffer.clear();
437 self.buffer.extend(&tmp[..]);
438 self.position = self.buffer.len();
439 tmp.clear();
440 self.refresh_line()?;
441 }
442 continue;
443 }
444 },
445 keys::C => {
447 buf[0] = keys::CTRL_F;
448 }
449 keys::D => {
451 buf[0] = keys::CTRL_B;
452 }
453 _ => {
454 buf[0] = buf2[1];
455 }
456 }
457 }
458 _ => {
459 buf[0] = buf2[0];
462 }
463 }
464 }
465
466 if buf[0] == keys::CTRL_I {
468 match self.completion {
469 Some(callback) => {
470 let c = self.completion(callback)?;
471 if c == 0 {
472 continue;
473 }
474 buf[0] = c;
475 }
476 None => continue,
477 }
478 }
479
480 match buf[0] {
481 keys::CTRL_A => {
483 self.position = 0;
484 self.refresh_line()?;
485 }
486 keys::CTRL_B => {
488 if self.position == 0 {
489 continue;
490 }
491 self.position -= 1;
492 self.refresh_line()?;
493 }
494 keys::CTRL_C => {
496 self.disable_raw_mode()?;
497 return Err(io::ErrorKind::Interrupted.into());
498 }
499 keys::CTRL_D => {
500 if self.buffer.len() == 0 {
502 self.disable_raw_mode()?;
503 return Err(io::ErrorKind::Interrupted.into());
504 } else if self.position < self.buffer.len() {
506 self.buffer.remove(self.position);
507 self.refresh_line()?;
508 }
509 }
510 keys::CTRL_E => {
512 self.position = self.buffer.len();
513 self.refresh_line()?;
514 }
515 keys::CTRL_F => {
517 if self.position == self.buffer.len() {
518 continue;
519 }
520 self.position += 1;
521 self.refresh_line()?;
522 }
523 keys::CTRL_H | keys::BACKSPACE => {
524 if self.position == 0 || self.buffer.len() == 0 {
525 continue;
526 }
527 self.position -= 1;
528 self.buffer.remove(self.position);
529 self.refresh_line()?;
530 }
531 keys::CTRL_J | keys::CTRL_M => {
533 break;
534 }
535 keys::CTRL_K => {
536 self.buffer.truncate(self.position);
537 self.refresh_line()?;
538 }
539 keys::CTRL_L => {
540 let mut stdout = io::stdout();
541 stdout.write_all(b"\x1b[H\x1b[2J")?;
542 self.refresh_line()?;
543 }
544 keys::ESC => {
546 continue;
547 }
548 _ => {
549 if self.position < self.buffer.len() {
550 self.buffer[self.position] = buf[0];
551 } else {
552 self.buffer.extend(&buf);
553 }
554 self.position += 1;
555 self.refresh_line()?;
556 }
557 }
558 }
559 let mut stdout = io::stdout();
560 stdout
561 .write_all(format!("\n\x1b[{}D", self.prompt.len() + self.position).as_bytes())
562 .and(stdout.flush())
563 }
564}
565
566impl<'a> Drop for Line<'a> {
567 fn drop(&mut self) {
568 self.disable_raw_mode().unwrap()
569 }
570}
571
572pub struct Interaction {
574 prompt: Vec<u8>,
575 completion: Option<Completion>,
576 pub multi: bool,
578 history: History,
579}
580
581impl Interaction {
582 pub fn new(
584 prompt: Vec<u8>,
585 completion: Option<Completion>,
586 multi: bool,
587 limit: usize,
588 ) -> Self {
589 Interaction {
590 prompt,
591 completion,
592 multi,
593 history: History::new(limit),
594 }
595 }
596
597 pub fn from(prompt: &[u8]) -> Self {
599 Interaction::new(prompt.to_vec(), None, true, 0)
600 }
601
602 pub fn from_str(prompt: &str) -> Self {
604 Interaction::new(prompt.as_bytes().to_vec(), None, true, 0)
605 }
606
607 pub fn line(&mut self) -> io::Result<Vec<u8>> {
609 let mut buffer = vec![0; 0];
610 Line::new(
611 &mut buffer,
612 &self.prompt,
613 &self.completion,
614 self.multi,
615 &mut self.history,
616 )
617 .fetch()
618 .and_then(|_| {
619 if buffer.len() > 0 {
620 self.history.append(buffer.clone());
621 }
622 Ok(buffer)
623 })
624 }
625
626 pub fn set_prompt(&mut self, prompt: &[u8]) {
628 self.prompt = prompt.to_vec();
629 }
630
631 pub fn set_completion(&mut self, completion: Completion) {
633 self.completion = Some(completion);
634 }
635
636 pub fn set_history_limit(&mut self, limit: usize) {
638 self.history = History::new(limit);
639 }
640
641 pub fn load_history<P: AsRef<Path>>(&mut self, file_path: P) -> io::Result<()> {
643 self.history.load(file_path)
644 }
645
646 pub fn save_history<P: AsRef<Path>>(&mut self, file_path: P) -> io::Result<()> {
648 self.history.save(file_path)
649 }
650}
651
652pub struct InteractionBuilder {
671 prompt: Vec<u8>,
672 completion: Option<Completion>,
673 multi: bool,
674 history: History,
675}
676
677impl InteractionBuilder {
678 pub fn new() -> Self {
680 InteractionBuilder {
681 prompt: vec![0; 0],
682 completion: None,
683 multi: true,
684 history: History::new(0),
685 }
686 }
687
688 pub fn build(self) -> Interaction {
690 Interaction {
691 prompt: self.prompt,
692 completion: self.completion,
693 multi: self.multi,
694 history: self.history,
695 }
696 }
697
698 pub fn prompt(mut self, prompt: &[u8]) -> Self {
700 self.prompt = prompt.to_vec();
701 self
702 }
703
704 pub fn prompt_str(mut self, prompt: &str) -> Self {
706 self.prompt = prompt.as_bytes().to_vec();
707 self
708 }
709
710 pub fn completion(mut self, completion: Completion) -> Self {
712 self.completion = Some(completion);
713 self
714 }
715
716 pub fn mode(mut self, multi: bool) -> Self {
718 self.multi = multi;
719 self
720 }
721
722 pub fn history_limit(mut self, limit: usize) -> Self {
724 self.history = History::new(limit);
725 self
726 }
727
728 pub fn load_history<P: AsRef<Path>>(mut self, file_path: P) -> io::Result<Self> {
730 self.history.load(file_path).and(Ok(self))
731 }
732}