Browse Source

tinyrl: Implement history

Serj Kalichev 5 months ago
parent
commit
7bba24cd2b
7 changed files with 93 additions and 152 deletions
  1. 1 0
      bin/klish/interactive.c
  2. 1 1
      tinyrl/hist.h
  3. 22 8
      tinyrl/hist/hist.c
  4. 2 0
      tinyrl/tinyrl.h
  5. 27 43
      tinyrl/tinyrl/keys.c
  6. 1 0
      tinyrl/tinyrl/private.h
  7. 39 100
      tinyrl/tinyrl/tinyrl.c

+ 1 - 0
bin/klish/interactive.c

@@ -121,6 +121,7 @@ static bool_t tinyrl_key_enter(tinyrl_t *tinyrl, unsigned char key)
 	ctx_t *ctx = (ctx_t *)tinyrl_udata(tinyrl);
 	faux_error_t *error = faux_error_new();
 
+	tinyrl_line_to_hist(tinyrl);
 	tinyrl_multi_crlf(tinyrl);
 	tinyrl_reset_line_state(tinyrl);
 

+ 1 - 1
tinyrl/hist.h

@@ -15,7 +15,7 @@ C_DECL_BEGIN
 hist_t *hist_new(const char *hist_fname, size_t stifle);
 void hist_free(hist_t *hist);
 
-void hist_add(hist_t *hist, const char *line);
+void hist_add(hist_t *hist, const char *line, bool_t temp);
 void hist_clear(hist_t *hist);
 
 void hist_pos_reset(hist_t *hist);

+ 22 - 8
tinyrl/hist/hist.c

@@ -20,6 +20,7 @@ struct hist_s {
 	faux_list_node_t *pos;
 	size_t stifle;
 	char *fname;
+	bool_t temp;
 };
 
 
@@ -41,7 +42,6 @@ static int hist_kcompare(const void *key, const void *list_item)
 }
 
 
-
 hist_t *hist_new(const char *hist_fname, size_t stifle)
 {
 	hist_t *hist = faux_zmalloc(sizeof(hist_t));
@@ -55,6 +55,7 @@ hist_t *hist_new(const char *hist_fname, size_t stifle)
 	hist->stifle = stifle;
 	if (hist_fname)
 		hist->fname = faux_str_dup(hist_fname);
+	hist->temp = BOOL_FALSE;
 
 	return hist;
 }
@@ -76,6 +77,12 @@ void hist_pos_reset(hist_t *hist)
 	if (!hist)
 		return;
 
+	// History contain temp entry
+	if (hist->temp) {
+		faux_list_del(hist->list, faux_list_tail(hist->list));
+		hist->temp = BOOL_FALSE;
+	}
+
 	hist->pos = NULL;
 }
 
@@ -97,10 +104,13 @@ const char *hist_pos_up(hist_t *hist)
 	if (!hist)
 		return NULL;
 
-	if (!hist->pos)
+	if (!hist->pos) {
 		hist->pos = faux_list_tail(hist->list);
-	else
-		hist->pos = faux_list_prev_node(hist->pos);
+	} else {
+		faux_list_node_t *new_pos = faux_list_prev_node(hist->pos);
+		if (new_pos) // Don't go up over the list
+			hist->pos = new_pos;
+	}
 
 	if (!hist->pos)
 		return NULL;
@@ -125,17 +135,21 @@ const char *hist_pos_down(hist_t *hist)
 }
 
 
