diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Buffer.zig | 32 | ||||
| -rw-r--r-- | src/KeyMap.zig | 6 | ||||
| -rw-r--r-- | src/KeyReader.zig | 8 |
3 files changed, 43 insertions, 3 deletions
diff --git a/src/Buffer.zig b/src/Buffer.zig index f9a1576..bb6d3ce 100644 --- a/src/Buffer.zig +++ b/src/Buffer.zig | |||
| @@ -94,6 +94,22 @@ pub fn backwardDeleteChar(self: *Buffer) !void { | |||
| 94 | return self.deleteChar(); | 94 | return self.deleteChar(); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | pub fn backwardParagraph(self: *Buffer) void { | ||
| 98 | if (self.cy == 0) { | ||
| 99 | return; | ||
| 100 | } | ||
| 101 | |||
| 102 | self.cy -= 1; | ||
| 103 | while (self.cy > 0) : (self.cy -= 1) { | ||
| 104 | // TODO: I'm lazy but also consider lines of only whitespace | ||
| 105 | if (self.rows.items[self.cy].data.items.len == 0) { | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | self.cx = 0; | ||
| 111 | } | ||
| 112 | |||
| 97 | pub fn cleanWhiteSpace(self: *Buffer) !void { | 113 | pub fn cleanWhiteSpace(self: *Buffer) !void { |
| 98 | for (self.rows.items) |*row| { | 114 | for (self.rows.items) |*row| { |
| 99 | try row.cleanWhiteSpace(self); | 115 | try row.cleanWhiteSpace(self); |
| @@ -272,6 +288,22 @@ pub fn forwardChar(self: *Buffer) void { | |||
| 272 | } | 288 | } |
| 273 | } | 289 | } |
| 274 | 290 | ||
| 291 | pub fn forwardParagraph(self: *Buffer) void { | ||
| 292 | if (self.cy == self.rows.items.len) { | ||
| 293 | return; | ||
| 294 | } | ||
| 295 | |||
| 296 | self.cy += 1; | ||
| 297 | while (self.cy < self.rows.items.len) : (self.cy += 1) { | ||
| 298 | // TODO: I'm lazy but also consider whitespace-only lines | ||
| 299 | if (self.rows.items[self.cy].data.items.len == 0) { | ||
| 300 | break; | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | self.cx = 0; | ||
| 305 | } | ||
| 306 | |||
| 275 | // TODO: Make use of the callback feature to go to the final line while typing in. | 307 | // TODO: Make use of the callback feature to go to the final line while typing in. |
| 276 | pub fn goToLine(self: *Buffer, editor: *Editor) !void { | 308 | pub fn goToLine(self: *Buffer, editor: *Editor) !void { |
| 277 | if (try editor.prompt(self.allocator, "Goto line")) |line_str| { | 309 | if (try editor.prompt(self.allocator, "Goto line")) |line_str| { |
diff --git a/src/KeyMap.zig b/src/KeyMap.zig index 8df4c06..90dcd01 100644 --- a/src/KeyMap.zig +++ b/src/KeyMap.zig | |||
| @@ -112,11 +112,17 @@ pub fn defaultMap(allocator: Allocator) !KeyMap { | |||
| 112 | try map.bind(&.{Key.meta(Key.ctrl('d'))}, Buffer.backwardDeleteChar); | 112 | try map.bind(&.{Key.meta(Key.ctrl('d'))}, Buffer.backwardDeleteChar); |
| 113 | 113 | ||
| 114 | // M-<*> | 114 | // M-<*> |
| 115 | try map.bind(&.{Key.meta(Key.down)}, Buffer.forwardParagraph); | ||
| 116 | try map.bind(&.{Key.meta(Key.up)}, Buffer.backwardParagraph); | ||
| 115 | // M-g is taken | 117 | // M-g is taken |
| 118 | try map.bind(&.{Key.meta('n')}, Buffer.forwardParagraph); | ||
| 116 | // M-O is taken | 119 | // M-O is taken |
| 120 | try map.bind(&.{Key.meta('p')}, Buffer.backwardParagraph); | ||
| 117 | try map.bind(&.{Key.meta('v')}, Buffer.pageUp); | 121 | try map.bind(&.{Key.meta('v')}, Buffer.pageUp); |
| 118 | 122 | ||
| 119 | // C-<*> | 123 | // C-<*> |
| 124 | try map.bind(&.{Key.ctrl(Key.down)}, Buffer.forwardParagraph); | ||
| 125 | try map.bind(&.{Key.ctrl(Key.up)}, Buffer.backwardParagraph); | ||
| 120 | try map.bind(&.{Key.ctrl('a')}, Buffer.moveBeginningOfLine); | 126 | try map.bind(&.{Key.ctrl('a')}, Buffer.moveBeginningOfLine); |
| 121 | try map.bind(&.{Key.ctrl('b')}, Buffer.backwardChar); | 127 | try map.bind(&.{Key.ctrl('b')}, Buffer.backwardChar); |
| 122 | try map.bind(&.{Key.ctrl('d')}, Buffer.deleteChar); | 128 | try map.bind(&.{Key.ctrl('d')}, Buffer.deleteChar); |
diff --git a/src/KeyReader.zig b/src/KeyReader.zig index 28e6dcb..5ddef82 100644 --- a/src/KeyReader.zig +++ b/src/KeyReader.zig | |||
| @@ -31,7 +31,7 @@ pub fn readKey(self: *KeyReader) Error!Key { | |||
| 31 | const reader = std.io.getStdIn().reader(); | 31 | const reader = std.io.getStdIn().reader(); |
| 32 | const char = try readByteBlocking(reader); | 32 | const char = try readByteBlocking(reader); |
| 33 | if (char == '\x1b') { | 33 | if (char == '\x1b') { |
| 34 | return self.readMetaKey(reader); | 34 | return self.readMetaKey(reader, true); |
| 35 | } else if (char == '\x9b') { | 35 | } else if (char == '\x9b') { |
| 36 | return self.readControlSequence(reader); | 36 | return self.readControlSequence(reader); |
| 37 | } else { | 37 | } else { |
| @@ -186,9 +186,11 @@ fn readControlSequence(self: *KeyReader, reader: File.Reader) !Key { | |||
| 186 | return Key.meta('['); | 186 | return Key.meta('['); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | fn readMetaKey(self: *KeyReader, reader: File.Reader) Error!Key { | 189 | fn readMetaKey(self: *KeyReader, reader: File.Reader, canRecurse: bool) Error!Key { |
| 190 | if (try readByte(reader)) |char| { | 190 | if (try readByte(reader)) |char| { |
| 191 | if (char == '[') { | 191 | if (char == '\x1b' and canRecurse) { |
| 192 | return Key.meta(try self.readMetaKey(reader, false)); | ||
| 193 | } else if (char == '[') { | ||
| 192 | return self.readControlSequence(reader); | 194 | return self.readControlSequence(reader); |
| 193 | } else { | 195 | } else { |
| 194 | return Key.meta(char); | 196 | return Key.meta(char); |