mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Capture read command contents without displaying it via a silent flag.
Implement a `read --silent` flag. This echos the input using an obfuscation character.
This commit is contained in:
parent
da09a915f2
commit
8213885491
7 changed files with 56 additions and 20 deletions
|
@ -1976,9 +1976,9 @@ static int builtin_random(parser_t &parser, io_streams_t &streams, wchar_t **arg
|
||||||
|
|
||||||
/// Read from the tty. This is only valid when the stream is stdin and it is attached to a tty and
|
/// Read from the tty. This is only valid when the stream is stdin and it is attached to a tty and
|
||||||
/// we weren't asked to split on null characters.
|
/// we weren't asked to split on null characters.
|
||||||
static int read_interactive(wcstring &buff, int nchars, bool shell, const wchar_t *mode_name,
|
static int read_interactive(wcstring &buff, int nchars, bool shell, bool silent,
|
||||||
const wchar_t *prompt, const wchar_t *right_prompt,
|
const wchar_t *mode_name, const wchar_t *prompt,
|
||||||
const wchar_t *commandline) {
|
const wchar_t *right_prompt, const wchar_t *commandline) {
|
||||||
int exit_res = STATUS_BUILTIN_OK;
|
int exit_res = STATUS_BUILTIN_OK;
|
||||||
const wchar_t *line;
|
const wchar_t *line;
|
||||||
|
|
||||||
|
@ -1994,6 +1994,7 @@ static int read_interactive(wcstring &buff, int nchars, bool shell, const wchar_
|
||||||
reader_set_allow_autosuggesting(false);
|
reader_set_allow_autosuggesting(false);
|
||||||
reader_set_expand_abbreviations(false);
|
reader_set_expand_abbreviations(false);
|
||||||
reader_set_exit_on_interrupt(true);
|
reader_set_exit_on_interrupt(true);
|
||||||
|
reader_set_silent_status(silent);
|
||||||
|
|
||||||
reader_set_buffer(commandline, wcslen(commandline));
|
reader_set_buffer(commandline, wcslen(commandline));
|
||||||
proc_push_interactive(1);
|
proc_push_interactive(1);
|
||||||
|
@ -2137,9 +2138,10 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
|
||||||
int nchars = 0;
|
int nchars = 0;
|
||||||
bool shell = false;
|
bool shell = false;
|
||||||
bool array = false;
|
bool array = false;
|
||||||
|
bool silent = false;
|
||||||
bool split_null = false;
|
bool split_null = false;
|
||||||
|
|
||||||
const wchar_t *short_options = L"ac:ghlm:n:p:suxzP:UR:";
|
const wchar_t *short_options = L"ac:ghilm:n:p:suxzP:UR:";
|
||||||
const struct woption long_options[] = {{L"export", no_argument, NULL, 'x'},
|
const struct woption long_options[] = {{L"export", no_argument, NULL, 'x'},
|
||||||
{L"global", no_argument, NULL, 'g'},
|
{L"global", no_argument, NULL, 'g'},
|
||||||
{L"local", no_argument, NULL, 'l'},
|
{L"local", no_argument, NULL, 'l'},
|
||||||
|
@ -2150,6 +2152,7 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
|
||||||
{L"right-prompt", required_argument, NULL, 'R'},
|
{L"right-prompt", required_argument, NULL, 'R'},
|
||||||
{L"command", required_argument, NULL, 'c'},
|
{L"command", required_argument, NULL, 'c'},
|
||||||
{L"mode-name", required_argument, NULL, 'm'},
|
{L"mode-name", required_argument, NULL, 'm'},
|
||||||
|
{L"silent", no_argument, NULL, 'i'},
|
||||||
{L"nchars", required_argument, NULL, 'n'},
|
{L"nchars", required_argument, NULL, 'n'},
|
||||||
{L"shell", no_argument, NULL, 's'},
|
{L"shell", no_argument, NULL, 's'},
|
||||||
{L"array", no_argument, NULL, 'a'},
|
{L"array", no_argument, NULL, 'a'},
|
||||||
|
@ -2226,6 +2229,10 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
|
||||||
array = true;
|
array = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case L'i': {
|
||||||
|
silent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case L'z': {
|
case L'z': {
|
||||||
split_null = true;
|
split_null = true;
|
||||||
break;
|
break;
|
||||||
|
@ -2302,8 +2309,8 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
|
||||||
// We should read interactively using reader_readline(). This does not support splitting on
|
// We should read interactively using reader_readline(). This does not support splitting on
|
||||||
// null. The call to reader_readline may change woptind, so we save and restore it.
|
// null. The call to reader_readline may change woptind, so we save and restore it.
|
||||||
int saved_woptind = w.woptind;
|
int saved_woptind = w.woptind;
|
||||||
exit_res =
|
exit_res = read_interactive(buff, nchars, shell, silent, mode_name, prompt, right_prompt,
|
||||||
read_interactive(buff, nchars, shell, mode_name, prompt, right_prompt, commandline);
|
commandline);
|
||||||
w.woptind = saved_woptind;
|
w.woptind = saved_woptind;
|
||||||
} else if (!nchars && !stream_stdin_is_a_tty && lseek(streams.stdin_fd, 0, SEEK_CUR) != -1) {
|
} else if (!nchars && !stream_stdin_is_a_tty && lseek(streams.stdin_fd, 0, SEEK_CUR) != -1) {
|
||||||
exit_res = read_in_chunks(streams.stdin_fd, buff, split_null);
|
exit_res = read_in_chunks(streams.stdin_fd, buff, split_null);
|
||||||
|
|
|
@ -50,6 +50,7 @@ static bool thread_asserts_cfg_for_testing = false;
|
||||||
|
|
||||||
wchar_t ellipsis_char;
|
wchar_t ellipsis_char;
|
||||||
wchar_t omitted_newline_char;
|
wchar_t omitted_newline_char;
|
||||||
|
wchar_t obfuscation_read_char;
|
||||||
bool g_profiling_active = false;
|
bool g_profiling_active = false;
|
||||||
const wchar_t *program_name;
|
const wchar_t *program_name;
|
||||||
int debug_level = 1; // default maximum debug output level (errors and warnings)
|
int debug_level = 1; // default maximum debug output level (errors and warnings)
|
||||||
|
@ -457,6 +458,9 @@ void fish_setlocale() {
|
||||||
|
|
||||||
// Use the Unicode "return" symbol if it can be encoded using the current locale.
|
// Use the Unicode "return" symbol if it can be encoded using the current locale.
|
||||||
omitted_newline_char = can_be_encoded(L'\x23CE') ? L'\x23CE' : L'~';
|
omitted_newline_char = can_be_encoded(L'\x23CE') ? L'\x23CE' : L'~';
|
||||||
|
|
||||||
|
// solid circle unicode character if it is able, fallback to the hash character
|
||||||
|
obfuscation_read_char = can_be_encoded(L'\u25cf') ? L'\u25cf' : L'#';
|
||||||
}
|
}
|
||||||
|
|
||||||
long read_blocked(int fd, void *buf, size_t count) {
|
long read_blocked(int fd, void *buf, size_t count) {
|
||||||
|
|
|
@ -159,6 +159,9 @@ extern wchar_t ellipsis_char;
|
||||||
/// Character representing an omitted newline at the end of text.
|
/// Character representing an omitted newline at the end of text.
|
||||||
extern wchar_t omitted_newline_char;
|
extern wchar_t omitted_newline_char;
|
||||||
|
|
||||||
|
/// Character used for the silent mode of the read command
|
||||||
|
extern wchar_t obfuscation_read_char;
|
||||||
|
|
||||||
/// The verbosity level of fish. If a call to debug has a severity level higher than \c debug_level,
|
/// The verbosity level of fish. If a call to debug has a severity level higher than \c debug_level,
|
||||||
/// it will not be printed.
|
/// it will not be printed.
|
||||||
extern int debug_level;
|
extern int debug_level;
|
||||||
|
|
|
@ -168,6 +168,8 @@ class reader_data_t {
|
||||||
bool suppress_autosuggestion;
|
bool suppress_autosuggestion;
|
||||||
/// Whether abbreviations are expanded.
|
/// Whether abbreviations are expanded.
|
||||||
bool expand_abbreviations;
|
bool expand_abbreviations;
|
||||||
|
/// Silent mode used for password input on the read command
|
||||||
|
bool silent;
|
||||||
/// The representation of the current screen contents.
|
/// The representation of the current screen contents.
|
||||||
screen_t screen;
|
screen_t screen;
|
||||||
/// The history.
|
/// The history.
|
||||||
|
@ -256,13 +258,14 @@ class reader_data_t {
|
||||||
|
|
||||||
/// Constructor
|
/// Constructor
|
||||||
reader_data_t()
|
reader_data_t()
|
||||||
: allow_autosuggestion(0),
|
: allow_autosuggestion(false),
|
||||||
suppress_autosuggestion(0),
|
suppress_autosuggestion(false),
|
||||||
expand_abbreviations(0),
|
expand_abbreviations(false),
|
||||||
|
silent(false),
|
||||||
history(0),
|
history(0),
|
||||||
token_history_pos(0),
|
token_history_pos(0),
|
||||||
search_pos(0),
|
search_pos(0),
|
||||||
sel_active(0),
|
sel_active(false),
|
||||||
sel_begin_pos(0),
|
sel_begin_pos(0),
|
||||||
sel_start_pos(0),
|
sel_start_pos(0),
|
||||||
sel_stop_pos(0),
|
sel_stop_pos(0),
|
||||||
|
@ -270,13 +273,13 @@ class reader_data_t {
|
||||||
complete_func(0),
|
complete_func(0),
|
||||||
highlight_function(0),
|
highlight_function(0),
|
||||||
test_func(0),
|
test_func(0),
|
||||||
end_loop(0),
|
end_loop(false),
|
||||||
prev_end_loop(0),
|
prev_end_loop(false),
|
||||||
next(0),
|
next(0),
|
||||||
search_mode(0),
|
search_mode(0),
|
||||||
repaint_needed(0),
|
repaint_needed(false),
|
||||||
screen_reset_needed(0),
|
screen_reset_needed(false),
|
||||||
exit_on_interrupt(0) {}
|
exit_on_interrupt(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Sets the command line contents, without clearing the pager.
|
/// Sets the command line contents, without clearing the pager.
|
||||||
|
@ -412,8 +415,13 @@ static void reader_repaint() {
|
||||||
// Update the indentation.
|
// Update the indentation.
|
||||||
data->indents = parse_util_compute_indents(cmd_line->text);
|
data->indents = parse_util_compute_indents(cmd_line->text);
|
||||||
|
|
||||||
|
wcstring full_line;
|
||||||
|
if (data->silent) {
|
||||||
|
full_line = wcstring(cmd_line->text.length(), obfuscation_read_char);
|
||||||
|
} else {
|
||||||
// Combine the command and autosuggestion into one string.
|
// Combine the command and autosuggestion into one string.
|
||||||
wcstring full_line = combine_command_and_autosuggestion(cmd_line->text, data->autosuggestion);
|
full_line = combine_command_and_autosuggestion(cmd_line->text, data->autosuggestion);
|
||||||
|
}
|
||||||
|
|
||||||
size_t len = full_line.size();
|
size_t len = full_line.size();
|
||||||
if (len < 1) len = 1;
|
if (len < 1) len = 1;
|
||||||
|
@ -439,9 +447,9 @@ static void reader_repaint() {
|
||||||
bool focused_on_pager = data->active_edit_line() == &data->pager.search_field_line;
|
bool focused_on_pager = data->active_edit_line() == &data->pager.search_field_line;
|
||||||
size_t cursor_position = focused_on_pager ? data->pager.cursor_position() : cmd_line->position;
|
size_t cursor_position = focused_on_pager ? data->pager.cursor_position() : cmd_line->position;
|
||||||
|
|
||||||
s_write(&data->screen, data->left_prompt_buff, data->right_prompt_buff, full_line,
|
s_write(&data->screen, data->left_prompt_buff, data->right_prompt_buff, full_line, cmd_line->size(),
|
||||||
cmd_line->size(), &colors[0], &indents[0], cursor_position,
|
&colors[0], &indents[0], cursor_position, data->current_page_rendering,
|
||||||
data->current_page_rendering, focused_on_pager);
|
focused_on_pager);
|
||||||
|
|
||||||
data->repaint_needed = false;
|
data->repaint_needed = false;
|
||||||
}
|
}
|
||||||
|
@ -2044,6 +2052,8 @@ void reader_set_test_function(parser_test_error_bits_t (*f)(const wchar_t *)) {
|
||||||
|
|
||||||
void reader_set_exit_on_interrupt(bool i) { data->exit_on_interrupt = i; }
|
void reader_set_exit_on_interrupt(bool i) { data->exit_on_interrupt = i; }
|
||||||
|
|
||||||
|
void reader_set_silent_status(bool flag) { data->silent = flag; }
|
||||||
|
|
||||||
void reader_import_history_if_necessary(void) {
|
void reader_import_history_if_necessary(void) {
|
||||||
// Import history from older location (config path) if our current history is empty.
|
// Import history from older location (config path) if our current history is empty.
|
||||||
if (data->history && data->history->is_empty()) {
|
if (data->history && data->history->is_empty()) {
|
||||||
|
|
|
@ -189,6 +189,8 @@ void reader_set_expand_abbreviations(bool flag);
|
||||||
/// Sets whether the reader should exit on ^C.
|
/// Sets whether the reader should exit on ^C.
|
||||||
void reader_set_exit_on_interrupt(bool flag);
|
void reader_set_exit_on_interrupt(bool flag);
|
||||||
|
|
||||||
|
void reader_set_silent_status(bool f);
|
||||||
|
|
||||||
/// Returns true if the shell is exiting, 0 otherwise.
|
/// Returns true if the shell is exiting, 0 otherwise.
|
||||||
bool shell_is_exiting();
|
bool shell_is_exiting();
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,15 @@ expect_prompt
|
||||||
expect_marker 2
|
expect_marker 2
|
||||||
print_var_contents foo
|
print_var_contents foo
|
||||||
|
|
||||||
|
# read -i
|
||||||
|
|
||||||
|
send_line "read -i foo"
|
||||||
|
expect_read_prompt
|
||||||
|
send_line -h "read_i\r_marker 3"
|
||||||
|
expect_prompt
|
||||||
|
expect_marker 3
|
||||||
|
print_var_contents foo
|
||||||
|
|
||||||
# read -n
|
# read -n
|
||||||
|
|
||||||
send_line "read -n 3 foo"
|
send_line "read -n 3 foo"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
$foo: 'text'
|
$foo: 'text'
|
||||||
$foo: 'again'
|
$foo: 'again'
|
||||||
$foo: 'bar'
|
$foo: 'bar'
|
||||||
|
$foo: 'read_i'
|
||||||
$foo: '123'
|
$foo: '123'
|
||||||
$foo: '456'
|
$foo: '456'
|
||||||
$foo: 'hello'
|
$foo: 'hello'
|
||||||
|
|
Loading…
Reference in a new issue