-void hist_add(hist_t *hist, const char *line)
+void hist_add(hist_t *hist, const char *line, bool_t temp)
 {
 	if (!hist)
 		return;
 
 	hist_pos_reset(hist);
-	// Try to find the same string within history
-	faux_list_kdel(hist->list, line);
+	if (temp) {
+		hist->temp = BOOL_TRUE;
+	} else {
+		// Try to find the same string within history
+		faux_list_kdel(hist->list, line);
+	}
 	// Add line to the end of list.
 	// Use (void *)line to make compiler happy about 'const' modifier.
-	faux_list_add(hist->list, (void *)line);
+	faux_list_add(hist->list, (void *)faux_str_dup(line));
 
 	// Stifle list. Note we add only one element so list length can be
 	// (stifle + 1) but not greater so remove only one element from list.

+ 2 - 0
tinyrl/tinyrl.h

@@ -84,6 +84,8 @@ const char *tinyrl_prompt(const tinyrl_t *tinyrl);
 const char *tinyrl_line(const tinyrl_t *tinyrl);
 bool_t tinyrl_hist_save(const tinyrl_t *tinyrl);
 bool_t tinyrl_hist_restore(tinyrl_t *tinyrl);
+void tinyrl_line_to_hist(tinyrl_t *tinyrl);
+void tinyrl_reset_hist_pos(tinyrl_t *tinyrl);
 void *tinyrl_udata(const tinyrl_t *tinyrl);
 void tinyrl_set_udata(tinyrl_t *tinyrl, void *udata);
 void tty_raw_mode(tinyrl_t *tinyrl);

+ 27 - 43
tinyrl/tinyrl/keys.c

@@ -32,6 +32,7 @@ bool_t tinyrl_key_interrupt(tinyrl_t *tinyrl, unsigned char key)
 	tinyrl_multi_crlf(tinyrl);
 	tinyrl_reset_line_state(tinyrl);
 	tinyrl_reset_line(tinyrl);
+	tinyrl_reset_hist_pos(tinyrl);
 
 	// Happy compiler
 	key = key;
@@ -104,6 +105,7 @@ bool_t tinyrl_key_crlf(tinyrl_t *tinyrl, unsigned char key)
 	tinyrl_multi_crlf(tinyrl);
 	tinyrl_reset_line_state(tinyrl);
 	tinyrl_reset_line(tinyrl);
+	tinyrl_reset_hist_pos(tinyrl);
 
 	key = key; // Happy compiler
 
@@ -113,55 +115,37 @@ bool_t tinyrl_key_crlf(tinyrl_t *tinyrl, unsigned char key)
 
 bool_t tinyrl_key_up(tinyrl_t *tinyrl, unsigned char key)
 {
-	bool_t result = BOOL_FALSE;
-/*
-	tinyrl_history_entry_t *entry = NULL;
-	if (tinyrl->line == tinyrl->buffer) {
-		// go to the last history entry 
-		entry = tinyrl_history_getlast(tinyrl->history, &tinyrl->hist_iter);
-	} else {
-		// already traversing the history list so get previous 
-		entry = tinyrl_history_getprevious(&tinyrl->hist_iter);
-	}
-	if (entry) {
-		// display the entry moving the insertion point
-		 * to the end of the line 
-		 
-		tinyrl->line = tinyrl_history_entry__get_line(entry);
-		tinyrl->point = tinyrl->end = strlen(tinyrl->line);
-		result = BOOL_TRUE;
+	const char *str = NULL;
+
+	str = hist_pos(tinyrl->hist);
+	// Up key is pressed for the first time and current line is new typed one
+	if (!str) {
+		hist_add(tinyrl->hist, tinyrl->line.str, BOOL_TRUE); // Temp entry
+		hist_pos_up(tinyrl->hist); // Skip newly added temp entry
 	}
-	// keep the compiler happy 
-	key = key;
-*/
-	return result;
+	hist_pos_up(tinyrl->hist);
+	str = hist_pos(tinyrl->hist);
+	// Empty history
+	if (!str)
+		return BOOL_TRUE;
+	tinyrl_line_replace(tinyrl, str);
+
+	return BOOL_TRUE;
 }
 
 
 bool_t tinyrl_key_down(tinyrl_t *tinyrl, unsigned char key)
 {
-	bool_t result = BOOL_FALSE;
-/*
-	if (tinyrl->line != tinyrl->buffer) {
-		// we are not already at the bottom 
-		// the iterator will have been set up by the key_up() function 
-		tinyrl_history_entry_t *entry =
-		    tinyrl_history_getnext(&tinyrl->hist_iter);
-		if (!entry) {
-			// nothing more in the history list 
-			tinyrl->line = tinyrl->buffer;
-		} else {
-			tinyrl->line = tinyrl_history_entry__get_line(entry);
-		}
-		// display the entry moving the insertion point
-		// to the end of the line 
-		tinyrl->point = tinyrl->end = strlen(tinyrl->line);
-		result = BOOL_TRUE;
-	}
-	// keep the compiler happy 
-	key = key;
-*/
-	return result;
+	const char *str = NULL;
+
+	hist_pos_down(tinyrl->hist);
+	str = hist_pos(tinyrl->hist);
+	// Empty history
+	if (!str)
+		return BOOL_TRUE;
+	tinyrl_line_replace(tinyrl, str);
+
+	return BOOL_TRUE;
 }
 
 

+ 1 - 0
tinyrl/tinyrl/private.h

@@ -38,6 +38,7 @@ bool_t tinyrl_esc_seq(tinyrl_t *tinyrl, const char *esc_seq);
 bool_t tinyrl_line_extend(tinyrl_t *tinyrl, size_t len);
 bool_t tinyrl_line_insert(tinyrl_t *tinyrl, const char *text, size_t len);
 bool_t tinyrl_line_delete(tinyrl_t *tinyrl, off_t start, size_t len);
+bool_t tinyrl_line_replace(tinyrl_t *tinyrl, const char *text);
 
 
 typedef struct line_s {

+ 39 - 100
tinyrl/tinyrl/tinyrl.c

@@ -101,7 +101,9 @@ void tinyrl_free(tinyrl_t *tinyrl)
 
 	tty_restore_mode(tinyrl);
 
+	hist_save(tinyrl->hist);
 	hist_free(tinyrl->hist);
+
 	vt100_free(tinyrl->term);
 	faux_str_free(tinyrl->prompt);
 	tinyrl_reset_line_state(tinyrl); // It's really reset 'last' string
@@ -535,6 +537,27 @@ bool_t tinyrl_line_delete(tinyrl_t *tinyrl, off_t start, size_t len)
 }
 
 
+bool_t tinyrl_line_replace(tinyrl_t *tinyrl, const char *text)
+{
+	size_t len = 0;
+
+	if (faux_str_is_empty(text)) {
+		tinyrl_reset_line(tinyrl);
+		return BOOL_TRUE;
+	}
+
+	len = strlen(text);
+	tinyrl_line_extend(tinyrl, len + 1);
+
+	memcpy(tinyrl->line.str, text, len);
+	tinyrl->line.pos = len;
+	tinyrl->line.len = len;
+	tinyrl->line.str[tinyrl->line.len] = '\0';
+
+	return BOOL_TRUE;
+}
+
+
 static void move_cursor(const tinyrl_t *tinyrl, size_t cur_pos, size_t target_pos)
 {
 	int rows = 0;
@@ -680,6 +703,22 @@ void tinyrl_multi_crlf(const tinyrl_t *tinyrl)
 	vt100_oflush(tinyrl->term);
 }
 
+
+void tinyrl_line_to_hist(tinyrl_t *tinyrl)
+{
+	if (tinyrl->line.len == 0)
+		return;
+
+	hist_add(tinyrl->hist, tinyrl->line.str, BOOL_FALSE);
+}
+
+
+void tinyrl_reset_hist_pos(tinyrl_t *tinyrl)
+{
+	hist_pos_reset(tinyrl->hist);
+}
+
+
 #if 0
 
 /*----------------------------------------------------------------------- */
@@ -701,10 +740,6 @@ static void changed_line(tinyrl_t * tinyrl)
 }
 
 
