back to scratko.xyz
summaryrefslogtreecommitdiff
path: root/readline.c
diff options
context:
space:
mode:
authorscratko <m@scratko.xyz>2024-06-20 18:38:11 +0300
committerscratko <m@scratko.xyz>2024-06-23 23:25:46 +0300
commit74c6a747a58b38131534556ab95fa4dd4b514780 (patch)
tree68dae86f9ee994c2bc13681703a8c69e0e2b5f51 /readline.c
parent8f4f87eabec13330a2b3a974975053c1e4632a11 (diff)
downloadshell-74c6a747a58b38131534556ab95fa4dd4b514780.tar.gz
shell-74c6a747a58b38131534556ab95fa4dd4b514780.tar.bz2
shell-74c6a747a58b38131534556ab95fa4dd4b514780.zip
Shell-edit releaseshell-edit
Autocomplete program and file names (tab). Moving the cursor to edit commands (left and right arrows). Deleting a character in a command (backspace).
Diffstat (limited to 'readline.c')
-rw-r--r--readline.c153
1 files changed, 153 insertions, 0 deletions
diff --git a/readline.c b/readline.c
new file mode 100644
index 0000000..c36b19a
--- /dev/null
+++ b/readline.c
@@ -0,0 +1,153 @@
+#include "readline.h"
+#include "shell.h"
+
+#include <stdlib.h>
+#include <string.h> /* memmove */
+#include <stdio.h>
+
+void readline_create_array(struct readline_type *readline)
+{
+ readline->arr = calloc(initial_size, 1);
+ readline->cursor_pos = 0;
+ readline->last_element_index = -1;
+ readline->considered_index = 0;
+ readline->allocation_size = initial_size;
+}
+
+static void readline_copy_array(struct readline_type *readline, char *new_arr)
+{
+ int i;
+ for(i = 0; i <= readline->last_element_index; ++i)
+ new_arr[i] = readline->arr[i];
+}
+
+static void readline_allocate_memory(struct readline_type *readline)
+{
+ char *new_arr = calloc(readline->allocation_size * 2, 1);
+ readline_copy_array(readline, new_arr);
+ free(readline->arr);
+ readline->arr = new_arr;
+ readline->allocation_size *= 2;
+}
+
+static void readline_reprint_modified_part(struct readline_type *readline,
+ int begin_idx)
+{
+ int i, counter;
+ for(i = begin_idx, counter = 0; i <= readline->last_element_index;
+ ++i, ++counter)
+ putchar(readline->arr[i]);
+
+ /* return cursor to previous position */
+ for( ; counter != 0; --counter)
+ putchar('\b');
+ fflush(stdout);
+}
+
+void readline_add_char(struct readline_type *readline, int ch)
+{
+ char *begin_arr;
+ int size;
+
+ if(readline->last_element_index+1 == readline->allocation_size)
+ readline_allocate_memory(readline);
+ /* insert in middle position */
+ if(readline->cursor_pos - 1 != readline->last_element_index) {
+ begin_arr = readline->arr + readline->cursor_pos;
+ size = readline->last_element_index - readline->cursor_pos + 1;
+ memmove(begin_arr+1, begin_arr, size);
+ readline->arr[readline->cursor_pos] = ch;
+ ++readline->last_element_index;
+ readline_reprint_modified_part(readline, readline->cursor_pos + 1);
+ } else {
+ ++readline->last_element_index;
+ readline->arr[readline->last_element_index] = ch;
+ }
+ ++readline->cursor_pos;
+}
+
+void readline_reset_array(struct readline_type *readline)
+{
+ readline->last_element_index = -1;
+ readline->cursor_pos = 0;
+}
+
+void readline_clear(struct readline_type *readline)
+{
+ free(readline->arr);
+ readline->arr = NULL;
+}
+
+void readline_print(struct readline_type *readline)
+{
+ int i;
+ for(i = 0; i <= readline->last_element_index; ++i)
+ putchar(readline->arr[i]);
+ readline->cursor_pos = readline->last_element_index + 1;
+ fflush(stdout);
+}
+
+enum keys readline_detect_arrow_keys(int ch)
+{
+ char next_ch;
+ if(ch == esc) {
+ next_ch = getchar();
+ if(next_ch != '[')
+ return unknown_key;
+ next_ch = getchar();
+
+ switch(next_ch) {
+ case left_arrow:
+ return left_arrow;
+ case right_arrow:
+ return right_arrow;
+ case up_arrow:
+ return up_arrow;
+ case down_arrow:
+ return down_arrow;
+ default:
+ return unknown_key;
+ }
+ }
+ return none;
+}
+
+void readline_move_along(struct readline_type *readline, enum keys found_key)
+{
+ switch(found_key) {
+ case left_arrow:
+ if(readline->cursor_pos > 0) {
+ putchar('\b');
+ fflush(stdout);
+ --readline->cursor_pos;
+ }
+ break;
+ case right_arrow:
+ if(readline->cursor_pos <= readline->last_element_index) {
+ putchar(readline->arr[readline->cursor_pos]);
+ fflush(stdout);
+ ++readline->cursor_pos;
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+void readline_character_deletion(struct readline_type *readline)
+{
+ char *begin_arr;
+ int size;
+
+ if(readline->cursor_pos > 0) {
+ putchar('\b');
+ fflush(stdout);
+ begin_arr = readline->arr + readline->cursor_pos;
+ size = readline->last_element_index - readline->cursor_pos + 1;
+ memmove(begin_arr-1, begin_arr, size);
+ readline->arr[readline->last_element_index] = ' ';
+ readline_reprint_modified_part(readline, readline->cursor_pos - 1);
+ --readline->last_element_index;
+ --readline->cursor_pos;
+ }
+}