Browse Source

Implement keys ^U, ^W, ^K, ^Y

Serj Kalichev 5 months ago
parent
commit
832d50eb12
4 changed files with 72 additions and 74 deletions
  1. 63 70
      tinyrl/tinyrl/keys.c
  2. 3 2
      tinyrl/tinyrl/private.h
  3. 4 0
      tinyrl/tinyrl/tinyrl.c
  4. 2 2
      tinyrl/tinyrl/utf8.c

+ 63 - 70
tinyrl/tinyrl/keys.c

@@ -67,18 +67,19 @@ bool_t tinyrl_key_end_of_line(tinyrl_t *tinyrl, unsigned char key)
 
 bool_t tinyrl_key_kill(tinyrl_t *tinyrl, unsigned char key)
 {
-/*
-	// release any old kill string 
-	lub_string_free(tinyrl->kill_string);
+	// Free old buffered string
+	faux_str_free(tinyrl->buffer);
+	tinyrl->buffer = NULL;
 
-	// store the killed string 
-	tinyrl->kill_string = lub_string_dup(&tinyrl->buffer[tinyrl->point]);
+	// Nothing to kill
+	if (tinyrl->line.pos == tinyrl->line.len)
+		return BOOL_TRUE;
+	// Store killed string
+	tinyrl->buffer = faux_str_dup(tinyrl->line.str + tinyrl->line.pos);
+	// Delete text to the end of the line
+	tinyrl_line_delete(tinyrl, tinyrl->line.pos, tinyrl->line.len);
 
-	// delete the text to the end of the line 
-	tinyrl_delete_text(tinyrl, tinyrl->point, tinyrl->end);
-*/
 	// Happy compiler
-	tinyrl = tinyrl;
 	key = key;
 
 	return BOOL_TRUE;
@@ -87,18 +88,15 @@ bool_t tinyrl_key_kill(tinyrl_t *tinyrl, unsigned char key)
 
 bool_t tinyrl_key_yank(tinyrl_t *tinyrl, unsigned char key)
 {
-	bool_t result = BOOL_FALSE;
-/*
-	if (tinyrl->kill_string) {
-		// insert the kill string at the current insertion point 
-		result = tinyrl_insert_text(tinyrl, tinyrl->kill_string);
-	}
-*/
+	if (!tinyrl->buffer)
+		return BOOL_TRUE;
+
+	tinyrl_line_insert(tinyrl, tinyrl->buffer, strlen(tinyrl->buffer));
+
 	// Happy compiler
-	tinyrl = tinyrl;
 	key = key;
 
-	return result;
+	return BOOL_TRUE;
 }
 
 
@@ -233,23 +231,45 @@ bool_t tinyrl_key_delete(tinyrl_t *tinyrl, unsigned char key)
 
 bool_t tinyrl_key_backword(tinyrl_t *tinyrl, unsigned char key)
 {
-	bool_t result = BOOL_FALSE;
-/*
-    // remove current whitespace before cursor 
-	while (tinyrl->point > 0 && isspace(tinyrl->line[tinyrl->point - 1]))
-        tinyrl_key_backspace(tinyrl, KEY_BS);
-
-    // delete word before cusor 
-	while (tinyrl->point > 0 && !isspace(tinyrl->line[tinyrl->point - 1]))
-        tinyrl_key_backspace(tinyrl, KEY_BS);
-
-	result = BOOL_TRUE;
-*/
+	size_t new_pos = tinyrl->line.pos;
+
+	// Free old buffered string
+	faux_str_free(tinyrl->buffer);
+	tinyrl->buffer = NULL;
+
+	if (tinyrl->line.pos == 0)
+		return BOOL_TRUE;
+
+	// Remove spaces before cursor
+	while (new_pos > 0) {
+		size_t prev_pos = tinyrl->utf8 ?
+			utf8_move_left(tinyrl->line.str, new_pos) : (new_pos - 1);
+		if (!isspace(tinyrl->line.str[prev_pos]))
+			break;
+		new_pos = prev_pos;
+	}
+
+	// Delete word before cusor
+	while (new_pos > 0) {
+		size_t prev_pos = tinyrl->utf8 ?
+			utf8_move_left(tinyrl->line.str, new_pos) : (new_pos - 1);
+		if (isspace(tinyrl->line.str[prev_pos]))
+			break;
+		new_pos = prev_pos;
+	}
+
+	if (new_pos == tinyrl->line.pos)
+		return BOOL_TRUE;
+
+	// Store string
+	tinyrl->buffer = faux_str_dupn(tinyrl->line.str + new_pos,
+		tinyrl->line.pos - new_pos);
+	tinyrl_line_delete(tinyrl, new_pos, tinyrl->line.pos - new_pos);
+
 	// Happy compiler
-	tinyrl = tinyrl;
 	key = key;
 
-	return result;
+	return BOOL_TRUE;
 }
 
 
@@ -267,58 +287,31 @@ bool_t tinyrl_key_clear_screen(tinyrl_t *tinyrl, unsigned char key)
 
 bool_t tinyrl_key_erase_line(tinyrl_t *tinyrl, unsigned char key)
 {
-/*	unsigned int end;
+	// Free old buffered string
+	faux_str_free(tinyrl->buffer);
+	tinyrl->buffer = NULL;
 
-	// release any old kill string 
-	lub_string_free(tinyrl->kill_string);
-
-	if (!tinyrl->point) {
-		tinyrl->kill_string = NULL;
+	// Nothing to erase
+	if (tinyrl->line.len == 0)
 		return BOOL_TRUE;
-	}
-
-	end = tinyrl->point - 1;
-
-	// store the killed string 
-	tinyrl->kill_string = malloc(tinyrl->point + 1);
-	memcpy(tinyrl->kill_string, tinyrl->buffer, tinyrl->point);
-	tinyrl->kill_string[tinyrl->point] = '\0';
+	// Store string
+	tinyrl->buffer = faux_str_dup(tinyrl->line.str);
+	// Delete text to the end of the line
+	tinyrl_line_delete(tinyrl, 0, tinyrl->line.len);
 
-	// delete the text from the start of the line 
-	tinyrl_delete_text(tinyrl, 0, end);
-	tinyrl->point = 0;
-*/
 	// Happy compiler
-	tinyrl = tinyrl;
 	key = key;
 
 	return BOOL_TRUE;
 }
 
 
+// Key tab handler is needed to mask real <tab> output
 bool_t tinyrl_key_tab(tinyrl_t *tinyrl, unsigned char key)
 {
-	bool_t result = BOOL_FALSE;
-/*
-	tinyrl_match_e status = tinyrl_complete_with_extensions(tinyrl);
-
-	switch (status) {
-	case TINYRL_COMPLETED_MATCH:
-	case TINYRL_MATCH:
-		// everything is OK with the world... 
-		result = tinyrl_insert_text(tinyrl, " ");
-		break;
-	case TINYRL_NO_MATCH:
-	case TINYRL_MATCH_WITH_EXTENSIONS:
-	case TINYRL_AMBIGUOUS:
-	case TINYRL_COMPLETED_AMBIGUOUS:
-		// oops don't change the result and let the bell ring 
-		break;
-	}
-*/
 	// Happy compiler
 	tinyrl = tinyrl;
 	key = key;
 
-	return result;
+	return BOOL_TRUE;
 }

+ 3 - 2
tinyrl/tinyrl/private.h

@@ -10,8 +10,8 @@
 // UTF-8 functions
 ssize_t utf8_to_wchar(const char *sp, unsigned long *sym_out);
 bool_t utf8_wchar_is_cjk(unsigned long sym);
-off_t utf8_move_left(const char *line, off_t cur_pos);
-off_t utf8_move_right(const char *line, off_t cur_pos);
+size_t utf8_move_left(const char *line, size_t cur_pos);
+size_t utf8_move_right(const char *line, size_t cur_pos);
 ssize_t utf8_nsyms(const char *str, size_t len);
 
 // Keys
@@ -61,6 +61,7 @@ struct tinyrl_s {
 	size_t prompt_chars; // Symbol positions
 	void *udata; // Arbitrary user data
 	bool_t busy; // Long executed commands set this flag
+	char *buffer; // Internal buffer for kill/yank operations
 
 	// Input processing vars. Input is processed char by char so
 	// the current state of processing is necessary.

+ 4 - 0
tinyrl/tinyrl/tinyrl.c

@@ -79,6 +79,9 @@ tinyrl_t *tinyrl_new(FILE *istream, FILE *ostream,
 	tinyrl->hist = hist_new(hist_fname, hist_stifle);
 	tinyrl_hist_restore(tinyrl);
 
+	// Internal buffer for edit operations like kill/yank
+	tinyrl->buffer = NULL;
+
 	// Save terminal settings
 	tinyrl_save_mode(tinyrl);
 	tinyrl_native_mode(tinyrl);
@@ -102,6 +105,7 @@ void tinyrl_free(tinyrl_t *tinyrl)
 	faux_str_free(tinyrl->prompt);
 	tinyrl_reset_line_state(tinyrl); // It's really reset 'last' string
 	faux_str_free(tinyrl->line.str);
+	faux_str_free(tinyrl->buffer);
 
 	faux_free(tinyrl);
 }

+ 2 - 2
tinyrl/tinyrl/utf8.c

@@ -170,7 +170,7 @@ bool_t utf8_wchar_is_cjk(unsigned long sym)
  * @param [in] cur_pos Current position within UTF-8 string.
  * @return Position of previous UTF-8 character or NULL on error.
  */
-off_t utf8_move_left(const char *line, off_t cur_pos)
+size_t utf8_move_left(const char *line, size_t cur_pos)
 {
 	const char *pos = line + cur_pos;
 
@@ -192,7 +192,7 @@ off_t utf8_move_left(const char *line, off_t cur_pos)
  * @param [in] cur_pos Current position within UTF-8 string.
  * @return Position of next UTF-8 character or NULL on error.
  */
-off_t utf8_move_right(const char *line, off_t cur_pos)
+size_t utf8_move_right(const char *line, size_t cur_pos)
 {
 	const char *pos = line + cur_pos;