Merge remote-tracking branch 'upstream/master' into bind_mode

Conflicts:
	builtin.cpp
	reader.cpp
	share/functions/fish_default_key_bindings.fish
This commit is contained in:
Julian Aron Prenner
2014-01-15 15:27:06 +01:00
73 changed files with 24891 additions and 3415 deletions

View File

@@ -64,6 +64,7 @@
#include "expand.h"
#include "path.h"
#include "history.h"
#include "parse_tree.h"
/**
The default prompt for the read command
@@ -164,7 +165,7 @@ static const io_chain_t *real_io;
/**
Counts the number of non null pointers in the specified array
*/
static int builtin_count_args(wchar_t **argv)
static int builtin_count_args(const wchar_t * const * argv)
{
int argc = 1;
while (argv[argc] != NULL)
@@ -243,9 +244,6 @@ wcstring builtin_help_get(parser_t &parser, const wchar_t *name)
static void builtin_print_help(parser_t &parser, const wchar_t *cmd, wcstring &b)
{
int is_short = 0;
if (&b == &stderr_buffer)
{
stderr_buffer.append(parser.current_line());
@@ -259,7 +257,7 @@ static void builtin_print_help(parser_t &parser, const wchar_t *cmd, wcstring &b
wchar_t *str = wcsdup(h.c_str());
if (str)
{
bool is_short = false;
if (&b == &stderr_buffer)
{
@@ -278,7 +276,7 @@ static void builtin_print_help(parser_t &parser, const wchar_t *cmd, wcstring &b
int cut=0;
int i;
is_short = 1;
is_short = true;
/*
First move down 4 lines
@@ -789,7 +787,6 @@ static int builtin_block(parser_t &parser, wchar_t **argv)
int scope=UNSET;
int erase = 0;
int argc=builtin_count_args(argv);
int type = (1<<EVENT_ANY);
woptind=0;
@@ -887,7 +884,7 @@ static int builtin_block(parser_t &parser, wchar_t **argv)
block_t *block = parser.block_at_index(block_idx);
event_blockage_t eb = {};
eb.typemask = type;
eb.typemask = (1<<EVENT_ANY);
switch (scope)
{
@@ -1093,20 +1090,22 @@ static int builtin_emit(parser_t &parser, wchar_t **argv)
static int builtin_generic(parser_t &parser, wchar_t **argv)
{
int argc=builtin_count_args(argv);
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
if (argc == 1)
{
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_ERROR;
}
woptind=0;
static const struct woption
long_options[] =
{
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
}
;
{ L"help", no_argument, 0, 'h' },
{ 0, 0, 0, 0 }
};
while (1)
{
@@ -1803,12 +1802,325 @@ static int builtin_pwd(parser_t &parser, wchar_t **argv)
}
}
/* This is nearly identical to builtin_function, and is intended to be the successor (with no block manipulation, no function/end split) */
int define_function(parser_t &parser, const wcstring_list_t &c_args, const wcstring &contents, wcstring *out_err)
{
assert(out_err != NULL);
/* wgetopt expects 'function' as the first argument. Make a new wcstring_list with that property. */
wcstring_list_t args;
args.push_back(L"function");
args.insert(args.end(), c_args.begin(), c_args.end());
/* Hackish const_cast matches the one in builtin_run */
const null_terminated_array_t<wchar_t> argv_array(args);
wchar_t **argv = const_cast<wchar_t **>(argv_array.get());
int argc = builtin_count_args(argv);
int res=STATUS_BUILTIN_OK;
wchar_t *desc=0;
std::vector<event_t> events;
std::auto_ptr<wcstring_list_t> named_arguments(NULL);
wchar_t *name = 0;
bool shadows = true;
woptind=0;
const struct woption long_options[] =
{
{ L"description", required_argument, 0, 'd' },
{ L"on-signal", required_argument, 0, 's' },
{ L"on-job-exit", required_argument, 0, 'j' },
{ L"on-process-exit", required_argument, 0, 'p' },
{ L"on-variable", required_argument, 0, 'v' },
{ L"on-event", required_argument, 0, 'e' },
{ L"help", no_argument, 0, 'h' },
{ L"argument-names", no_argument, 0, 'a' },
{ L"no-scope-shadowing", no_argument, 0, 'S' },
{ 0, 0, 0, 0 }
};
while (1 && (!res))
{
int opt_index = 0;
int opt = wgetopt_long(argc,
argv,
L"d:s:j:p:v:e:haS",
long_options,
&opt_index);
if (opt == -1)
break;
switch (opt)
{
case 0:
if (long_options[opt_index].flag != 0)
break;
append_format(*out_err,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name);
res = 1;
break;
case 'd':
desc=woptarg;
break;
case 's':
{
int sig = wcs2sig(woptarg);
if (sig < 0)
{
append_format(*out_err,
_(L"%ls: Unknown signal '%ls'\n"),
argv[0],
woptarg);
res=1;
break;
}
events.push_back(event_t::signal_event(sig));
break;
}
case 'v':
{
if (wcsvarname(woptarg))
{
append_format(*out_err,
_(L"%ls: Invalid variable name '%ls'\n"),
argv[0],
woptarg);
res=STATUS_BUILTIN_ERROR;
break;
}
events.push_back(event_t::variable_event(woptarg));
break;
}
case 'e':
{
events.push_back(event_t::generic_event(woptarg));
break;
}
case 'j':
case 'p':
{
pid_t pid;
wchar_t *end;
event_t e(EVENT_ANY);
if ((opt == 'j') &&
(wcscasecmp(woptarg, L"caller") == 0))
{
int job_id = -1;
if (is_subshell)
{
size_t block_idx = 0;
/* Find the outermost substitution block */
for (block_idx = 0; ; block_idx++)
{
const block_t *b = parser.block_at_index(block_idx);
if (b == NULL || b->type() == SUBST)
break;
}
/* Go one step beyond that, to get to the caller */
const block_t *caller_block = parser.block_at_index(block_idx + 1);
if (caller_block != NULL && caller_block->job != NULL)
{
job_id = caller_block->job->job_id;
}
}
if (job_id == -1)
{
append_format(*out_err,
_(L"%ls: Cannot find calling job for event handler\n"),
argv[0]);
res=1;
}
else
{
e.type = EVENT_JOB_ID;
e.param1.job_id = job_id;
}
}
else
{
errno = 0;
pid = fish_wcstoi(woptarg, &end, 10);
if (errno || !end || *end)
{
append_format(*out_err,
_(L"%ls: Invalid process id %ls\n"),
argv[0],
woptarg);
res=1;
break;
}
e.type = EVENT_EXIT;
e.param1.pid = (opt=='j'?-1:1)*abs(pid);
}
if (res)
{
/* nothing */
}
else
{
events.push_back(e);
}
break;
}
case 'a':
if (named_arguments.get() == NULL)
named_arguments.reset(new wcstring_list_t);
break;
case 'S':
shadows = 0;
break;
case 'h':
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_OK;
case '?':
builtin_unknown_option(parser, argv[0], argv[woptind-1]);
res = 1;
break;
}
}
if (!res)
{
if (argc == woptind)
{
append_format(*out_err,
_(L"%ls: Expected function name\n"),
argv[0]);
res=1;
}
else if (wcsfuncname(argv[woptind]))
{
append_format(*out_err,
_(L"%ls: Illegal function name '%ls'\n"),
argv[0],
argv[woptind]);
res=1;
}
else if (parser_keywords_is_reserved(argv[woptind]))
{
append_format(*out_err,
_(L"%ls: The name '%ls' is reserved,\nand can not be used as a function name\n"),
argv[0],
argv[woptind]);
res=1;
}
else if (! wcslen(argv[woptind]))
{
append_format(*out_err, _(L"%ls: No function name given\n"), argv[0]);
}
else
{
name = argv[woptind++];
if (named_arguments.get())
{
while (woptind < argc)
{
if (wcsvarname(argv[woptind]))
{
append_format(*out_err,
_(L"%ls: Invalid variable name '%ls'\n"),
argv[0],
argv[woptind]);
res = STATUS_BUILTIN_ERROR;
break;
}
named_arguments->push_back(argv[woptind++]);
}
}
else if (woptind != argc)
{
append_format(*out_err,
_(L"%ls: Expected one argument, got %d\n"),
argv[0],
argc);
res=1;
}
}
}
if (res)
{
builtin_print_help(parser, argv[0], *out_err);
}
else
{
function_data_t d;
d.name = name;
if (desc)
d.description = desc;
d.events.swap(events);
d.shadows = shadows;
if (named_arguments.get())
d.named_arguments.swap(*named_arguments);
for (size_t i=0; i<d.events.size(); i++)
{
event_t &e = d.events.at(i);
e.function_name = d.name;
}
d.definition = contents.c_str();
// TODO: fix def_offset inside function_add
function_add(d, parser);
}
return res;
}
/**
The function builtin, used for providing subroutines.
It calls various functions from function.c to perform any heavy lifting.
*/
static int builtin_function(parser_t &parser, wchar_t **argv)
{
/* Hack hack hack - with the new parser, this is only invoked for help */
if (parser_use_ast())
{
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_OK;
}
int argc = builtin_count_args(argv);
int res=STATUS_BUILTIN_OK;
wchar_t *desc=0;
@@ -1921,7 +2233,7 @@ static int builtin_function(parser_t &parser, wchar_t **argv)
if (is_subshell)
{
size_t block_idx = 0;
/* Find the outermost substitution block */
for (block_idx = 0; ; block_idx++)
{
@@ -1929,7 +2241,7 @@ static int builtin_function(parser_t &parser, wchar_t **argv)
if (b == NULL || b->type() == SUBST)
break;
}
/* Go one step beyond that, to get to the caller */
const block_t *caller_block = parser.block_at_index(block_idx + 1);
if (caller_block != NULL && caller_block->job != NULL)
@@ -2034,6 +2346,10 @@ static int builtin_function(parser_t &parser, wchar_t **argv)
res=1;
}
else if (! wcslen(argv[woptind]))
{
append_format(stderr_buffer, _(L"%ls: No function name given\n"), argv[0]);
}
else
{
@@ -3070,10 +3386,7 @@ static int builtin_source(parser_t &parser, wchar_t ** argv)
argc = builtin_count_args(argv);
const wchar_t *fn;
const wchar_t *fn_intern;
const wchar_t *fn, *fn_intern;
if (argc < 2 || (wcscmp(argv[1], L"-") == 0))
{
@@ -3106,18 +3419,7 @@ static int builtin_source(parser_t &parser, wchar_t ** argv)
return STATUS_BUILTIN_ERROR;
}
fn = wrealpath(argv[1], NULL);
if (!fn)
{
fn_intern = intern(argv[1]);
}
else
{
fn_intern = intern(fn);
free((void *)fn);
}
fn_intern = intern(argv[1]);
}
parser.push_block(new source_block_t(fn_intern));
@@ -3421,6 +3723,12 @@ static int builtin_for(parser_t &parser, wchar_t **argv)
int argc = builtin_count_args(argv);
int res=STATUS_BUILTIN_ERROR;
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
if (argc == 1)
{
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_ERROR;
}
if (argc < 3)
{
@@ -3709,7 +4017,7 @@ static int builtin_break_continue(parser_t &parser, wchar_t **argv)
{
parser.block_at_index(block_idx)->skip = true;
}
/* Skip the loop itself */
block_t *loop_block = parser.block_at_index(loop_idx);
loop_block->skip = true;
@@ -3787,7 +4095,7 @@ static int builtin_return(parser_t &parser, wchar_t **argv)
builtin_print_help(parser, argv[0], stderr_buffer);
return STATUS_BUILTIN_ERROR;
}
/* Skip everything up to (and then including) the function block */
for (size_t i=0; i < function_block_idx; i++)
{
@@ -3808,6 +4116,13 @@ static int builtin_switch(parser_t &parser, wchar_t **argv)
int res=STATUS_BUILTIN_OK;
int argc = builtin_count_args(argv);
/* Hackish - if we have no arguments other than the command, we are a "naked invocation" and we just print help */
if (argc == 1)
{
builtin_print_help(parser, argv[0], stdout_buffer);
return STATUS_BUILTIN_ERROR;
}
if (argc != 2)
{
append_format(stderr_buffer,
@@ -4012,6 +4327,49 @@ static int builtin_history(parser_t &parser, wchar_t **argv)
return STATUS_BUILTIN_ERROR;
}
#pragma mark Simulator
int builtin_parse(parser_t &parser, wchar_t **argv)
{
struct sigaction act;
sigemptyset(& act.sa_mask);
act.sa_flags=0;
act.sa_handler=SIG_DFL;
sigaction(SIGINT, &act, 0);
std::vector<char> txt;
for (;;)
{
char buff[256];
ssize_t amt = read_loop(builtin_stdin, buff, sizeof buff);
if (amt <= 0) break;
txt.insert(txt.end(), buff, buff + amt);
}
if (! txt.empty())
{
const wcstring src = str2wcstring(&txt.at(0), txt.size());
parse_node_tree_t parse_tree;
parse_error_list_t errors;
bool success = parse_tree_from_string(src, parse_flag_none, &parse_tree, &errors);
if (! success)
{
stdout_buffer.append(L"Parsing failed:\n");
for (size_t i=0; i < errors.size(); i++)
{
stdout_buffer.append(errors.at(i).describe(src));
stdout_buffer.push_back(L'\n');
}
stdout_buffer.append(L"(Reparsed with continue after error)\n");
parse_tree.clear();
errors.clear();
parse_tree_from_string(src, parse_flag_continue_after_error, &parse_tree, &errors);
}
const wcstring dump = parse_dump_tree(parse_tree, src);
stdout_buffer.append(dump);
}
return STATUS_BUILTIN_OK;
}
/*
END OF BUILTIN COMMANDS
@@ -4027,6 +4385,7 @@ static int builtin_history(parser_t &parser, wchar_t **argv)
static const builtin_data_t builtin_datas[]=
{
{ L"[", &builtin_test, N_(L"Test a condition") },
{ L"__fish_parse", &builtin_parse, N_(L"Try out the new parser") },
{ L"and", &builtin_generic, N_(L"Execute command if previous command suceeded") },
{ L"begin", &builtin_begin, N_(L"Create a block of code") },
{ L"bg", &builtin_bg, N_(L"Send job to background") },
@@ -4171,7 +4530,7 @@ void builtin_get_names(std::vector<completion_t> &list)
{
for (size_t i=0; i < BUILTIN_COUNT; i++)
{
list.push_back(completion_t(builtin_datas[i].name));
append_completion(list, builtin_datas[i].name);
}
}
@@ -4218,4 +4577,3 @@ void builtin_pop_io(parser_t &parser)
builtin_stdin = 0;
}
}