Last active
June 27, 2023 23:57
-
-
Save gabehollombe/064a90351c204381832d749ca6b569e0 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env ruby | |
require 'curses' | |
include Curses | |
include Curses::Key | |
class Fixnum | |
def clamp(low, high) | |
v = self | |
v = low if self < low | |
v = high if self > high | |
v | |
end | |
end | |
class Cursor | |
attr_reader :row, :col | |
def initialize(row=0, col=0) | |
@row = row | |
@col = col | |
end | |
def right; Cursor.new @row, @col + 1; end | |
def left; Cursor.new @row, @col - 1; end | |
def down; Cursor.new @row + 1, @col; end | |
def up; Cursor.new @row - 1, @col; end | |
end | |
class Buffer | |
attr_reader :lines, :cursor | |
def initialize(lines=[], cursor=Cursor.new) | |
@lines = lines | |
@cursor = cursor | |
end | |
def cur_row; @cursor.row; end | |
def cur_col; @cursor.col; end | |
def current_line; @lines[cur_row]; end | |
def add_char(char) | |
lines = @lines.dup | |
line = lines[cur_row] || [] | |
line.insert cur_col, char | |
lines[cur_row] = line | |
Buffer.new lines, @cursor.right | |
end | |
def remove_char_before_cursor | |
return Buffer.new @lines, @cursor if cur_col == 0 | |
lines = @lines.dup | |
line = lines[cur_row] || [] | |
line.delete_at(cur_col - 1) | |
lines[@cursor.row] = line | |
Buffer.new lines, @cursor.left | |
end | |
def new_line | |
lines = @lines.dup | |
line, next_line = current_line.partition.with_index { |_, i| i < cur_col } | |
lines[cur_row] = line | |
lines = lines.insert cur_row + 1, next_line | |
Buffer.new lines, Cursor.new(cur_row + 1, 0) | |
end | |
def beginning_of_line | |
Buffer.new lines, Cursor.new(cur_row, 0) | |
end | |
def end_of_line | |
Buffer.new lines, Cursor.new(cur_row, current_line.length) | |
end | |
def cursor_left | |
Buffer.new lines, clamp(@cursor.left) | |
end | |
def cursor_right | |
Buffer.new lines, clamp(@cursor.right) | |
end | |
def cursor_up | |
Buffer.new lines, clamp(@cursor.up) | |
end | |
def cursor_down | |
Buffer.new lines, clamp(@cursor.down) | |
end | |
def clamp(cursor) | |
r = cursor.row.clamp(0, @lines.count - 1) | |
c = cursor.col.clamp(0, @lines[r].length) | |
Cursor.new r, c | |
end | |
end | |
class Editor | |
BACKSPACE = 127 | |
CTRLA = 1 | |
CTRLC = 3 | |
CTRLE = 5 | |
ENTER = 13 | |
def main | |
raw | |
noecho | |
nonl | |
stdscr.keypad = true | |
init_screen | |
buffer = Buffer.new | |
begin | |
loop do | |
char = getch | |
buffer = case char | |
when CTRLC then break | |
when CTRLA then buffer.beginning_of_line | |
when CTRLE then buffer.end_of_line | |
when KEY_UP then buffer.cursor_up | |
when KEY_DOWN then buffer.cursor_down | |
when KEY_LEFT then buffer.cursor_left | |
when KEY_RIGHT then buffer.cursor_right | |
when BACKSPACE then buffer.remove_char_before_cursor | |
when ENTER then buffer.new_line | |
when /[[:print:]]/ then buffer.add_char(char) | |
else buffer | |
end | |
render buffer | |
end | |
ensure | |
close_screen | |
end | |
end | |
def render(buffer) | |
clear | |
buffer.lines.each_with_index do |line, index| | |
setpos index, 0 | |
addstr(line.join) | |
end | |
setpos buffer.cursor.row, buffer.cursor.col | |
refresh | |
end | |
end | |
Editor.new.main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I modified it a little to make it edit a file. https://gist.github.com/nroose/32997db80a45b570bc53174dbe7a5e66