-
-
-
-
 /*----------------------------------------------------------------------- */
 /* 
  * A convenience function for displaying a list of strings in columnar
@@ -825,27 +860,6 @@ void tinyrl_delete_matches(char **tinyrl)
 	free(tinyrl);
 }
 
-/*-------------------------------------------------------- */
-
-/*-------------------------------------------------------- */
-/*
- * Ring the terminal bell, obeying the setting of bell-style.
- */
-void tinyrl_ding(const tinyrl_t * tinyrl)
-{
-	tinyrl_vt100_ding(tinyrl->term);
-}
-
-/*-------------------------------------------------------- */
-void tinyrl_reset_line_state(tinyrl_t * tinyrl)
-{
-	lub_string_free(tinyrl->last_buffer);
-	tinyrl->last_buffer = NULL;
-	tinyrl->last_line_size = 0;
-
-	tinyrl_redisplay(tinyrl);
-}
-
 /*-------------------------------------------------------- */
 void tinyrl_replace_line(tinyrl_t * tinyrl, const char *text, int clear_undo)
 {
@@ -964,24 +978,6 @@ tinyrl_match_e tinyrl_complete(tinyrl_t * tinyrl)
 	return tinyrl_do_complete(tinyrl, BOOL_FALSE);
 }
 
-/*-------------------------------------------------------- */
-void *tinyrl__get_context(const tinyrl_t * tinyrl)
-{
-	return tinyrl->context;
-}
-
-/*--------------------------------------------------------- */
-const char *tinyrl__get_line(const tinyrl_t * tinyrl)
-{
-	return tinyrl->line;
-}
-
-/*--------------------------------------------------------- */
-tinyrl_history_t *tinyrl__get_history(const tinyrl_t * tinyrl)
-{
-	return tinyrl->history;
-}
-
 /*--------------------------------------------------------- */
 void tinyrl_completion_over(tinyrl_t * tinyrl)
 {
@@ -1000,61 +996,4 @@ bool_t tinyrl_is_completion_error_over(const tinyrl_t * tinyrl)
 	return tinyrl->completion_error_over;
 }
 
