From 83a71ae0a156872dacf26cdd1ef7057fe9777157 Mon Sep 17 00:00:00 2001 From: FantasyPvP <80643031+FantasyPvP@users.noreply.github.com> Date: Sat, 2 Nov 2024 22:39:16 +0000 Subject: [PATCH] started C implementation, created custom library for handling strings --- .vscode/settings.json | 16 +++ final/binary | Bin 0 -> 17400 bytes final/dynstr.c | 232 ++++++++++++++++++++++++++++++++++++++++ final/dynstr.h | 36 +++++++ final/editor.c | 82 ++++++++++++++ final/editor.h | 18 ++++ final/main.c | 65 +++++++++-- final/util.c | 0 prototype/something.txt | 8 +- prototype/src/main.rs | 61 +++++++---- 10 files changed, 488 insertions(+), 30 deletions(-) create mode 100644 .vscode/settings.json create mode 100755 final/binary create mode 100644 final/dynstr.c create mode 100644 final/dynstr.h create mode 100644 final/editor.c create mode 100644 final/editor.h create mode 100644 final/util.c diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a8195b9 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,16 @@ +{ + "files.associations": { + "array": "c", + "string": "c", + "string_view": "c", + "ranges": "c", + "span": "c", + "*.inc": "c", + "*.ipp": "c", + "bitset": "c", + "format": "c", + "initializer_list": "c", + "vector": "c", + "__bit_reference": "c" + } +} \ No newline at end of file diff --git a/final/binary b/final/binary new file mode 100755 index 0000000000000000000000000000000000000000..8b4cb0a244bd5cac073c2a12c63c2c164404fbb8 GIT binary patch literal 17400 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 +#include +#include +#include + +typedef struct { + int size; + int capacity; + char* data; +} String; + +String str_with_capacity(int capacity) { + String s; + + /// allocate memory for 'capacity' chars + s.data = (char*)calloc(capacity, sizeof(char)); + + s.size = 0; + s.capacity = capacity; + + return s; +} + +String str_from_chars(char* string) { + String s; + + s.data = (char*)calloc(strlen(string), sizeof(char)); + strcpy(s.data, string); + s.size = strlen(string); + s.capacity = strlen(string); + return s; +} + +String str_from_slice(char* string, int len) { + String s; + + s.data = (char*)calloc(len, sizeof(char)); + strncpy(s.data, string, len); + s.size = len; + s.capacity = len; + return s; +} + + +String str_new() { + return str_with_capacity(1); +} + +int str_dealloc(String* self) { + free(self->data); + return 0; +} + +void str_push(String* self, char c) { + // check size < capacity + if (self->size < self->capacity) { + self->data[self->size] = c; + self->size++; + return; + } + + // reallocate to add capacity for an extra char + int newcap = self->capacity + sizeof(char); + self->data = (char*)realloc(self->data, newcap); + self->data[self->size] = c; + self->size++; + self->capacity = newcap; + return; +} + +char str_pop(String* self) { + if (self->size == 0) { + return '\0'; + } + self->size--; + char c = self->data[self->size]; + return c; +} + +void str_insert(String* self, int index, char c) { + if (index > self->size) { + return; + } + self->size++; + for (int i = self->size - 1; i > index; i--) { + self->data[i] = self->data[i - 1]; + } + self->data[index] = c; +} + +void str_remove(String* self, int index) { + if (index >= self->size) { + return; + } + self->size--; + for (int i = index; i < self->size; i++) { + self->data[i] = self->data[i + 1]; + } +} + +String* str_lines(String* self, int* numlines) { + + char* string = self->data; + String* lines = NULL; + + // find the number of lines in the file + *numlines = 0; + for (int i = 0; i < strlen(string); i++) { + if (string[i] == '\n') { + (*numlines)++; + } + } + + // add one if the last char is not a newline + // in this case there is one more line than newline symbols + if (self->data[strlen(self->data) - 1] != '\n') { + (*numlines)++; + } + + // allocate memory for an array of pointers to each line + lines = (String*)malloc((*numlines + 1) * sizeof(String)); + + int i = 0; + char* start = string; + char* end = string; + + while (*end != '\0') { + if (*end == '\n') { + lines[i] = str_from_slice(start, end - start); + + end++; + start = end; + + i++; + } else { + end++; + } + } + // returns an array of String + return lines; +} + +/// splits a string into an array of strings based on a delimiter +String* str_split(String* self, int* res_len, char c) { + + char* string = self->data; + String* elements = NULL; + + // find the number of lines in the file + + bool flag = false; + *res_len = 0; + for (int i = 0; i < strlen(string); i++) { + if (string[i] == c) { + if (flag) { + (*res_len)++; + flag = false; + } + } else { + flag = true; + } + } + if (flag) { + (*res_len)++; + } + + // allocate memory for an array of pointers to each line + elements = (String*)malloc((*res_len) * sizeof(String)); + + int i = 0; + flag = false; + char* start = string; + char* end = string; + + while (*end != '\0') { + if (*end == c) { + if (flag) { + elements[i] = str_from_slice(start, end - start); + i++; + } + end++; + start = end; + flag = false; + } else { + end++; + flag = true; + } + } if (flag) { + elements[i] = str_from_slice(start, end - start); + } + + + // returns an array of String + return elements; +} + +int str_len(String* s) { + return s->size; +} + +char* to_chars(String* s) { + return s->data; +} + +// int main() { +// String s = str_from_chars("hello\nworld\neeeee\notherline\n\0"); + +// int numlines = 0; +// String* lns = str_lines(&s, &numlines); +// str_dealloc(&s); + +// for (int i = 0; i < numlines; i++) { +// printf("%s\n", lns[i].data); +// str_dealloc(&lns[i]); +// } + +// String s2 = str_from_chars("$this$needs$to$be$split"); + +// int elements = 0; +// String* split = str_split(&s2, &elements, '$'); +// str_dealloc(&s2); + +// printf("%d elements\n", elements); +// for (int i = 0; i < elements; i++) { +// printf("%s\n", split[i].data); +// str_dealloc(&split[i]); +// printf("(dealloced)\n"); +// } +// } \ No newline at end of file diff --git a/final/dynstr.h b/final/dynstr.h new file mode 100644 index 0000000..0391223 --- /dev/null +++ b/final/dynstr.h @@ -0,0 +1,36 @@ +#ifndef DYNSTR_H +#define DYNSTR_H + +typedef struct { + int size; + int capacity; + char* data; +} String; + +String str_with_capacity(int capacity); + +String str_from_chars(char* string); + +String str_from_slice(char* string, int len); + +String str_new(); + +String* str_lines(String* self, int* numlines); + +// String* str_split(String* self, int* res_len, char c); + +void str_push(String* s, char c); + +char str_pop(String* s); + +void str_insert(String* s, int index, char c); + +void str_remove(String* s, int index); + +int str_dealloc(String* s); + +char* to_chars(String* s); + +int str_len(String* s); + +#endif diff --git a/final/editor.c b/final/editor.c new file mode 100644 index 0000000..f90b417 --- /dev/null +++ b/final/editor.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include "dynstr.h" +#include + +typedef struct { + int lines; + int screen_line; + int screen_col; + bool editmode; + String* buffer; +} Editor; + +Editor new_editor() { + Editor e; + e.lines = 0; + e.screen_line = 0; + e.screen_col = 0; + e.editmode = false; + e.buffer = NULL; + return e; +} + +Editor editor_from(char* input_string) { + // TODO: fix this function + Editor e; + e.lines = 0; + e.screen_line = 0; + e.screen_col = 0; + e.editmode = false; + e.buffer = NULL; + return e; +} + +void move_cursor(Editor* self, int x, int y) { + if (x != 0 + && self->screen_line + y >= 0 + && self->screen_line + y <= self->lines) + { + self->screen_line += y; + int line_width = str_len(&self->buffer[self->screen_line]); + if (self->screen_col > line_width) { + self->screen_col = line_width; + } + } else if (self->screen_col + x < 0) { + if (self->screen_line - 1 >= 0) { + self->screen_col = str_len(&self->buffer[self->screen_line]); + } + } else if (self->screen_col + x > str_len(&self->buffer[self->screen_line])) { + if (self->screen_line + 1 <= self->lines) { + self->screen_col = 0; + self->screen_line += 1; + } + } else if (x != 0) { + self->screen_col += x; + } + + move(self->screen_line, self->screen_col); +} + +void delchar(Editor* self) { + str_remove(&self->buffer[self->screen_line], self->screen_col); + delch(); +} + +void addchar(Editor* self, char c) { + insch(c); + // insert the character into the string at the given index + if (self->screen_line == self->lines) { + // reallocate self->buffer to be 1 larger + self->lines++; + self->buffer = realloc(self->buffer, sizeof(String) * (self->lines + 1)); + } + str_insert(&self->buffer[self->screen_line], self->screen_col, c); + move_cursor(self, 1, 0); +} + +String* to_string(Editor* self) { + +} + diff --git a/final/editor.h b/final/editor.h new file mode 100644 index 0000000..ec45b4b --- /dev/null +++ b/final/editor.h @@ -0,0 +1,18 @@ +#include "dynstr.h" + +typedef struct { + int screen_line; + int screen_col; + bool editmode; + String* buffer; +} Editor; + +Editor new_editor(); + +Editor editor_from(char* input_string); + +void move_cursor(Editor* self, int x, int y); +void delchar(Editor* self); +void addchar(Editor* self, char c); + +String* to_string(Editor* self); \ No newline at end of file diff --git a/final/main.c b/final/main.c index 688cf3c..865c133 100644 --- a/final/main.c +++ b/final/main.c @@ -1,17 +1,7 @@ #include #include #include -#include -#include -#include - -typedef struct { - int file_line; - int file_col; - int buff_line; - int buff_col; - int editmode; -} EditorData; +#include "editor.h" void help() { printf("Usage:\n"); @@ -23,3 +13,56 @@ void help() { printf(" cmd len // returns the length of the specified file\n"); printf(" cmd log // prints a list of all changes made to the file\n"); } + +int open_editor() { + initscr(); + raw(); + noecho(); + keypad(stdscr, true); + int max_y, max_x; + getmaxyx(stdscr, max_y, max_x); + + move(0, 0); + + Editor editor = new_editor(); + + while (true) { + refresh(); + int c = getch(); + if (editor.editmode) { + switch (c) { + case 27: + editor.editmode = false; + break; + case KEY_BACKSPACE: + delchar(&editor); + break; + case KEY_ENTER: + editor.editmode = false; + break; + default: + addchar(&editor, c); + break; + } + } else { + switch (c) { + case 'q': + return 0; + case 'i': + editor.editmode = true; + break; + case 'w': + // TODO: write function to save the data to a file + break; + default: + break; + } + } + } +} + +int main() { + open_editor(); + return 0; +} + diff --git a/final/util.c b/final/util.c new file mode 100644 index 0000000..e69de29 diff --git a/prototype/something.txt b/prototype/something.txt index 6c041dd..2a99654 100644 --- a/prototype/something.txt +++ b/prototype/something.txt @@ -1 +1,7 @@ -[package] name = "cs_coursework_editor_draft" version = "0.1.0" edition = "2021" [dependencies] ncurses = "6.0.1" i may have made a very scuffed version of vim. \ No newline at end of file +[package] +name = "cs_coursework_editor_draft" +version = "0.1.0" +edition = "2021" + +[dependencies] +ncurses = "6.0.1" diff --git a/prototype/src/main.rs b/prototype/src/main.rs index 1d1de9b..51ed803 100644 --- a/prototype/src/main.rs +++ b/prototype/src/main.rs @@ -17,6 +17,7 @@ struct EditorData { } impl EditorData { + /// called when the user creates a new file or supplies a valid file path that does not exist/* */. fn new() -> EditorData { EditorData { buffer: Vec::new(), @@ -27,6 +28,7 @@ impl EditorData { editmode: false, } } + /// called when the user opens an existing file from a valid directory. fn from(s: String) -> EditorData { EditorData { buffer: s @@ -41,22 +43,23 @@ impl EditorData { } } + /// moves the cursor (with bounds checks) fn mv_cursor(&mut self, dy: i32, dx: i32) { if dy != 0 && self.screen_line + dy >= 0 && self.screen_line + dy <= self.buffer.len() as i32 { self.screen_line += dy; - let line_width = self.buffer[self.screen_line as usize].len() as i32; + let line_width = self.buffer.get(self.screen_line as usize).unwrap_or(&Vec::::new()).len() as i32; if self.screen_col > line_width { self.screen_col = line_width; } } else if self.screen_col + dx < 0 { if self.screen_line - 1 >= 0 { self.screen_line -= 1; - self.screen_col = self.buffer[self.screen_line as usize].len() as i32; + self.screen_col = self.buffer.get(self.screen_line as usize).unwrap_or(&Vec::::new()).len() as i32; } - } else if self.screen_col + dx > self.buffer[self.screen_line as usize].len() as i32 { + } else if self.screen_col + dx > self.buffer.get(self.screen_line as usize).unwrap_or(&Vec::::new()).len() as i32 { if self.screen_line + 1 <= self.buffer.len() as i32 { self.screen_col = 0; self.screen_line += 1; @@ -67,6 +70,9 @@ impl EditorData { ncurses::mv(self.screen_line, self.screen_col); } + /// Delete the character at the cursor. + /// if the cursor is at the end of the line, the next line is appended to the current line and the next line is removed. + /// Otherwise, the character at the cursor is removed and the rest of the line is shifted left. fn delchar(&mut self) { if self.screen_col == self.buffer[self.screen_line as usize].len() as i32 { let oldline = self.buffer[1 + self.screen_line as usize].clone(); @@ -76,18 +82,29 @@ impl EditorData { ncurses::clear(); let s = self.to_string(); ncurses::addstr(&s).unwrap(); + ncurses::mv(self.screen_line, self.screen_col); + } else { + self.buffer[self.screen_line as usize].remove(self.screen_col as usize); + ncurses::delch(); } - - self.buffer[self.file_line as usize].remove(self.file_col as usize); - ncurses::delch(); } + /// Insert a character at the cursor, + /// then update the cursor position. fn addchar(&mut self, c: char) { - self.buffer[self.screen_line as usize].insert(self.screen_col as usize, c); + ncurses::insch(keystroke as u32); + if let Some(line) = self.buffer.get_mut(self.screen_line as usize) { + line.insert(self.screen_col as usize, c); + } else { + self.buffer.push(Vec::new()); + self.buffer.get_mut(self.screen_line as usize).unwrap().push(c); + } + data.mv_cursor(0, 1); } } impl ToString for EditorData { + /// converts the buffer to a string so that it can be written back to the text file. fn to_string(&self) -> String { self.buffer .iter() @@ -97,6 +114,18 @@ impl ToString for EditorData { } } +/// commands: +/// +/// * `open `: opens the specified file in the editor. +/// * `rm `: deletes the specified file. +/// * `new `: creates a new empty file at the specified path. +/// * `mv `: moves the specified file to the new path. +/// * `cp `: copies the specified file to the new path. +/// * `lenc `: prints the length of the specified file in characters. +/// * `lenl `: prints the length of the specified file in lines. +/// * `log`: prints a list of all changes made to the file. +/// +/// an invalid command will result in the help message being printed. fn main() { let args = env::args().collect::>(); @@ -136,7 +165,6 @@ fn help() { println!( "Usage: cmd open // opens the specified file -Write cmd rm // deletes the specified file cmd new // creates a new empty file at the specified path cmd mv // moves the specified file to the new path @@ -188,11 +216,11 @@ fn open(filename: &str) -> Result<(), &'static str> { ncurses::KEY_RIGHT => data.mv_cursor(0, 1), ncurses::KEY_UP => data.mv_cursor(-1, 0), ncurses::KEY_DOWN => data.mv_cursor(1, 0), + ncurses::KEY_ENTER => { + + } _ => { - ncurses::insch(keystroke as u32); - data.addchar(char::from_u32(keystroke as u32).unwrap()); - data.mv_cursor(0, 1); } } } else { @@ -202,13 +230,10 @@ fn open(filename: &str) -> Result<(), &'static str> { } 119 => { let buff_size = max_y * max_x; - let mut buff = vec![0; buff_size as usize]; + + + let buff = data.to_string(); - for i in 0..buff_size { - buff[i as usize] = - (ncurses::mvwinch(ncurses::stdscr(), i / max_x, i % max_x) - & ncurses::A_CHARTEXT) as u8; - } ncurses::endwin(); OpenOptions::new() @@ -216,7 +241,7 @@ fn open(filename: &str) -> Result<(), &'static str> { .truncate(true) .open(filename) .unwrap() - .write_all(&buff) + .write_all(buff.as_bytes()) .unwrap(); } 113 => {