let read take a simple string for the prompt

Fixes #802
This commit is contained in:
Kurtis Rader 2017-03-25 08:20:55 -07:00
parent e1c3ec25ab
commit 38c851f4cf
3 changed files with 49 additions and 32 deletions

View file

@ -10,6 +10,7 @@
- The `functions --metadata --verbose` output now includes the function description (#597).
- Completions for `helm` added (#3829).
- Empty CDPATH elements are now equivalent to "." (#2106).
- The `read` command now accepts simple strings for the prompt rather than fish script via the new `-P` and `--prompt-str` flags (#802).
---

View file

@ -23,6 +23,8 @@ The following options are available:
- `-p PROMPT_CMD` or `--prompt=PROMPT_CMD` uses the output of the shell command `PROMPT_CMD` as the prompt for the interactive mode. The default prompt command is <code>set_color green; echo read; set_color normal; echo "> "</code>.
- `-P PROMPT_STR` or `--prompt-str=PROMPT_STR` uses the string as the prompt for the interactive mode. It is equivalent to <code>echo PROMPT_STR</code> and is provided solely to avoid the need to frame the prompt as a command. All special characters in the string are automatically escaped before being passed to the <code>echo</code> command.
- `-R RIGHT_PROMPT_CMD` or `--right-prompt=RIGHT_PROMPT_CMD` uses the output of the shell command `RIGHT_PROMPT_CMD` as the right prompt for the interactive mode. There is no default right prompt command.
- `-s` or `--shell` enables syntax highlighting, tab completions and command termination suitable for entering shellscript code in the interactive mode.

View file

@ -2123,11 +2123,13 @@ static int read_one_char_at_a_time(int fd, wcstring &buff, int nchars, bool spli
/// The read builtin. Reads from stdin and stores the values in environment variables.
static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
wgetopter_t w;
wcstring buff;
wchar_t *cmd = argv[0];
int argc = builtin_count_args(argv);
int place = ENV_USER;
const wchar_t *prompt = DEFAULT_READ_PROMPT;
wcstring prompt_cmd;
const wchar_t *prompt = NULL;
const wchar_t *prompt_str = NULL;
const wchar_t *right_prompt = L"";
const wchar_t *commandline = L"";
int exit_res = STATUS_BUILTIN_OK;
@ -2137,36 +2139,28 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
bool array = false;
bool split_null = false;
while (1) {
static const struct woption long_options[] = {{L"export", no_argument, 0, 'x'},
{L"global", no_argument, 0, 'g'},
{L"local", no_argument, 0, 'l'},
{L"universal", no_argument, 0, 'U'},
{L"unexport", no_argument, 0, 'u'},
{L"prompt", required_argument, 0, 'p'},
{L"right-prompt", required_argument, 0, 'R'},
{L"command", required_argument, 0, 'c'},
{L"mode-name", required_argument, 0, 'm'},
{L"nchars", required_argument, 0, 'n'},
{L"shell", no_argument, 0, 's'},
{L"array", no_argument, 0, 'a'},
{L"null", no_argument, 0, 'z'},
{L"help", no_argument, 0, 'h'},
{0, 0, 0, 0}};
int opt_index = 0;
int opt = w.wgetopt_long(argc, argv, L"xglUup:R:c:hm:n:saz", long_options, &opt_index);
if (opt == -1) break;
const wchar_t *short_options = L"ac:ghlm:n:p:suxzP:UR:";
const struct woption long_options[] = {{L"export", no_argument, NULL, 'x'},
{L"global", no_argument, NULL, 'g'},
{L"local", no_argument, NULL, 'l'},
{L"universal", no_argument, NULL, 'U'},
{L"unexport", no_argument, NULL, 'u'},
{L"prompt", required_argument, NULL, 'p'},
{L"prompt-str", required_argument, NULL, 'P'},
{L"right-prompt", required_argument, NULL, 'R'},
{L"command", required_argument, NULL, 'c'},
{L"mode-name", required_argument, NULL, 'm'},
{L"nchars", required_argument, NULL, 'n'},
{L"shell", no_argument, NULL, 's'},
{L"array", no_argument, NULL, 'a'},
{L"null", no_argument, NULL, 'z'},
{L"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}};
int opt;
wgetopter_t w;
while ((opt = w.wgetopt_long(argc, argv, short_options, long_options, NULL)) != -1) {
switch (opt) {
case 0: {
if (long_options[opt_index].flag != 0) break;
streams.err.append_format(BUILTIN_ERR_UNKNOWN, argv[0],
long_options[opt_index].name);
builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
case L'x': {
place |= ENV_EXPORT;
break;
@ -2191,6 +2185,10 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
prompt = w.woptarg;
break;
}
case L'P': {
prompt_str = w.woptarg;
break;
}
case L'R': {
right_prompt = w.woptarg;
break;
@ -2236,20 +2234,36 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
builtin_print_help(parser, streams, argv[0], streams.out);
return STATUS_BUILTIN_OK;
}
case ':': {
streams.err.append_format(BUILTIN_ERR_MISSING, cmd, argv[w.woptind - 1]);
return STATUS_BUILTIN_ERROR;
}
case L'?': {
builtin_unknown_option(parser, streams, argv[0], argv[w.woptind - 1]);
return STATUS_BUILTIN_ERROR;
}
default: {
DIE("unexpected opt");
DIE("unexpected retval from wgetopt_long");
break;
}
}
}
if (prompt && prompt_str) {
streams.err.append_format(_(L"%ls: You can't specify both -p and -P\n"), argv[0]);
builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}
if (prompt_str) {
prompt_cmd = L"echo " + escape_string(prompt_str, ESCAPE_ALL);
prompt = prompt_cmd.c_str();
} else if (!prompt) {
prompt = DEFAULT_READ_PROMPT;
}
if ((place & ENV_UNEXPORT) && (place & ENV_EXPORT)) {
streams.err.append_format(BUILTIN_ERR_EXPUNEXP, argv[0]);
builtin_print_help(parser, streams, argv[0], streams.err);
return STATUS_BUILTIN_ERROR;
}