-/*--------------------------------------------------------- */
-void tinyrl_done(tinyrl_t * tinyrl)
-{
-	tinyrl->done = BOOL_TRUE;
-}
-
-/*--------------------------------------------------------- */
-void tinyrl_enable_echo(tinyrl_t * tinyrl)
-{
-	tinyrl->echo_enabled = BOOL_TRUE;
-}
-
-/*--------------------------------------------------------- */
-void tinyrl_disable_echo(tinyrl_t * tinyrl, char echo_char)
-{
-	tinyrl->echo_enabled = BOOL_FALSE;
-	tinyrl->echo_char = echo_char;
-}
-
-
-
-
-
-/*-------------------------------------------------------- */
-bool_t tinyrl_is_quoting(const tinyrl_t * tinyrl)
-{
-	bool_t result = BOOL_FALSE;
-	/* count the quotes upto the current insertion point */
-	unsigned int i = 0;
-	while (i < tinyrl->point) {
-		if (result && (tinyrl->line[i] == '\\')) {
-			i++;
-			if (i >= tinyrl->point)
-				break;
-			i++;
-			continue;
-		}
-		if (tinyrl->line[i++] == '"') {
-			result = result ? BOOL_FALSE : BOOL_TRUE;
-		}
-	}
-	return result;
-}
-
-/*-------------------------------------------------------- */
-bool_t tinyrl_is_empty(const tinyrl_t *tinyrl)
-{
-	return (tinyrl->point == 0) ? BOOL_TRUE : BOOL_FALSE;
-}
-
-/*--------------------------------------------------------- */
-void tinyrl_limit_line_length(tinyrl_t * tinyrl, unsigned int length)
-{
-	tinyrl->max_line_length = length;
-}
-
-
 #endif