hachem.wtf
aboutsummaryrefslogtreecommitdiff
path: root/kernel/tty.rv
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-10-07 21:43:38 +0200
committerhachem <im@hachem.wtf>2026-10-07 21:43:38 +0200
commite55291a32a8b3f7b5c105cd79e86f3c19f19b3d4 (patch)
tree0a52300c63a011683ceba1642e6f7c24e4d367ef /kernel/tty.rv
parent5d4a723a5f157c0ed38a348099a600d1d21c3c2b (diff)
feat: tty and ttf, you'd think somethn starting with tt would be fun to do...
Diffstat (limited to 'kernel/tty.rv')
-rw-r--r--kernel/tty.rv151
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,
+}