1extern crate pancurses;
2use pancurses::{Window, Input, initscr};
3
4pub struct Terminal {
14 win: Window,
15 layers: LayerArrangement
16}
17
18struct LayerArrangement {
19 layer_stack: Vec<Layer2D>
20}
21
22#[derive(Clone, Debug)]
56pub struct Layer {
57 pub posx: i32,
58 pub posy: i32,
59 pub inner_content: String,
60 content: String,
61 length: usize
62}
63
64#[derive(Clone, Debug)]
102pub struct Layer2D {
103 pub posx: i32,
104 pub posy: i32,
105 pub length: usize,
106 pub height: usize,
107 pub layers: Vec<Layer>,
108 char_count: usize,
109 stack_loc: i32
110}
111
112#[derive(Debug, PartialEq)]
113pub enum Key {
114 Alpha(char),
115 Enter,
116 Space,
117 Backspace,
118 ArrowUp,
119 ArrowDown,
120 ArrowLeft,
121 ArrowRight,
122 F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11,F12
123}
124
125
126impl Layer {
127 pub fn new(posx: i32, posy: i32) -> Layer {
129 Layer { posx, posy, content: String::new(), inner_content: String::new(), length: 0 }
130 }
131
132 pub fn get_content(&self) -> String {
134 self.content.clone()
135 }
136
137 pub fn set_content(&mut self, c: String) -> &mut Layer {
139 self.content = c;
140 if self.content.len() > self.length {
141 self.length = self.content.len();
142 }
143 self
144 }
145
146 pub fn inner_to_outer(&mut self) {
148 self.set_content(self.inner_content.clone());
149 }
150
151 pub fn shrink(&mut self) {
153 self.length = self.content.len();
154 }
155}
156
157impl Layer2D {
158 pub fn new(posx: i32, posy: i32, length: usize, height: usize, populator: Layer) -> Layer2D {
161 let mut l = Layer2D { posx, posy, length, height, layers: vec![], char_count: 0, stack_loc: 0 };
162 l.populate(populator);
163 l
164 }
165
166 pub fn populate(&mut self, populator: Layer) {
168 let n = populator.clone();
169 self.char_count = n.get_content().len();
170 self.layers = std::iter::repeat(n).take(self.length * self.height)
171 .enumerate()
172 .map(|(i, l)| {
173 let mut x = l.clone();
174 x.posx = (i % self.length * self.char_count) as i32;
175 x.posy = ((i / self.length) as f64).floor() as i32;
176 x
177 }).collect();
178 }
179
180 pub fn index(&mut self, x: usize, y: usize) -> &mut Layer {
182 &mut self.layers[x + y * self.length]
183 }
184
185 pub fn get(&self, x: usize, y: usize) -> &Layer {
187 &self.layers[x + y * self.length]
188 }
189}
190
191impl LayerArrangement {
192 fn new() -> LayerArrangement {
193 LayerArrangement { layer_stack: vec![] }
194 }
195
196 fn push(&mut self, layer: Layer2D) -> &mut Layer2D {
197 self.layer_stack.push(layer);
198 self.layer_stack.last_mut().unwrap()
199 }
200
201 fn pop(&mut self) -> Option<Layer2D> {
202 self.layer_stack.pop()
203 }
204}
205
206fn locate_idx(len: usize, l: i32) -> usize {
208 match l <= 0 {
209 false => l as usize,
210 true => ((len - 1) as i32 + l) as usize
211 }
212}
213
214impl Terminal {
215
216 pub fn new() -> Terminal {
218 let win = initscr();
219 win.keypad(true);
220 Terminal { win, layers: LayerArrangement::new() }
221 }
222
223 pub fn add_layer(&mut self, layer: Layer) -> &mut Layer {
225 let mut r2d = Layer2D::new(layer.posx, layer.posy, 1, 1, layer);
226 r2d.stack_loc = -(self.layers.layer_stack.len() as i32);
227 self.layers.push(r2d).index(0, 0)
228 }
229
230 pub fn add_layer2d(&mut self, layer: Layer2D) -> &mut Layer2D {
232 let mut r = layer.clone();
233 r.stack_loc = -(self.layers.layer_stack.len() as i32);
234 self.layers.push(layer)
235 }
236
237 pub fn refresh(&self) {
239 self.win.refresh();
240 let here = self.raw_posxy();
241 for l2d in &self.layers.layer_stack {
242 self.draw_layer2d(l2d);
243 }
244 self.raw_move(here.0, here.1);
245 self.win.refresh();
246 }
247
248 pub fn layer_front(&mut self) -> &mut Layer2D {
250 self.layers.layer_stack.last_mut().unwrap()
251 }
252
253 pub fn layer_back(&mut self) -> &mut Layer2D {
255 self.layers.layer_stack.first_mut().unwrap()
256 }
257
258 pub fn layer_swap(&mut self, a: i32, b: i32) {
260 let len = self.layers.layer_stack.len();
261 self.layers.layer_stack.swap(locate_idx(len, a), locate_idx(len, b));
262 }
263
264 pub fn layer_locate(&mut self, l: i32) -> &mut Layer2D {
279 let len = self.layers.layer_stack.len();
280 &mut self.layers.layer_stack[locate_idx(len, l)]
281 }
282
283 pub fn draw_layer(&self, layer: &Layer) {
285 self.raw_move(layer.posx, layer.posy);
286 self.raw_out_static(" ".repeat(layer.length)); self.raw_out(layer.get_content());
288 }
289
290 pub fn draw_layer_static(&self, layer: &Layer) {
292 let here = self.raw_posxy();
293 self.draw_layer(layer);
294 self.raw_move(here.0, here.1);
295 }
296
297 pub fn draw_layer2d(&self, layer: &Layer2D) {
299 self.raw_move(layer.posx, layer.posy);
300 layer.layers.iter().for_each(|l| self.draw_layer_static(l) );
301 }
302
303 pub fn draw_layer2d_static(&self, layer: &Layer) {
305 let here = self.raw_posxy();
306 self.draw_layer(layer);
307 self.raw_move(here.0, here.1);
308 }
309
310 pub fn out(&self, s: String) {
312 self.win.printw(s);
313 self.refresh();
314 }
315
316 pub fn out_static(&self, s: String) {
318 let here = self.raw_posxy();
319 self.out(s);
320 self.raw_move(here.0, here.1);
321 }
322
323 pub fn outln(&self, s: String) {
325 self.win.printw(s);
326 self.outbr();
327 }
328
329 pub fn outbr(&self) {
331 self.win.printw(String::from("\n"));
332 self.refresh();
333 }
334
335 pub fn raw_out(&self, s: String) {
337 self.win.printw(s);
338 }
339
340 pub fn raw_out_static(&self, s: String) {
342 let here = self.raw_posxy();
343 self.raw_out(s);
344 self.raw_move(here.0, here.1);
345 }
346
347 pub fn raw_outln(&self, s: String) {
349 self.win.printw(s);
350 self.raw_br();
351 }
352
353 pub fn raw_br(&self) {
355 self.win.printw(String::from("\n"));
356 }
357
358 pub fn raw_posxy(&self) -> (i32, i32) {
360 (self.win.get_cur_x(), self.win.get_cur_y())
361 }
362
363 pub fn raw_posx(&self) -> i32 {
365 self.win.get_cur_x()
366 }
367
368 pub fn raw_posy(&self) -> i32 {
370 self.win.get_cur_y()
371 }
372
373 pub fn raw_move(&self, x: i32, y: i32) {
375 self.win.mv(y, x);
376 }
377
378 pub fn raw_move_offset(&self, xoffs: i32, yoffs: i32) {
380 self.raw_move(self.raw_posx() + xoffs, self.raw_posy() + yoffs);
381 }
382
383 pub fn raw_move_first(&self) {
385 self.raw_move(0, self.raw_posy());
386 }
387
388 pub fn raw_move_prev(&self) {
390 self.raw_move_offset(-1, 0);
391 }
392
393 pub fn raw_move_next(&self) {
395 self.raw_move_offset(1, 0);
396 }
397
398 pub fn raw_delete(&self) {
400 self.win.delch();
401 }
402
403 pub fn raw_delete_prev(&self) {
405 self.raw_move_prev();
406 self.raw_delete();
407 }
408
409 pub fn raw_delete_offset(&self, xoffs: i32) {
418 let offs = xoffs / xoffs.abs(); let here = self.raw_posx();
420 while self.raw_posx() != here + xoffs {
421 self.raw_move_offset(offs, 0);
422 self.raw_delete();
423 }
424 }
425
426 pub fn raw_delete_from(&self, chars: usize) {
435 self.raw_move_first();
436 self.raw_move_offset(chars as i32, 0);
437 self.raw_delete_to(0);
438 }
439
440 pub fn raw_delete_to(&self, x: i32) {
449 let offs = if x > self.raw_posx() {
450 1
451 } else {
452 -1
453 };
454
455 while self.raw_posx() != x {
456 self.raw_move_offset(offs, 0);
457 self.raw_delete();
458 }
459 }
460
461 pub fn get_char(&self) -> Option<Key> {
463 match self.win.getch() {
464 Some(Input::Character('\n')) | Some(Input::Character('\r')) => Some(Key::Enter),
465 Some(Input::Character('\x08')) => Some(Key::Backspace),
466 Some(Input::Character(c)) => Some(Key::Alpha(c)),
467 Some(Input::KeyUp) => Some(Key::ArrowUp),
468 Some(Input::KeyDown) => Some(Key::ArrowDown),
469 Some(Input::KeyLeft) => Some(Key::ArrowLeft),
470 Some(Input::KeyRight) => Some(Key::ArrowRight),
471 Some(Input::KeyF1) => Some(Key::F1),
472 Some(Input::KeyF2) => Some(Key::F2),
473 Some(Input::KeyF3) => Some(Key::F3),
474 Some(Input::KeyF4) => Some(Key::F4),
475 Some(Input::KeyF5) => Some(Key::F5),
476 Some(Input::KeyF6) => Some(Key::F6),
477 Some(Input::KeyF7) => Some(Key::F7),
478 Some(Input::KeyF8) => Some(Key::F8),
479 Some(Input::KeyF9) => Some(Key::F9),
480 Some(Input::KeyF10) => Some(Key::F10),
481 Some(Input::KeyF11) => Some(Key::F11),
482 Some(Input::KeyF12) => Some(Key::F12),
483 None => None,
484 _ => None,
485 }
486 }
487
488 pub fn get_char_hidden(&self) -> Option<Key> {
490 let here = self.raw_posxy();
491 let ret = self.get_char();
492 match ret {
493 Some(Key::Alpha(c)) => { self.raw_delete_prev(); },
494 _ | None => ()
495 }
496 self.raw_move(here.0, here.1);
497 ret
498 }
499
500 pub fn ask(&self, prefix: String) -> String {
507 self.out(prefix);
508 let mut r = Layer::new(self.raw_posx(), self.raw_posy());
509 while let Some(i) = self.get_char_hidden() {
510 match i {
511 Key::Enter => break,
512 Key::Backspace => {
513 if let Some(i) = r.get_content().pop() {
514 let mut content = r.get_content();
515 content.pop();
516 r.set_content(content);
517 self.draw_layer(&r);
518 } else {
519 self.raw_move_next();
520 continue;
521 }
522 },
523 Key::Alpha(c) => {
524 let mut content = r.get_content();
525 content.push(c);
526 r.set_content(content);
527 self.draw_layer(&r);
528 },
529 _ => continue,
530 }
531 }
532 r.get_content()
533 }
534
535 pub fn mask(&self, prefix: String, mask: char) -> String {
537 self.out(prefix);
538 let mut r = Layer::new(self.raw_posx(), self.raw_posy());
539 let mut s = String::new();
540 while let Some(i) = self.get_char_hidden() {
541 match i {
542 Key::Enter => break,
543 Key::Backspace => {
544 if let Some(i) = r.get_content().pop() {
545 let mut content = r.get_content();
546 content.pop();
547 r.set_content(content);
548 self.draw_layer(&r);
549 s.pop();
550 } else {
551 self.raw_move_next();
552 continue;
553 }
554 },
555 Key::Alpha(c) => {
556 let mut content = r.get_content();
557 content.push(mask);
558 s.push(c);
559 r.set_content(content);
560 self.draw_layer(&r);
561 },
562 _ => continue,
563 }
564 }
565 s
566 }
567
568 pub fn yesno(&self, suffix: String, default: bool) -> bool {
580 let yn: Vec<String> = suffix.split('/').map(|s| String::from(s)).collect();
581 if yn.len() == 1 {
582 panic!("Expected a '/' character separating a yes no question!");
583 }
584 let mut ynl = Layer::new(self.raw_posx(), self.raw_posy());
585 let mut y = yn[0].clone();
586 let mut n = yn[1].clone();
587 match default {
588 true => { y = y.to_uppercase(); },
589 false => { n = n.to_uppercase(); },
590 }
591 ynl.set_content(format!("({}/{})", y.clone(), n.clone()));
592 self.draw_layer(&ynl);
593 let mut ret = default;
594 while let Some(i) = self.get_char_hidden() {
595 match i {
596 Key::Enter => break,
597 Key::ArrowRight => { ret = false; },
598 Key::ArrowLeft => { ret = true; },
599 _ => continue
600 }
601 match ret {
602 true => { y = { n = n.to_lowercase(); y.to_uppercase() } },
603 false => { n = { y = y.to_lowercase(); n.to_uppercase() } },
604 }
605 ynl.set_content(format!("({}/{})", y.clone(), n.clone()));
606 self.draw_layer(&ynl);
607 }
608 ret
609 }
610
611 pub fn choices(&self, prefix: String, strs: Vec<String>) -> String {
621 self.outbr();
622 let mut layers: Vec<Layer> = vec![];
623 for (i , str) in strs.iter().enumerate() {
624 let mut l = Layer::new(self.raw_posx(), self.raw_posy() + i as i32);
625 l.inner_content = str.clone();
626 if i == 0 {
627 l.set_content(format!("{}{}", prefix.clone(), l.inner_content.clone()));
628 } else { l.inner_to_outer(); }
629 self.draw_layer_static(&l);
630 layers.push(l);
631 }
632
633 self.raw_move_offset(0, layers.len() as i32);
634 let mut y = 0;
635 while let Some(i) = self.get_char_hidden() {
636 match i {
637 Key::Enter => break,
638 Key::ArrowDown => {
639 if (y < layers.len() - 1) {
640 y += 1;
641 }
642 },
643 Key::ArrowUp => {
644 if (y > 0) {
645 y -= 1;
646 }
647 }
648 _ => continue
649 }
650 for (i, l) in layers.iter_mut().enumerate() {
651 if i == y {
652 l.set_content(format!("{}{}", prefix.clone(), l.inner_content.clone()));
653 } else { l.inner_to_outer(); }
654 self.draw_layer_static(&l);
655 }
656 }
657
658 layers[y].inner_content.clone()
659 }
660}