mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-25 12:23:09 +00:00
Add '--init-command', '-C' to the command line switches.
In order to allow the execution of commands before dropping to an interactive prompt, a new switch, '-C' or '--init-command' has been added to those switches that we accept. The documentation has been updated correspondingly. The original code only supported a single command list to be executed, and this command list terminates the shell when it completes. To allow the new command list to preceed the original one, both have been wrapped in a new container class 'command_line_switches_t'. This is then passed around in place of the list of strings we used previously. I had considered moving the interactive, login and other command line switch states into this container, but doing so would change far more of the code, moving the structure to be available globally, and I wasn't confident of the impact. However, this might be a useful thing to do in the future. A new function, run_command_list, was lifted from the prior execution code, and re-used for both the initial command and the regular command execution.
This commit is contained in:
parent
3b5fdc3fb0
commit
053d940d0a
2 changed files with 49 additions and 16 deletions
|
@ -13,6 +13,8 @@ The following options are available:
|
|||
|
||||
- `-c` or `--command=COMMANDS` evaluate the specified commands instead of reading from the commandline
|
||||
|
||||
- `-C` or `--init-command=COMMANDS` evaluate the specified commands after reading the configuration, before running the command specified by `-c` or reading interactive input
|
||||
|
||||
- `-d` or `--debug-level=DEBUG_LEVEL` specify the verbosity level of fish. A higher number means higher verbosity. The default level is 1.
|
||||
|
||||
- `-i` or `--interactive` specify that fish is to run in interactive mode
|
||||
|
|
63
src/fish.cpp
63
src/fish.cpp
|
@ -1,3 +1,4 @@
|
|||
//
|
||||
// The main loop of the fish program.
|
||||
/*
|
||||
Copyright (C) 2005-2008 Axel Liljencrantz
|
||||
|
@ -57,6 +58,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|||
#define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
// container to hold the options specified within the command line
|
||||
class fish_cmd_opts_t {
|
||||
public:
|
||||
// Commands to be executed in place of interactive shell.
|
||||
std::vector<std::string> batch_cmds;
|
||||
// Commands to execute after the shell's config has been read.
|
||||
std::vector<std::string> postconfig_cmds;
|
||||
};
|
||||
|
||||
|
||||
/// If we are doing profiling, the filename to output to.
|
||||
static const char *s_profiling_output_filename = NULL;
|
||||
|
||||
|
@ -214,10 +225,23 @@ static int read_init(const struct config_paths_t &paths) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int run_command_list(std::vector<std::string> *cmds, const io_chain_t &io) {
|
||||
int res = 1;
|
||||
parser_t &parser = parser_t::principal_parser();
|
||||
|
||||
for (size_t i = 0; i < cmds->size(); i++) {
|
||||
const wcstring cmd_wcs = str2wcstring(cmds->at(i));
|
||||
res = parser.eval(cmd_wcs, io, TOP);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Parse the argument list, return the index of the first non-flag arguments.
|
||||
static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *cmds) {
|
||||
static const char *short_opts = "+hilnvc:p:d:D:";
|
||||
static int fish_parse_opt(int argc, char **argv, fish_cmd_opts_t *opts) {
|
||||
static const char *short_opts = "+hilnvc:C:p:d:D:";
|
||||
static const struct option long_opts[] = {{"command", required_argument, NULL, 'c'},
|
||||
{"init-command", required_argument, NULL, 'C'},
|
||||
{"debug-level", required_argument, NULL, 'd'},
|
||||
{"debug-stack-frames", required_argument, NULL, 'D'},
|
||||
{"interactive", no_argument, NULL, 'i'},
|
||||
|
@ -232,7 +256,11 @@ static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *cmds)
|
|||
while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) {
|
||||
switch (opt) {
|
||||
case 'c': {
|
||||
cmds->push_back(optarg);
|
||||
opts->batch_cmds.push_back(optarg);
|
||||
break;
|
||||
}
|
||||
case 'C': {
|
||||
opts->postconfig_cmds.push_back(optarg);
|
||||
break;
|
||||
}
|
||||
case 'd': {
|
||||
|
@ -251,7 +279,7 @@ static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *cmds)
|
|||
break;
|
||||
}
|
||||
case 'h': {
|
||||
cmds->push_back("__fish_print_help fish");
|
||||
opts->batch_cmds.push_back("__fish_print_help fish");
|
||||
break;
|
||||
}
|
||||
case 'i': {
|
||||
|
@ -305,7 +333,7 @@ static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *cmds)
|
|||
// We are an interactive session if we have not been given an explicit
|
||||
// command or file to execute and stdin is a tty. Note that the -i or
|
||||
// --interactive options also force interactive mode.
|
||||
if (cmds->size() == 0 && optind == argc && isatty(STDIN_FILENO)) {
|
||||
if (opts->batch_cmds.size() == 0 && optind == argc && isatty(STDIN_FILENO)) {
|
||||
is_interactive_session = 1;
|
||||
}
|
||||
|
||||
|
@ -331,8 +359,8 @@ int main(int argc, char **argv) {
|
|||
argv = (char **)dummy_argv; //!OCLINT(parameter reassignment)
|
||||
argc = 1; //!OCLINT(parameter reassignment)
|
||||
}
|
||||
std::vector<std::string> cmds;
|
||||
my_optind = fish_parse_opt(argc, argv, &cmds);
|
||||
fish_cmd_opts_t opts;
|
||||
my_optind = fish_parse_opt(argc, argv, &opts);
|
||||
|
||||
// No-exec is prohibited when in interactive mode.
|
||||
if (is_interactive_session && no_exec) {
|
||||
|
@ -370,19 +398,22 @@ int main(int argc, char **argv) {
|
|||
// Stomp the exit status of any initialization commands (issue #635).
|
||||
proc_set_last_status(STATUS_CMD_OK);
|
||||
|
||||
// Run the commands specified as arguments, if any.
|
||||
if (!cmds.empty()) {
|
||||
// Do something nasty to support OpenSUSE assuming we're bash. This may modify cmds.
|
||||
// Run post-config commands specified as arguments, if any.
|
||||
if (!opts.postconfig_cmds.empty()) {
|
||||
res = run_command_list(&opts.postconfig_cmds, empty_ios);
|
||||
}
|
||||
|
||||
if (!opts.batch_cmds.empty()) {
|
||||
// Run the commands specified as arguments, if any.
|
||||
if (is_login) {
|
||||
fish_xdm_login_hack_hack_hack_hack(&cmds, argc - my_optind, argv + my_optind);
|
||||
}
|
||||
for (size_t i = 0; i < cmds.size(); i++) {
|
||||
const wcstring cmd_wcs = str2wcstring(cmds.at(i));
|
||||
res = parser.eval(cmd_wcs, empty_ios, TOP);
|
||||
// Do something nasty to support OpenSUSE assuming we're bash. This may modify cmds.
|
||||
fish_xdm_login_hack_hack_hack_hack(&opts.batch_cmds, argc - my_optind,
|
||||
argv + my_optind);
|
||||
}
|
||||
res = run_command_list(&opts.batch_cmds, empty_ios);
|
||||
reader_exit(0, 0);
|
||||
} else if (my_optind == argc) {
|
||||
// Interactive mode
|
||||
// Implicitly interactive mode.
|
||||
res = reader_read(STDIN_FILENO, empty_ios);
|
||||
} else {
|
||||
char *file = *(argv + (my_optind++));
|
||||
|
|
Loading…
Reference in a new issue