aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/fish_key_reader.cpp52
-rw-r--r--src/reader.cpp23
-rw-r--r--tests/bind.expect20
-rw-r--r--tests/bind.expect.out2
4 files changed, 42 insertions, 55 deletions
diff --git a/src/fish_key_reader.cpp b/src/fish_key_reader.cpp
index 7908bfef..1c30c1db 100644
--- a/src/fish_key_reader.cpp
+++ b/src/fish_key_reader.cpp
@@ -16,7 +16,6 @@
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
-#include <termios.h>
#include <wctype.h>
#include <string>
@@ -25,15 +24,16 @@
#include "fallback.h" // IWYU pragma: keep
#include "input.h"
#include "input_common.h"
+#include "proc.h"
+#include "reader.h"
struct config_paths_t determine_config_directory_paths(const char *argv0);
-static struct termios saved_modes; // so we can reset the modes when we're done
static long long int prev_tstamp = 0;
static const char *ctrl_equivalents[] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, "\\a",
- "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, "\\e", NULL, NULL, NULL, NULL};
+ "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "\\e", NULL, NULL, NULL, NULL};
/// Return true if the recent sequence of characters indicates the user wants to exit the program.
bool should_exit(unsigned char c) {
@@ -47,7 +47,7 @@ bool should_exit(unsigned char c) {
}
/// Return the key name if the recent sequence of characters matches a known terminfo sequence.
-char * const key_name(unsigned char c) {
+char *const key_name(unsigned char c) {
static char recent_chars[8] = {0};
recent_chars[0] = recent_chars[1];
@@ -121,7 +121,7 @@ void process_input(bool continuous_mode) {
printf("%6lld usec dec: %3u hex: %2x char: %c\n", delta_tstamp, c, c, c);
}
- char * const name = key_name(c);
+ char *const name = key_name(c);
if (name) {
printf("FYI: Saw sequence for bind key name \"%s\"\n", name);
free(name);
@@ -136,48 +136,22 @@ void process_input(bool continuous_mode) {
}
}
-/// Set the tty modes to not interpret any characters. We want every character to be passed thru to
-/// this program. Including characters such as [ctrl-C] and [ctrl-D] that might normally have
-/// special significance (e.g., terminate the program).
-bool set_tty_modes(void) {
- struct termios modes;
-
- tcgetattr(0, &modes); // get the current tty modes
- saved_modes = modes; // save a copy so we can reset them on exit
-
- modes.c_lflag &= ~ICANON; // turn off canonical mode
- modes.c_lflag &= ~ECHO; // turn off echo mode
- modes.c_lflag &= ~ISIG; // turn off recognizing signal generating characters
- modes.c_iflag &= ~ICRNL; // turn off mapping CR to NL
- modes.c_iflag &= ~INLCR; // turn off mapping NL to CR
- modes.c_cc[VMIN] = 1; // return each character as they arrive
- modes.c_cc[VTIME] = 0; // wait forever for the next character
-
- if (tcsetattr(0, TCSANOW, &modes) != 0) { // set the new modes
- return false;
- }
- return true;
-}
-
-/// Restore the tty modes to what they were before this program was run. This shouldn't be required
-/// but we do it just in case the program that ran us doesn't handle tty modes for external programs
-/// in a sensible manner.
-void reset_tty_modes() { tcsetattr(0, TCSANOW, &saved_modes); }
-
/// Make sure we cleanup before exiting if we're signaled.
void signal_handler(int signo) {
printf("\nExiting on receipt of signal #%d\n", signo);
- reset_tty_modes();
+ restore_term_mode();
exit(1);
}
/// Setup our environment (e.g., tty modes), process key strokes, then reset the environment.
void setup_and_process_keys(bool continuous_mode) {
+ is_interactive_session = 1; // by definition this is interactive
set_main_thread();
setup_fork_guards();
wsetlocale(LC_ALL, L"POSIX");
program_name = L"fish_key_reader";
env_init();
+ reader_init();
input_init();
// Installing our handler for every signal (e.g., SIGSEGV) is dubious because it means that
@@ -198,13 +172,9 @@ void setup_and_process_keys(bool continuous_mode) {
set_wait_on_escape_ms(500);
}
- if (!set_tty_modes()) {
- printf("Could not set the tty modes. Refusing to continue running.\n");
- exit(1);
- }
// TODO: We really should enable keypad mode but see issue #838.
process_input(continuous_mode);
- reset_tty_modes();
+ restore_term_mode();
}
int main(int argc, char **argv) {
diff --git a/src/reader.cpp b/src/reader.cpp
index 235086c9..47258c64 100644
--- a/src/reader.cpp
+++ b/src/reader.cpp
@@ -784,23 +784,19 @@ void reader_init() {
// Set the mode used for the terminal, initialized to the current mode.
memcpy(&shell_modes, &terminal_mode_on_startup, sizeof shell_modes);
- shell_modes.c_iflag &= ~ICRNL; // turn off mapping CR (\cM) to NL (\cJ)
- shell_modes.c_iflag &= ~INLCR; // turn off mapping NL (\cJ) to CR (\cM)
+
+ shell_modes.c_iflag &= ~ICRNL; // disable mapping CR (\cM) to NL (\cJ)
+ shell_modes.c_iflag &= ~INLCR; // disable mapping NL (\cJ) to CR (\cM)
+ shell_modes.c_iflag &= ~IXON; // disable flow control
+ shell_modes.c_iflag &= ~IXOFF; // disable flow control
+
shell_modes.c_lflag &= ~ICANON; // turn off canonical mode
shell_modes.c_lflag &= ~ECHO; // turn off echo mode
- shell_modes.c_iflag &= ~IXON; // disable flow control
- shell_modes.c_iflag &= ~IXOFF; // disable flow control
+ shell_modes.c_lflag &= ~IEXTEN; // turn off handling of discard and lnext characters
+
shell_modes.c_cc[VMIN] = 1;
shell_modes.c_cc[VTIME] = 0;
-#if defined(_POSIX_VDISABLE)
-// PCA disable VDSUSP (typically control-Y), which is a funny job control. function available only
-// on OS X and BSD systems. This lets us use control-Y for yank instead.
-#ifdef VDSUSP
- shell_modes.c_cc[VDSUSP] = _POSIX_VDISABLE;
-#endif
-#endif
-
// We don't use term_steal because this can fail if fd 0 isn't associated with a tty and this
// function is run regardless of whether stdin is tied to a tty. This is harmless in that case.
// We do it unconditionally because disabling ICRNL mode (see above) needs to be done at the
@@ -1107,8 +1103,7 @@ wcstring completion_apply_to_command_line(const wcstring &val_str, complete_flag
// Perform the insertion and compute the new location.
wcstring result = command_line;
result.insert(insertion_point, replaced);
- size_t new_cursor_pos =
- insertion_point + replaced.size() + (back_into_trailing_quote ? 1 : 0);
+ size_t new_cursor_pos = insertion_point + replaced.size() + (back_into_trailing_quote ? 1 : 0);
if (add_space) {
if (quote != L'\0' && unescaped_quote(command_line, insertion_point) != quote) {
// This is a quoted parameter, first print a quote.
diff --git a/tests/bind.expect b/tests/bind.expect
index 7589fa8e..7c594241 100644
--- a/tests/bind.expect
+++ b/tests/bind.expect
@@ -199,3 +199,23 @@ expect_prompt -re {\r\nmno pqrt\r\n} {
} unmatched {
puts stderr "emacs transpose words fail, 100ms timeout: long delay"
}
+
+# Verify special characters, such as \cV, are not intercepted by the kernel
+# tty driver. Rather, they can be bound and handled by fish.
+send "bind \\cV 'echo ctrl-v seen'\r"
+expect_prompt
+send "\026\r"
+expect_prompt -re {ctrl-v seen} {
+ puts "ctrl-v seen"
+} unmatched {
+ puts stderr "ctrl-v not seen"
+}
+
+send "bind \\cO 'echo ctrl-o seen'\r"
+expect_prompt
+send "\017\r"
+expect_prompt -re {ctrl-o seen} {
+ puts "ctrl-o seen"
+} unmatched {
+ puts stderr "ctrl-o not seen"
+}
diff --git a/tests/bind.expect.out b/tests/bind.expect.out
index f74d54b2..07f09fde 100644
--- a/tests/bind.expect.out
+++ b/tests/bind.expect.out
@@ -13,3 +13,5 @@ default-mode custom timeout set correctly
emacs transpose words, 100ms timeout: no delay
emacs transpose words, 100ms timeout: short delay
emacs transpose words, 100ms timeout: long delay
+ctrl-v seen
+ctrl-o seen