mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-25 18:03:37 +08:00
Make fish_key_reader's output simpler (#8467)
* fish_key_reader: Simplify default output It now only prints the bind statement. Timing information and such is relegated to a separate "verbose" mode. * Adjust fish_key_reader docs * Adjust tests
This commit is contained in:
parent
084458bc47
commit
f2fd30df03
|
@ -13,14 +13,16 @@ Synopsis
|
||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
``fish_key_reader`` is used to study input received from the terminal and can help with key binds. The program is interactive and works on standard input. Individual characters themselves and their hexadecimal values are displayed.
|
``fish_key_reader`` is used to explain how you would bind a certain key sequence. By default, it prints the :ref:`bind <cmd-bind>` command for one key sequence read interactively over standard input.
|
||||||
|
|
||||||
The tool will write an example :ref:`bind <cmd-bind>` command matching the character sequence captured to stdout. If the character sequence matches a special key name (see ``bind --key-names``), both ``bind CHARS ...`` and ``bind -k KEYNAME ...`` usage will be shown. Additional details about the characters received, such as the delay between chars, are written to stderr.
|
If the character sequence matches a special key name (see ``bind --key-names``), both ``bind CHARS ...`` and ``bind -k KEYNAME ...`` usage will be shown. In verbose mode (enabled by passing ``--verbose``), additional details about the characters received, such as the delay between chars, are written to stderr.
|
||||||
|
|
||||||
The following options are available:
|
The following options are available:
|
||||||
|
|
||||||
- ``-c`` or ``--continuous`` begins a session where multiple key sequences can be inspected. By default the program exits after capturing a single key sequence.
|
- ``-c`` or ``--continuous`` begins a session where multiple key sequences can be inspected. By default the program exits after capturing a single key sequence.
|
||||||
|
|
||||||
|
- ``-V`` or ``--verbose`` tells fish_key_reader to output timing information and explain the sequence in more detail.
|
||||||
|
|
||||||
- ``-h`` or ``--help`` prints usage information.
|
- ``-h`` or ``--help`` prints usage information.
|
||||||
|
|
||||||
- ``-v`` or ``--version`` prints fish_key_reader's version and exits.
|
- ``-v`` or ``--version`` prints fish_key_reader's version and exits.
|
||||||
|
@ -28,7 +30,7 @@ The following options are available:
|
||||||
Usage Notes
|
Usage Notes
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
The delay in milliseconds since the previous character was received is included in the diagnostic information written to stderr. This information may be useful to determine the optimal ``fish_escape_delay_ms`` setting or learn the amount of lag introduced by tools like ``ssh``, ``mosh`` or ``tmux``.
|
In verbose mode, the delay in milliseconds since the previous character was received is included in the diagnostic information written to stderr. This information may be useful to determine the optimal ``fish_escape_delay_ms`` setting or learn the amount of lag introduced by tools like ``ssh``, ``mosh`` or ``tmux``.
|
||||||
|
|
||||||
``fish_key_reader`` intentionally disables handling of many signals. To terminate ``fish_key_reader`` in ``--continuous`` mode do:
|
``fish_key_reader`` intentionally disables handling of many signals. To terminate ``fish_key_reader`` in ``--continuous`` mode do:
|
||||||
|
|
||||||
|
@ -36,3 +38,21 @@ The delay in milliseconds since the previous character was received is included
|
||||||
- press :kbd:`Control`\ +\ :kbd:`D` twice, or
|
- press :kbd:`Control`\ +\ :kbd:`D` twice, or
|
||||||
- type ``exit``, or
|
- type ``exit``, or
|
||||||
- type ``quit``
|
- type ``quit``
|
||||||
|
|
||||||
|
Example
|
||||||
|
-------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
> fish_key_reader
|
||||||
|
Press a key:
|
||||||
|
# press up-arrow
|
||||||
|
bind \e\[A 'do something'
|
||||||
|
|
||||||
|
> fish_key_reader --verbose
|
||||||
|
Press a key:
|
||||||
|
# press alt+enter
|
||||||
|
hex: 1B char: \c[ (or \e)
|
||||||
|
( 0.027 ms) hex: D char: \cM (or \r)
|
||||||
|
bind \e\r 'do something'
|
||||||
|
|
||||||
|
|
|
@ -487,15 +487,11 @@ The key sequence (the ``\cc``) here depends on your setup, in particular the ter
|
||||||
|
|
||||||
> fish_key_reader # pressing control-c
|
> fish_key_reader # pressing control-c
|
||||||
Press a key:
|
Press a key:
|
||||||
hex: 3 char: \cC
|
|
||||||
Press [ctrl-C] again to exit
|
Press [ctrl-C] again to exit
|
||||||
bind \cC 'do something'
|
bind \cC 'do something'
|
||||||
|
|
||||||
> fish_key_reader # pressing the right-arrow
|
> fish_key_reader # pressing the right-arrow
|
||||||
Press a key:
|
Press a key:
|
||||||
hex: 1B char: \c[ (or \e)
|
|
||||||
( 0.077 ms) hex: 5B char: [
|
|
||||||
( 0.037 ms) hex: 43 char: C
|
|
||||||
bind \e\[C 'do something'
|
bind \e\[C 'do something'
|
||||||
|
|
||||||
Note that some key combinations are indistinguishable or unbindable. For instance control-i *is the same* as the tab key. This is a terminal limitation that fish can't do anything about.
|
Note that some key combinations are indistinguishable or unbindable. For instance control-i *is the same* as the tab key. This is a terminal limitation that fish can't do anything about.
|
||||||
|
|
|
@ -205,23 +205,25 @@ static bool output_matching_key_name(wchar_t wc) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double output_elapsed_time(double prev_tstamp, bool first_char_seen) {
|
static double output_elapsed_time(double prev_tstamp, bool first_char_seen, bool verbose) {
|
||||||
// How much time has passed since the previous char was received in microseconds.
|
// How much time has passed since the previous char was received in microseconds.
|
||||||
double now = timef();
|
double now = timef();
|
||||||
long long int delta_tstamp_us = 1000000 * (now - prev_tstamp);
|
long long int delta_tstamp_us = 1000000 * (now - prev_tstamp);
|
||||||
|
|
||||||
if (delta_tstamp_us >= 200000 && first_char_seen) std::fputwc(L'\n', stderr);
|
if (verbose) {
|
||||||
if (delta_tstamp_us >= 1000000) {
|
if (delta_tstamp_us >= 200000 && first_char_seen) std::fputwc(L'\n', stderr);
|
||||||
std::fwprintf(stderr, L" ");
|
if (delta_tstamp_us >= 1000000) {
|
||||||
} else {
|
std::fwprintf(stderr, L" ");
|
||||||
std::fwprintf(stderr, L"(%3lld.%03lld ms) ", delta_tstamp_us / 1000,
|
} else {
|
||||||
delta_tstamp_us % 1000);
|
std::fwprintf(stderr, L"(%3lld.%03lld ms) ", delta_tstamp_us / 1000,
|
||||||
|
delta_tstamp_us % 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process the characters we receive as the user presses keys.
|
/// Process the characters we receive as the user presses keys.
|
||||||
static void process_input(bool continuous_mode) {
|
static void process_input(bool continuous_mode, bool verbose) {
|
||||||
bool first_char_seen = false;
|
bool first_char_seen = false;
|
||||||
double prev_tstamp = 0.0;
|
double prev_tstamp = 0.0;
|
||||||
input_event_queue_t queue;
|
input_event_queue_t queue;
|
||||||
|
@ -244,14 +246,16 @@ static void process_input(bool continuous_mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t wc = evt->get_char();
|
wchar_t wc = evt->get_char();
|
||||||
prev_tstamp = output_elapsed_time(prev_tstamp, first_char_seen);
|
prev_tstamp = output_elapsed_time(prev_tstamp, first_char_seen, verbose);
|
||||||
// Hack for #3189. Do not suggest \c@ as the binding for nul, because a string containing
|
// Hack for #3189. Do not suggest \c@ as the binding for nul, because a string containing
|
||||||
// nul cannot be passed to builtin_bind since it uses C strings. We'll output the name of
|
// nul cannot be passed to builtin_bind since it uses C strings. We'll output the name of
|
||||||
// this key (nul) elsewhere.
|
// this key (nul) elsewhere.
|
||||||
if (wc) {
|
if (wc) {
|
||||||
add_char_to_bind_command(wc, bind_chars);
|
add_char_to_bind_command(wc, bind_chars);
|
||||||
}
|
}
|
||||||
output_info_about_char(wc);
|
if (verbose) {
|
||||||
|
output_info_about_char(wc);
|
||||||
|
}
|
||||||
if (output_matching_key_name(wc)) {
|
if (output_matching_key_name(wc)) {
|
||||||
output_bind_command(bind_chars);
|
output_bind_command(bind_chars);
|
||||||
}
|
}
|
||||||
|
@ -266,7 +270,7 @@ static void process_input(bool continuous_mode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Setup our environment (e.g., tty modes), process key strokes, then reset the environment.
|
/// Setup our environment (e.g., tty modes), process key strokes, then reset the environment.
|
||||||
[[noreturn]] static void setup_and_process_keys(bool continuous_mode) {
|
[[noreturn]] static void setup_and_process_keys(bool continuous_mode, bool verbose) {
|
||||||
set_interactive_session(true);
|
set_interactive_session(true);
|
||||||
set_main_thread();
|
set_main_thread();
|
||||||
setup_fork_guards();
|
setup_fork_guards();
|
||||||
|
@ -288,16 +292,17 @@ static void process_input(bool continuous_mode) {
|
||||||
std::fwprintf(stderr, L"\n");
|
std::fwprintf(stderr, L"\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
process_input(continuous_mode);
|
process_input(continuous_mode, verbose);
|
||||||
restore_term_mode();
|
restore_term_mode();
|
||||||
_exit(0);
|
_exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool parse_flags(int argc, char **argv, bool *continuous_mode) {
|
static bool parse_flags(int argc, char **argv, bool *continuous_mode, bool *verbose) {
|
||||||
const char *short_opts = "+chv";
|
const char *short_opts = "+chvV";
|
||||||
const struct option long_opts[] = {{"continuous", no_argument, nullptr, 'c'},
|
const struct option long_opts[] = {{"continuous", no_argument, nullptr, 'c'},
|
||||||
{"help", no_argument, nullptr, 'h'},
|
{"help", no_argument, nullptr, 'h'},
|
||||||
{"version", no_argument, nullptr, 'v'},
|
{"version", no_argument, nullptr, 'v'},
|
||||||
|
{"verbose", no_argument, nullptr, 'V'},
|
||||||
{nullptr, 0, nullptr, 0}};
|
{nullptr, 0, nullptr, 0}};
|
||||||
int opt;
|
int opt;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
@ -315,6 +320,10 @@ static bool parse_flags(int argc, char **argv, bool *continuous_mode) {
|
||||||
std::fwprintf(stdout, _(L"%ls, version %s\n"), program_name, get_fish_version());
|
std::fwprintf(stdout, _(L"%ls, version %s\n"), program_name, get_fish_version());
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
case 'V': {
|
||||||
|
*verbose = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
// We assume getopt_long() has already emitted a diagnostic msg.
|
// We assume getopt_long() has already emitted a diagnostic msg.
|
||||||
error = true;
|
error = true;
|
||||||
|
@ -337,15 +346,16 @@ static bool parse_flags(int argc, char **argv, bool *continuous_mode) {
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
program_name = L"fish_key_reader";
|
program_name = L"fish_key_reader";
|
||||||
bool continuous_mode = false;
|
bool continuous_mode = false;
|
||||||
|
bool verbose = false;
|
||||||
|
|
||||||
if (!parse_flags(argc, argv, &continuous_mode)) return 1;
|
if (!parse_flags(argc, argv, &continuous_mode, &verbose)) return 1;
|
||||||
|
|
||||||
if (!isatty(STDIN_FILENO)) {
|
if (!isatty(STDIN_FILENO)) {
|
||||||
std::fwprintf(stderr, L"Stdin must be attached to a tty.\n");
|
std::fwprintf(stderr, L"Stdin must be attached to a tty.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_and_process_keys(continuous_mode);
|
setup_and_process_keys(continuous_mode, verbose);
|
||||||
exit_without_destructors(0);
|
exit_without_destructors(0);
|
||||||
return EXIT_FAILURE; // above should exit
|
return EXIT_FAILURE; // above should exit
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ send, sendline, sleep, expect_prompt, expect_re, expect_str = (
|
||||||
)
|
)
|
||||||
expect_prompt()
|
expect_prompt()
|
||||||
|
|
||||||
sendline("exec $fish_key_reader -c")
|
sendline("exec $fish_key_reader -c -V")
|
||||||
|
|
||||||
# Do we get the expected startup prompt?
|
# Do we get the expected startup prompt?
|
||||||
expect_str("Press a key:")
|
expect_str("Press a key:")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user