Fix input_box refresh() out of order resize
[canto-curses.git] / canto_curses / input.py
1 # -*- coding: utf-8 -*-
2 #Canto-curses - ncurses RSS reader
3 #   Copyright (C) 2016 Jack Miller <jack@codezen.org>
4 #
5 #   This program is free software; you can redistribute it and/or modify
6 #   it under the terms of the GNU General Public License version 2 as 
7 #   published by the Free Software Foundation.
8
9 from canto_next.plugins import Plugin
10 from .guibase import GuiBase
11 from .widecurse import get_rlpoint
12 from .command import cmd_complete_info
13
14 import logging
15 log = logging.getLogger("INPUT")
16
17 import readline
18 import curses
19 import shlex
20 from curses import ascii
21
22 class InputPlugin(Plugin):
23     pass
24
25 class InputBox(GuiBase):
26     def __init__(self):
27         GuiBase.__init__(self)
28         self.plugin_class = InputPlugin
29         self.pad = None
30
31     def init(self, pad, callbacks):
32         self.pad = pad
33
34         self.callbacks = callbacks
35
36         self.reset()
37
38     def reset(self):
39         self.pad.erase()
40         self.pad.addstr(self.callbacks["get_var"]("input_prompt"))
41         self.minx = self.pad.getyx()[1]
42         self.x = self.minx
43
44         # Part that's not considered
45         self.completion_root = None
46         self.completions = None
47
48     def _get_prefix(self):
49         buf = readline.get_line_buffer()
50         if (not buf) or buf[-1].isspace():
51             prefix = ""
52         else:
53             prefix = shlex.split(buf)[-1]
54         return prefix
55
56     def rotate_completions(self):
57         complist = self.callbacks["get_var"]("input_completions")
58         oldpref = self.callbacks["get_var"]("input_completion_root")
59
60         prefix = self._get_prefix()
61         if not complist or oldpref != prefix:
62             r = cmd_complete_info()
63             if not r or not r[2]:
64                 complist = []
65             else:
66                 complist = [ x[len(prefix):] for x in r[2] if x.startswith(prefix) ]
67                 complist.sort()
68         else:
69             complist = complist[1:] + [ complist[0] ]
70
71         self.callbacks["set_var"]("input_completions", complist)
72         self.callbacks["set_var"]("input_completion_root", prefix)
73
74     def break_completion(self):
75         comp = self.callbacks["get_var"]("input_completions")
76         self.callbacks["set_var"]("input_completions", [])
77         self.callbacks["set_var"]("input_completion_root", "")
78         if comp:
79             return comp[0]
80         return None
81
82     def refresh(self):
83         if not self.pad:
84             return
85
86         self.pad.move(0, self.minx)
87         maxx = self.pad.getmaxyx()[1]
88
89         s = readline.get_line_buffer()
90         complist = self.callbacks["get_var"]("input_completions")
91         if complist:
92             s += complist[0]
93
94         log.debug("printing: '%s'", s[-1 * (maxx - self.minx):])
95         try:
96             self.pad.addstr(s[-1 * (maxx - self.minx):])
97         except:
98             pass
99         self.x = self.pad.getyx()[1]
100         self.pad.clrtoeol()
101         self.pad.move(0, min(maxx - 1, self.minx + get_rlpoint()))
102         try:
103             self.callbacks["refresh"]()
104         except:
105             pass
106
107     def redraw(self):
108         pass
109
110     def is_input(self):
111         return True
112
113     def get_opt_name(self):
114         return "input"
115
116     def get_height(self, mheight):
117         return 1
118
119     def get_width(self, mwidth):
120         return mwidth