aboutsummaryrefslogtreecommitdiffhomepage
path: root/builtin.cpp
diff options
context:
space:
mode:
authorGravatar ridiculousfish <corydoras@ridiculousfish.com>2014-08-21 21:36:39 -0700
committerGravatar ridiculousfish <corydoras@ridiculousfish.com>2014-08-21 21:36:39 -0700
commit033373f078db74b26dc458252734099482dc8a1a (patch)
treee0bce4834f17059cc83942eb4e3b0c036e6c2855 /builtin.cpp
parentd63db59adeb84251c3ab5fe1b13981e44571bf31 (diff)
parent16e50c258a5d5cecc76e1f2dc29a62be88a1ac2f (diff)
Merge branch 'make_type_better' of github.com:kballard/fish-shell into kballard-make_type_better
Diffstat (limited to 'builtin.cpp')
-rw-r--r--builtin.cpp164
1 files changed, 154 insertions, 10 deletions
diff --git a/builtin.cpp b/builtin.cpp
index 0213f5cb..efe28f90 100644
--- a/builtin.cpp
+++ b/builtin.cpp
@@ -1054,6 +1054,87 @@ static int builtin_emit(parser_t &parser, wchar_t **argv)
/**
+ Implementation of the builtin 'command'. Actual command running is handled by
+ the parser, this just processes the flags.
+*/
+static int builtin_command(parser_t &parser, wchar_t **argv)
+{
+ int argc=builtin_count_args(argv);
+ int print_path=0;
+
+ woptind=0;
+
+ static const struct woption
+ long_options[] =
+ {
+ { L"search", no_argument, 0, 's' },
+ { L"help", no_argument, 0, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ while (1)
+ {
+ int opt_index = 0;
+
+ int opt = wgetopt_long(argc,
+ argv,
+ L"svh",
+ long_options,
+ &opt_index);
+ if (opt == -1)
+ break;
+
+ switch (opt)
+ {
+ case 0:
+ if (long_options[opt_index].flag != 0)
+ break;
+ append_format(stderr_buffer,
+ BUILTIN_ERR_UNKNOWN,
+ argv[0],
+ long_options[opt_index].name);
+ builtin_print_help(parser, argv[0], stderr_buffer);
+ return STATUS_BUILTIN_ERROR;
+
+ case 'h':
+ builtin_print_help(parser, argv[0], stdout_buffer);
+ return STATUS_BUILTIN_OK;
+
+ case 's':
+ case 'v':
+ print_path=1;
+ break;
+
+ case '?':
+ builtin_unknown_option(parser, argv[0], argv[woptind-1]);
+ return STATUS_BUILTIN_ERROR;
+
+ }
+
+ }
+
+ if (!print_path)
+ {
+ builtin_print_help(parser, argv[0], stdout_buffer);
+ return STATUS_BUILTIN_ERROR;
+ }
+
+ int found=0;
+
+ for (int idx = woptind; argv[idx]; ++idx)
+ {
+ const wchar_t *command_name = argv[idx];
+ wcstring path;
+ if (path_get_path(command_name, &path))
+ {
+ append_format(stdout_buffer, L"%ls\n", path.c_str());
+ ++found;
+ }
+ }
+ return found ? STATUS_BUILTIN_OK : STATUS_BUILTIN_ERROR;
+}
+
+/**
A generic bultin that only supports showing a help message. This is
only a placeholder that prints the help message. Useful for
commands that live in the parser.
@@ -2233,6 +2314,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
int exit_res=STATUS_BUILTIN_OK;
const wchar_t *mode_name = READ_MODE_NAME;
int shell = 0;
+ int array = 0;
woptind=0;
@@ -2278,6 +2360,10 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
}
,
{
+ L"array", no_argument, 0, 'a'
+ }
+ ,
+ {
L"help", no_argument, 0, 'h'
}
,
@@ -2291,7 +2377,7 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
int opt = wgetopt_long(argc,
argv,
- L"xglUup:c:hm:s",
+ L"xglUup:c:hm:sa",
long_options,
&opt_index);
if (opt == -1)
@@ -2346,6 +2432,10 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
shell = 1;
break;
+ case 'a':
+ array = 1;
+ break;
+
case 'h':
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_OK;
@@ -2378,6 +2468,14 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
return STATUS_BUILTIN_ERROR;
}
+ if (array && woptind+1 != argc)
+ {
+ append_format(stderr_buffer, _(L"%ls: --array option requires a single variable name.\n"), argv[0]);
+ builtin_print_help(parser, argv[0], stderr_buffer);
+
+ return STATUS_BUILTIN_ERROR;
+ }
+
/*
Verify all variable names
*/
@@ -2512,18 +2610,64 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
wchar_t *state;
env_var_t ifs = env_get_string(L"IFS");
- if (ifs.missing())
- ifs = L"";
- nxt = wcstok(buff, (i<argc-1)?ifs.c_str():L"", &state);
+ if (ifs.missing_or_empty())
+ {
+ /* Every character is a separate token */
+ size_t bufflen = wcslen(buff);
+ if (array)
+ {
+ if (bufflen > 0)
+ {
+ wcstring chars(bufflen+(bufflen-1), ARRAY_SEP);
+ for (size_t j=0; j<bufflen; ++j)
+ {
+ chars[j*2] = buff[j];
+ }
+ env_set(argv[i], chars.c_str(), place);
+ }
+ else
+ {
+ env_set(argv[i], NULL, place);
+ }
+ }
+ else
+ {
+ size_t j = 0;
+ for (; i+1 < argc; ++i)
+ {
+ env_set(argv[i], j < bufflen ? (wchar_t[2]){buff[j], 0} : L"", place);
+ if (j < bufflen) ++j;
+ }
+ if (i < argc) env_set(argv[i], &buff[j], place);
+ }
+ }
+ else if (array)
+ {
+ wcstring tokens;
+ tokens.reserve(wcslen(buff));
+ bool empty = true;
- while (i<argc)
+ for (nxt = wcstok(buff, ifs.c_str(), &state); nxt != 0; nxt = wcstok(0, ifs.c_str(), &state))
+ {
+ if (! tokens.empty()) tokens.push_back(ARRAY_SEP);
+ tokens.append(nxt);
+ empty = false;
+ }
+ env_set(argv[i], empty ? NULL : tokens.c_str(), place);
+ }
+ else
{
- env_set(argv[i], nxt != 0 ? nxt: L"", place);
+ nxt = wcstok(buff, (i<argc-1)?ifs.c_str():L"", &state);
+
+ while (i<argc)
+ {
+ env_set(argv[i], nxt != 0 ? nxt: L"", place);
- i++;
- if (nxt != 0)
- nxt = wcstok(0, (i<argc-1)?ifs.c_str():L"", &state);
+ i++;
+ if (nxt != 0)
+ nxt = wcstok(0, (i<argc-1)?ifs.c_str():L"", &state);
+ }
}
}
@@ -3726,7 +3870,7 @@ static const builtin_data_t builtin_datas[]=
{ L"builtin", &builtin_builtin, N_(L"Run a builtin command instead of a function") },
{ L"case", &builtin_generic, N_(L"Conditionally execute a block of commands") },
{ L"cd", &builtin_cd, N_(L"Change working directory") },
- { L"command", &builtin_generic, N_(L"Run a program instead of a function or builtin") },
+ { L"command", &builtin_command, N_(L"Run a program instead of a function or builtin") },
{ L"commandline", &builtin_commandline, N_(L"Set or get the commandline") },
{ L"complete", &builtin_complete, N_(L"Edit command specific completions") },
{ L"contains", &builtin_contains, N_(L"Search for a specified string in a list") },