diff options
Diffstat (limited to 'kernel/tty.rv')
| -rw-r--r-- | kernel/tty.rv | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/kernel/tty.rv b/kernel/tty.rv new file mode 100644 index 0000000..5fcd224 --- /dev/null +++ b/kernel/tty.rv @@ -0,0 +1,151 @@ +# tty layer as opposed to a future window management server bullshit thingy +# this is just tty0 it adds nice shit like ^B and stuff +# also has history and shit + +global tty = { + line = "", cursor = 0, esc = 0, + history = {}, hist_index = 0, + + back = fn(self, n) do + let i = 0 + while i < n do puts("\x08") i += 1 end + end, + blanks = fn(self, n) do + let i = 0 + while i < n do puts(" ") i += 1 end + end, + + insert = fn(self, ch) do + const pre = self.line[0..self.cursor] + const post = self.line[self.cursor..] + self.line = pre ~ ch ~ post + puts(ch ~ post) + self:back(post:len()) + self.cursor += 1 + end, + + backspace = fn(self) do + if self.cursor == 0 return :nil + const pre = self.line[0..(self.cursor - 1)] + const post = self.line[self.cursor..] + self.line = pre ~ post + self.cursor -= 1 + puts("\x08") + puts(post ~ " ") + self:back(post:len() + 1) + end, + + move_left = fn(self) do + if self.cursor > 0 do puts("\x08") self.cursor -= 1 end + end, + move_right = fn(self) do + if self.cursor < self.line:len() do puts(self.line[self.cursor]) self.cursor += 1 end + end, + home = fn(self) do + self:back(self.cursor) + self.cursor = 0 + end, + to_end = fn(self) do + puts(self.line[self.cursor..]) + self.cursor = self.line:len() + end, + + kill = fn(self) do + self:back(self.cursor) + self:blanks(self.line:len()) + self:back(self.line:len()) + self.line = "" + self.cursor = 0 + end, + + erase_word = fn(self) do + if self.cursor == 0 return :nil + let at = self.cursor + while (at > 0 and self.line[at - 1] == " ") do at -= 1 end + while (at > 0 and self.line[at - 1] != " ") do at -= 1 end + let count = self.cursor - at + while count > 0 do self:backspace() count -= 1 end + end, + + replace_line = fn(self, text) do + self:kill() + self.line = text + puts(text) + self.cursor = text:len() + end, + + history_prev = fn(self) do + if self.history:len() == 0 return :nil + if self.hist_index > 0 do self.hist_index -= 1 end + self:replace_line(self.history[self.hist_index]) + end, + history_next = fn(self) do + if self.history:len() == 0 return :nil + if self.hist_index < self.history:len() - 1 do + self.hist_index += 1 + self:replace_line(self.history[self.hist_index]) + end + else do + self.hist_index = self.history:len() + self:replace_line("") + end + end, + + submit = fn(self) do + puts("\n") + const entered = self.line + if entered:len() > 0 do self.history:push(entered) end + self.hist_index = self.history:len() + self.line = "" + self.cursor = 0 + run(entered) + end, + + cancel = fn(self) do + puts("^C\n") + self.line = "" + self.cursor = 0 + self.hist_index = self.history:len() + puts(prompt()) + end, + + clear_screen = fn(self) do + console:clear() + puts(prompt()) + puts(self.line) + self:back(self.line:len() - self.cursor) + end, + + feed = fn(self, byte) do + if stdin_deliver(byte) return :nil + + if self.esc == 1 do + if byte == 91 do self.esc = 2 end + else do self.esc = 0 end + return :nil + end + if self.esc == 2 do + self.esc = 0 + if byte == 65 do self:history_prev() end # up + else if byte == 66 do self:history_next() end # down + else if byte == 67 do self:move_right() end # right + else if byte == 68 do self:move_left() end # left + else if byte == 72 do self:home() end # home + else if byte == 70 do self:to_end() end # end + return :nil + end + if byte == 27 do self.esc = 1 return :nil end # ESC, start a sequence + + if byte == 10 do self:submit() return :nil end # enter + if byte == 8 or byte == 127 do self:backspace() return :nil end # bs / del + if byte == 1 do self:home() return :nil end # ctrl-a + if byte == 5 do self:to_end() return :nil end # ctrl-e + if byte == 3 do self:cancel() return :nil end # ctrl-c + if byte == 12 do self:clear_screen() return :nil end # ctrl-l + if byte == 21 do self:kill() return :nil end # ctrl-u + if byte == 23 do self:erase_word() return :nil end # ctrl-w + if byte < 32 return :nil # ctrl-d and other ctrls: ignore + if byte > 126 return :nil + self:insert(string.of_ascii(byte)) + end, +} |
