Fix libedit history behaviour
This commit is contained in:
		
							parent
							
								
									3cf3c0215e
								
							
						
					
					
						commit
						c1b6918db3
					
				
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							| @ -1,4 +1,4 @@ | |||||||
| Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name> | Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name> | ||||||
| 
 | 
 | ||||||
| Permission to use, copy, modify, and/or distribute this software for any | Permission to use, copy, modify, and/or distribute this software for any | ||||||
| purpose with or without fee is hereby granted. | purpose with or without fee is hereby granted. | ||||||
|  | |||||||
| @ -140,8 +140,7 @@ the higher-level protocol (the "Sec-Ws-Protocol" HTTP field). | |||||||
| 
 | 
 | ||||||
| Bugs | Bugs | ||||||
| ---- | ---- | ||||||
| The editline (libedit) frontend is more of a proof of concept that mostly seems | The editline (libedit) frontend may exhibit some unexpected behaviour. | ||||||
| to work but exhibits bugs that are not our fault. |  | ||||||
| 
 | 
 | ||||||
| Examples | Examples | ||||||
| -------- | -------- | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| /*
 | /*
 | ||||||
|  * json-rpc-shell.c: a shell for JSON-RPC 2.0 |  * json-rpc-shell.c: a shell for JSON-RPC 2.0 | ||||||
|  * |  * | ||||||
|  * Copyright (c) 2014 - 2020, Přemysl Eric Janouch <p@janouch.name> |  * Copyright (c) 2014 - 2022, Přemysl Eric Janouch <p@janouch.name> | ||||||
|  * |  * | ||||||
|  * Permission to use, copy, modify, and/or distribute this software for any |  * Permission to use, copy, modify, and/or distribute this software for any | ||||||
|  * purpose with or without fee is hereby granted. |  * purpose with or without fee is hereby granted. | ||||||
| @ -515,6 +515,7 @@ struct input_el | |||||||
| 	char *entered_line;                 ///< Buffers the entered line
 | 	char *entered_line;                 ///< Buffers the entered line
 | ||||||
| 
 | 
 | ||||||
| 	bool active;                        ///< Interface has been started
 | 	bool active;                        ///< Interface has been started
 | ||||||
|  | 	bool need_restart;                  ///< Need to clear history state
 | ||||||
| 	char *prompt;                       ///< The prompt we use
 | 	char *prompt;                       ///< The prompt we use
 | ||||||
| 	int prompt_shown;                   ///< Whether the prompt is shown now
 | 	int prompt_shown;                   ///< Whether the prompt is shown now
 | ||||||
| 
 | 
 | ||||||
| @ -540,12 +541,24 @@ input_el_redisplay (struct input_el *self) | |||||||
| { | { | ||||||
| 	// See rl_redisplay(), however NetBSD editline's map.c v1.54 breaks VREPRINT
 | 	// See rl_redisplay(), however NetBSD editline's map.c v1.54 breaks VREPRINT
 | ||||||
| 	// so we bind redisplay somewhere else in input_el_start()
 | 	// so we bind redisplay somewhere else in input_el_start()
 | ||||||
| 	char x[] = { 'q' & 31, 0 }; | 	wchar_t x[] = { L'q' & 31, 0 }; | ||||||
| 	el_push (self->editline, x); | 	el_wpush (self->editline, x); | ||||||
| 
 | 
 | ||||||
| 	// We have to do this or it gets stuck and nothing is done
 | 	// We have to do this or it gets stuck and nothing is done
 | ||||||
| 	int count = 0; | 	int dummy_count = 0; | ||||||
| 	(void) el_wgets (self->editline, &count); | 	(void) el_wgets (self->editline, &dummy_count); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Editline keeping its own history position (look for "eventno" there).
 | ||||||
|  | // This is the only sane way of resetting it.
 | ||||||
|  | static void | ||||||
|  | input_el_start_over (struct input_el *self) | ||||||
|  | { | ||||||
|  | 	wchar_t x[] = { L'c' & 31, 0 }; | ||||||
|  | 	el_wpush (self->editline, x); | ||||||
|  | 
 | ||||||
|  | 	int dummy_count = 0; | ||||||
|  | 	(void) el_wgets (self->editline, &dummy_count); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static char * | static char * | ||||||
| @ -603,13 +616,14 @@ input_el_on_return (EditLine *editline, int key) | |||||||
| 	self->entered_line = xstrndup | 	self->entered_line = xstrndup | ||||||
| 		(info_mb->buffer, info_mb->lastchar - info_mb->buffer); | 		(info_mb->buffer, info_mb->lastchar - info_mb->buffer); | ||||||
| 
 | 
 | ||||||
| 	// Now we need to force editline to actually print the newline
 | 	// Now we need to force editline into actually printing the newline
 | ||||||
| 	el_cursor (editline, len++ - point); | 	el_cursor (editline, len++ - point); | ||||||
| 	el_insertstr (editline, "\n"); | 	el_insertstr (editline, "\n"); | ||||||
| 	input_el_redisplay (self); | 	input_el_redisplay (self); | ||||||
| 
 | 
 | ||||||
| 	// Finally we need to discard the old line's contents
 | 	// Finally we need to discard the old line's contents
 | ||||||
| 	el_wdeletestr (editline, len); | 	el_wdeletestr (editline, len); | ||||||
|  | 	self->need_restart = true; | ||||||
| 	return CC_NEWLINE; | 	return CC_NEWLINE; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -673,8 +687,6 @@ input_el_start (struct input *input, const char *program_name) | |||||||
| 	el_set (self->editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); | 	el_set (self->editline, EL_BIND, "^w", "ed-delete-prev-word", NULL); | ||||||
| 	// Just what are you doing?
 | 	// Just what are you doing?
 | ||||||
| 	el_set (self->editline, EL_BIND, "^u", "vi-kill-line-prev",   NULL); | 	el_set (self->editline, EL_BIND, "^u", "vi-kill-line-prev",   NULL); | ||||||
| 	// See input_el_redisplay(), functionally important
 |  | ||||||
| 	el_set (self->editline, EL_BIND, "^q", "ed-redisplay",        NULL); |  | ||||||
| 
 | 
 | ||||||
| 	// It's probably better to handle these ourselves
 | 	// It's probably better to handle these ourselves
 | ||||||
| 	input_el_addbind (self->editline, "send-line", "Send line", | 	input_el_addbind (self->editline, "send-line", "Send line", | ||||||
| @ -690,6 +702,11 @@ input_el_start (struct input *input, const char *program_name) | |||||||
| 	// Source the user's defaults file
 | 	// Source the user's defaults file
 | ||||||
| 	el_source (self->editline, NULL); | 	el_source (self->editline, NULL); | ||||||
| 
 | 
 | ||||||
|  | 	// See input_el_redisplay(), functionally important
 | ||||||
|  | 	el_set (self->editline, EL_BIND, "^q", "ed-redisplay",        NULL); | ||||||
|  | 	// This is what buffered el_wgets() does, functionally important
 | ||||||
|  | 	el_set (self->editline, EL_BIND, "^c", "ed-start-over",       NULL); | ||||||
|  | 
 | ||||||
| 	self->active = true; | 	self->active = true; | ||||||
| 	self->prompt_shown = 1; | 	self->prompt_shown = 1; | ||||||
| } | } | ||||||
| @ -977,6 +994,16 @@ input_el_on_tty_readable (struct input *input) | |||||||
| 	// We bind the return key to process it how we need to
 | 	// We bind the return key to process it how we need to
 | ||||||
| 	struct input_el *self = (struct input_el *) input; | 	struct input_el *self = (struct input_el *) input; | ||||||
| 
 | 
 | ||||||
|  | 	int unbuffered = 0; | ||||||
|  | 	(void) el_get (self->editline, EL_UNBUFFERED, &unbuffered); | ||||||
|  | 
 | ||||||
|  | 	// We must invoke ch_reset(), which isn't done for us with EL_UNBUFFERED.
 | ||||||
|  | 	if (unbuffered && self->need_restart) | ||||||
|  | 	{ | ||||||
|  | 		self->need_restart = false; | ||||||
|  | 		input_el_start_over (self); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// el_gets() with EL_UNBUFFERED doesn't work with UTF-8,
 | 	// el_gets() with EL_UNBUFFERED doesn't work with UTF-8,
 | ||||||
| 	// we must use the wide-character interface
 | 	// we must use the wide-character interface
 | ||||||
| 	int count = 0; | 	int count = 0; | ||||||
| @ -984,8 +1011,7 @@ input_el_on_tty_readable (struct input *input) | |||||||
| 
 | 
 | ||||||
| 	// Editline works in a funny NO_TTY mode when the input is not a tty,
 | 	// Editline works in a funny NO_TTY mode when the input is not a tty,
 | ||||||
| 	// we cannot use EL_UNBUFFERED and expect sane results then
 | 	// we cannot use EL_UNBUFFERED and expect sane results then
 | ||||||
| 	int unbuffered = 0; | 	if (!unbuffered) | ||||||
| 	if (!el_get (self->editline, EL_UNBUFFERED, &unbuffered) && !unbuffered) |  | ||||||
| 	{ | 	{ | ||||||
| 		char *entered_line = buf ? input_el_wcstombs (buf) : NULL; | 		char *entered_line = buf ? input_el_wcstombs (buf) : NULL; | ||||||
| 		self->super.on_input (entered_line, self->super.user_data); | 		self->super.on_input (entered_line, self->super.user_data); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user