mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-26 12:53:13 +00:00
Merge branch 'master' into ast_templates
Conflicts: fish_tests.cpp
This commit is contained in:
commit
551d2dfebd
22 changed files with 756 additions and 460 deletions
|
@ -1660,7 +1660,7 @@ static int builtin_echo(parser_t &parser, wchar_t **argv)
|
|||
wc = L'\b';
|
||||
break;
|
||||
case L'e':
|
||||
wc = L'\e';
|
||||
wc = L'\x1B';
|
||||
break;
|
||||
case L'f':
|
||||
wc = L'\f';
|
||||
|
@ -2372,8 +2372,9 @@ static int builtin_read(parser_t &parser, wchar_t **argv)
|
|||
reader_set_highlight_function(&highlight_shell);
|
||||
reader_set_test_function(&reader_shell_test);
|
||||
}
|
||||
/* No autosuggestions in builtin_read */
|
||||
/* No autosuggestions or abbreviations in builtin_read */
|
||||
reader_set_allow_autosuggesting(false);
|
||||
reader_set_expand_abbreviations(false);
|
||||
reader_set_exit_on_interrupt(true);
|
||||
|
||||
reader_set_buffer(commandline, wcslen(commandline));
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
\a = alert (bell)
|
||||
\b = backspace
|
||||
\c = produce no further output
|
||||
\e = escape
|
||||
\f = form feed
|
||||
\n = new line
|
||||
\r = carriage return
|
||||
|
@ -319,6 +320,9 @@ void builtin_printf_state_t::print_esc_char(wchar_t c)
|
|||
case L'c': /* Cancel the rest of the output. */
|
||||
this->early_exit = true;
|
||||
break;
|
||||
case L'e': /* Escape */
|
||||
this->append_output(L'\x1B');
|
||||
break;
|
||||
case L'f': /* Form feed. */
|
||||
this->append_output(L'\f');
|
||||
break;
|
||||
|
@ -358,7 +362,7 @@ long builtin_printf_state_t::print_esc(const wchar_t *escstart, bool octal_0)
|
|||
esc_value = esc_value * 16 + hex_to_bin(*p);
|
||||
if (esc_length == 0)
|
||||
this->fatal_error(_(L"missing hexadecimal number in escape"));
|
||||
this->append_format_output(L"%lc", esc_value);
|
||||
this->append_output(esc_value);
|
||||
}
|
||||
else if (is_octal_digit(*p))
|
||||
{
|
||||
|
@ -367,10 +371,12 @@ long builtin_printf_state_t::print_esc(const wchar_t *escstart, bool octal_0)
|
|||
extension to POSIX that is compatible with Bash 2.05b. */
|
||||
for (esc_length = 0, p += octal_0 && *p == L'0'; esc_length < 3 && is_octal_digit(*p); ++esc_length, ++p)
|
||||
esc_value = esc_value * 8 + octal_to_bin(*p);
|
||||
this->append_format_output(L"%c", esc_value);
|
||||
this->append_output(esc_value);
|
||||
}
|
||||
else if (*p && wcschr(L"\"\\abcfnrtv", *p))
|
||||
else if (*p && wcschr(L"\"\\abcefnrtv", *p))
|
||||
{
|
||||
print_esc_char(*p++);
|
||||
}
|
||||
else if (*p == L'u' || *p == L'U')
|
||||
{
|
||||
wchar_t esc_char = *p;
|
||||
|
@ -575,6 +581,16 @@ void builtin_printf_state_t::print_direc(const wchar_t *start, size_t length, wc
|
|||
}
|
||||
}
|
||||
|
||||
/* For each character in str, set the corresponding boolean in the array to the given flag */
|
||||
static inline void modify_allowed_format_specifiers(bool ok[UCHAR_MAX + 1], const char *str, bool flag)
|
||||
{
|
||||
for (const char *c = str; *c != '\0'; c++)
|
||||
{
|
||||
unsigned char idx = static_cast<unsigned char>(*c);
|
||||
ok[idx] = flag;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the text in FORMAT, using ARGV (with ARGC elements) for
|
||||
arguments to any `%' directives.
|
||||
Return the number of elements of ARGV used. */
|
||||
|
@ -617,9 +633,7 @@ int builtin_printf_state_t::print_formatted(const wchar_t *format, int argc, wch
|
|||
break;
|
||||
}
|
||||
|
||||
ok['a'] = ok['A'] = ok['c'] = ok['d'] = ok['e'] = ok['E'] =
|
||||
ok['f'] = ok['F'] = ok['g'] = ok['G'] = ok['i'] = ok['o'] =
|
||||
ok['s'] = ok['u'] = ok['x'] = ok['X'] = true;
|
||||
modify_allowed_format_specifiers(ok, "aAcdeEfFgGiosuxX", true);
|
||||
|
||||
for (;; f++, direc_length++)
|
||||
{
|
||||
|
@ -627,18 +641,17 @@ int builtin_printf_state_t::print_formatted(const wchar_t *format, int argc, wch
|
|||
{
|
||||
case L'I':
|
||||
case L'\'':
|
||||
ok['a'] = ok['A'] = ok['c'] = ok['e'] = ok['E'] =
|
||||
ok['o'] = ok['s'] = ok['x'] = ok['X'] = false;
|
||||
modify_allowed_format_specifiers(ok, "aAceEosxX", false);
|
||||
break;
|
||||
case '-':
|
||||
case '+':
|
||||
case ' ':
|
||||
break;
|
||||
case L'#':
|
||||
ok['c'] = ok['d'] = ok['i'] = ok['s'] = ok['u'] = false;
|
||||
modify_allowed_format_specifiers(ok, "cdisu", false);
|
||||
break;
|
||||
case '0':
|
||||
ok['c'] = ok['s'] = false;
|
||||
modify_allowed_format_specifiers(ok, "cs", false);
|
||||
break;
|
||||
default:
|
||||
goto no_more_flag_characters;
|
||||
|
@ -679,7 +692,7 @@ no_more_flag_characters:
|
|||
{
|
||||
++f;
|
||||
++direc_length;
|
||||
ok['c'] = false;
|
||||
modify_allowed_format_specifiers(ok, "c", false);
|
||||
if (*f == L'*')
|
||||
{
|
||||
++f;
|
||||
|
|
1
env.cpp
1
env.cpp
|
@ -137,7 +137,6 @@ struct env_node_t
|
|||
|
||||
class variable_entry_t
|
||||
{
|
||||
bool exportv; /**< Whether the variable should be exported */
|
||||
wcstring value; /**< Value of the variable */
|
||||
};
|
||||
|
||||
|
|
49
expand.cpp
49
expand.cpp
|
@ -1336,10 +1336,7 @@ static int expand_cmdsubst(parser_t &parser, const wcstring &input, std::vector<
|
|||
const wchar_t * const in = input.c_str();
|
||||
|
||||
int parse_ret;
|
||||
switch (parse_ret = parse_util_locate_cmdsubst(in,
|
||||
¶n_begin,
|
||||
¶n_end,
|
||||
0))
|
||||
switch (parse_ret = parse_util_locate_cmdsubst(in, ¶n_begin, ¶n_end, false))
|
||||
{
|
||||
case -1:
|
||||
parser.error(SYNTAX_ERROR,
|
||||
|
@ -1628,10 +1625,7 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
|
|||
{
|
||||
wchar_t *begin, *end;
|
||||
|
||||
if (parse_util_locate_cmdsubst(input.c_str(),
|
||||
&begin,
|
||||
&end,
|
||||
1) != 0)
|
||||
if (parse_util_locate_cmdsubst(input.c_str(), &begin, &end, true) != 0)
|
||||
{
|
||||
parser.error(CMDSUBST_ERROR, -1, L"Command substitutions not allowed");
|
||||
return EXPAND_ERROR;
|
||||
|
@ -1939,3 +1933,42 @@ bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector<completion_t> *args)
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool expand_abbreviation(const wcstring &src, wcstring *output)
|
||||
{
|
||||
if (src.empty())
|
||||
return false;
|
||||
|
||||
/* Get the abbreviations. Return false if we have none */
|
||||
env_var_t var = env_get_string(USER_ABBREVIATIONS_VARIABLE_NAME);
|
||||
if (var.missing_or_empty())
|
||||
return false;
|
||||
|
||||
bool result = false;
|
||||
wcstring line;
|
||||
wcstokenizer tokenizer(var, ARRAY_SEP_STR);
|
||||
while (tokenizer.next(line))
|
||||
{
|
||||
/* Line is expected to be of the form 'foo=bar'. Parse out the first =. Be forgiving about spaces, but silently skip on failure (no equals, or equals at the end or beginning). Try to avoid copying any strings until we are sure this is a match. */
|
||||
size_t equals = line.find(L'=');
|
||||
if (equals == wcstring::npos || equals == 0 || equals + 1 == line.size())
|
||||
continue;
|
||||
|
||||
/* Find the character just past the end of the command. Walk backwards, skipping spaces. */
|
||||
size_t cmd_end = equals;
|
||||
while (cmd_end > 0 && iswspace(line.at(cmd_end - 1)))
|
||||
cmd_end--;
|
||||
|
||||
/* See if this command matches */
|
||||
if (line.compare(0, cmd_end, src) == 0)
|
||||
{
|
||||
/* Success. Set output to everythign past the end of the string. */
|
||||
if (output != NULL)
|
||||
output->assign(line, equals + 1, wcstring::npos);
|
||||
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
4
expand.h
4
expand.h
|
@ -206,6 +206,10 @@ void expand_variable_error(parser_t &parser, const wchar_t *token, size_t token_
|
|||
*/
|
||||
std::vector<wcstring> expand_get_all_process_names(void);
|
||||
|
||||
/** Abbreviation support. Expand src as an abbreviation, returning true if one was found, false if not. If result is not-null, returns the abbreviation by reference. */
|
||||
#define USER_ABBREVIATIONS_VARIABLE_NAME L"fish_user_abbreviations"
|
||||
bool expand_abbreviation(const wcstring &src, wcstring *output);
|
||||
|
||||
/* Terrible hacks */
|
||||
bool fish_xdm_login_hack_hack_hack_hack(std::vector<std::string> *cmds, int argc, const char * const *argv);
|
||||
bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector<completion_t> *args);
|
||||
|
|
30
fish.cpp
30
fish.cpp
|
@ -382,36 +382,6 @@ static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *out_c
|
|||
return my_optind;
|
||||
}
|
||||
|
||||
/**
|
||||
Calls a bunch of init functions, parses the init files and then
|
||||
parses commands from stdin or files, depending on arguments
|
||||
*/
|
||||
|
||||
static wcstring full_escape(const wchar_t *in)
|
||||
{
|
||||
wcstring out;
|
||||
for (; *in; in++)
|
||||
{
|
||||
if (*in < 32)
|
||||
{
|
||||
append_format(out, L"\\x%.2x", *in);
|
||||
}
|
||||
else if (*in < 128)
|
||||
{
|
||||
out.push_back(*in);
|
||||
}
|
||||
else if (*in < 65536)
|
||||
{
|
||||
append_format(out, L"\\u%.4x", *in);
|
||||
}
|
||||
else
|
||||
{
|
||||
append_format(out, L"\\U%.8x", *in);
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
extern int g_fork_count;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
|
|
@ -1209,6 +1209,7 @@
|
|||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
||||
WARNING_CFLAGS = "-Wall";
|
||||
};
|
||||
name = "Release_C++11";
|
||||
};
|
||||
|
@ -1361,6 +1362,7 @@
|
|||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
||||
WARNING_CFLAGS = "-Wall";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
|
@ -1385,6 +1387,7 @@
|
|||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||
SDKROOT = macosx;
|
||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
||||
WARNING_CFLAGS = "-Wall";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "highlight.h"
|
||||
#include "parse_tree.h"
|
||||
#include "parse_exec.h"
|
||||
#include "parse_util.h"
|
||||
|
||||
/**
|
||||
The number of tests to run
|
||||
|
@ -529,6 +530,28 @@ static void test_parser()
|
|||
}
|
||||
}
|
||||
|
||||
static void test_utils()
|
||||
{
|
||||
say(L"Testing utils");
|
||||
const wchar_t *a = L"echo (echo (echo hi";
|
||||
|
||||
const wchar_t *begin = NULL, *end = NULL;
|
||||
parse_util_cmdsubst_extent(a, 0, &begin, &end);
|
||||
if (begin != a || end != begin + wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
parse_util_cmdsubst_extent(a, 1, &begin, &end);
|
||||
if (begin != a || end != begin + wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
parse_util_cmdsubst_extent(a, 2, &begin, &end);
|
||||
if (begin != a || end != begin + wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
parse_util_cmdsubst_extent(a, 3, &begin, &end);
|
||||
if (begin != a || end != begin + wcslen(begin)) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
|
||||
parse_util_cmdsubst_extent(a, 8, &begin, &end);
|
||||
if (begin != a + wcslen(L"echo (")) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
|
||||
parse_util_cmdsubst_extent(a, 17, &begin, &end);
|
||||
if (begin != a + wcslen(L"echo (echo (")) err(L"parse_util_cmdsubst_extent failed on line %ld", (long)__LINE__);
|
||||
}
|
||||
|
||||
class lru_node_test_t : public lru_node_t
|
||||
{
|
||||
public:
|
||||
|
@ -680,6 +703,65 @@ static void test_fuzzy_match(void)
|
|||
if (string_fuzzy_match_string(L"BB", L"ALPHA!").type != fuzzy_match_none) err(L"test_fuzzy_match failed on line %ld", __LINE__);
|
||||
}
|
||||
|
||||
static void test_abbreviations(void)
|
||||
{
|
||||
say(L"Testing abbreviations");
|
||||
|
||||
const wchar_t *abbreviations =
|
||||
L"gc=git checkout" ARRAY_SEP_STR
|
||||
L"foo=" ARRAY_SEP_STR
|
||||
L"gc=something else" ARRAY_SEP_STR
|
||||
L"=" ARRAY_SEP_STR
|
||||
L"=foo" ARRAY_SEP_STR
|
||||
L"foo" ARRAY_SEP_STR
|
||||
L"foo=bar";
|
||||
|
||||
env_push(true);
|
||||
|
||||
int ret = env_set(USER_ABBREVIATIONS_VARIABLE_NAME, abbreviations, ENV_LOCAL);
|
||||
if (ret != 0) err(L"Unable to set abbreviation variable");
|
||||
|
||||
wcstring result;
|
||||
if (expand_abbreviation(L"", &result)) err(L"Unexpected success with empty abbreviation");
|
||||
if (expand_abbreviation(L"nothing", &result)) err(L"Unexpected success with missing abbreviation");
|
||||
|
||||
if (! expand_abbreviation(L"gc", &result)) err(L"Unexpected failure with gc abbreviation");
|
||||
if (result != L"git checkout") err(L"Wrong abbreviation result for gc");
|
||||
result.clear();
|
||||
|
||||
if (! expand_abbreviation(L"foo", &result)) err(L"Unexpected failure with foo abbreviation");
|
||||
if (result != L"bar") err(L"Wrong abbreviation result for foo");
|
||||
|
||||
bool expanded;
|
||||
expanded = reader_expand_abbreviation_in_command(L"just a command", 3, &result);
|
||||
if (expanded) err(L"Command wrongly expanded on line %ld", (long)__LINE__);
|
||||
expanded = reader_expand_abbreviation_in_command(L"gc somebranch", 0, &result);
|
||||
if (! expanded) err(L"Command not expanded on line %ld", (long)__LINE__);
|
||||
|
||||
expanded = reader_expand_abbreviation_in_command(L"gc somebranch", wcslen(L"gc"), &result);
|
||||
if (! expanded) err(L"gc not expanded");
|
||||
if (result != L"git checkout somebranch") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str());
|
||||
|
||||
expanded = reader_expand_abbreviation_in_command(L"echo hi ; gc somebranch", wcslen(L"echo hi ; g"), &result);
|
||||
if (! expanded) err(L"gc not expanded on line %ld", (long)__LINE__);
|
||||
if (result != L"echo hi ; git checkout somebranch") err(L"gc incorrectly expanded on line %ld", (long)__LINE__);
|
||||
|
||||
expanded = reader_expand_abbreviation_in_command(L"echo (echo (echo (echo (gc ", wcslen(L"echo (echo (echo (echo (gc"), &result);
|
||||
if (! expanded) err(L"gc not expanded on line %ld", (long)__LINE__);
|
||||
if (result != L"echo (echo (echo (echo (git checkout ") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str());
|
||||
|
||||
/* if commands should be expanded */
|
||||
expanded = reader_expand_abbreviation_in_command(L"if gc", wcslen(L"if gc"), &result);
|
||||
if (! expanded) err(L"gc not expanded on line %ld", (long)__LINE__);
|
||||
if (result != L"if git checkout") err(L"gc incorrectly expanded on line %ld to '%ls'", (long)__LINE__, result.c_str());
|
||||
|
||||
/* others should not be */
|
||||
expanded = reader_expand_abbreviation_in_command(L"of gc", wcslen(L"of gc"), &result);
|
||||
if (expanded) err(L"gc incorrectly expanded on line %ld", (long)__LINE__);
|
||||
|
||||
env_pop();
|
||||
}
|
||||
|
||||
/** Test path functions */
|
||||
static void test_path()
|
||||
{
|
||||
|
@ -1771,9 +1853,11 @@ int main(int argc, char **argv)
|
|||
test_tok();
|
||||
test_fork();
|
||||
test_parser();
|
||||
test_utils();
|
||||
test_lru();
|
||||
test_expand();
|
||||
test_fuzzy_match();
|
||||
test_abbreviations();
|
||||
test_test();
|
||||
test_path();
|
||||
test_word_motion();
|
||||
|
|
|
@ -1106,6 +1106,9 @@ static void tokenize(const wchar_t * const buff, std::vector<int> &color, const
|
|||
if (! is_cmd && use_function)
|
||||
is_cmd = function_exists_no_autoload(cmd, vars);
|
||||
|
||||
if (! is_cmd)
|
||||
is_cmd = expand_abbreviation(cmd, NULL);
|
||||
|
||||
/*
|
||||
Moving on to expensive tests
|
||||
*/
|
||||
|
@ -1319,7 +1322,7 @@ void highlight_shell(const wcstring &buff, std::vector<int> &color, size_t pos,
|
|||
|
||||
std::fill(color.begin(), color.end(), -1);
|
||||
|
||||
/* Do something sucky and get the current working directory on this background thread. This should really be passed in. Note that we also need this as a vector (of one directory). */
|
||||
/* Do something sucky and get the current working directory on this background thread. This should really be passed in. */
|
||||
const wcstring working_directory = env_get_pwd_slash();
|
||||
|
||||
/* Tokenize the string */
|
||||
|
@ -1335,7 +1338,7 @@ void highlight_shell(const wcstring &buff, std::vector<int> &color, size_t pos,
|
|||
{
|
||||
wchar_t *begin, *end;
|
||||
|
||||
if (parse_util_locate_cmdsubst(subpos, &begin, &end, 1) <= 0)
|
||||
if (parse_util_locate_cmdsubst(subpos, &begin, &end, true) <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -153,10 +153,7 @@ size_t parse_util_get_offset(const wcstring &str, int line, long line_offset)
|
|||
}
|
||||
|
||||
|
||||
int parse_util_locate_cmdsubst(const wchar_t *in,
|
||||
wchar_t **begin,
|
||||
wchar_t **end,
|
||||
int allow_incomplete)
|
||||
int parse_util_locate_cmdsubst(const wchar_t *in, wchar_t **begin, wchar_t **end, bool allow_incomplete)
|
||||
{
|
||||
wchar_t *pos;
|
||||
wchar_t prev=0;
|
||||
|
@ -243,73 +240,57 @@ int parse_util_locate_cmdsubst(const wchar_t *in,
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void parse_util_cmdsubst_extent(const wchar_t *buff,
|
||||
size_t cursor_pos,
|
||||
const wchar_t **a,
|
||||
const wchar_t **b)
|
||||
void parse_util_cmdsubst_extent(const wchar_t *buff, size_t cursor_pos, const wchar_t **a, const wchar_t **b)
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
wchar_t *pos;
|
||||
const wchar_t *cursor = buff + cursor_pos;
|
||||
const wchar_t * const cursor = buff + cursor_pos;
|
||||
|
||||
CHECK(buff,);
|
||||
|
||||
if (a)
|
||||
{
|
||||
*a = (wchar_t *)buff;
|
||||
}
|
||||
const size_t bufflen = wcslen(buff);
|
||||
assert(cursor_pos <= bufflen);
|
||||
|
||||
if (b)
|
||||
/* ap and bp are the beginning and end of the tightest command substitition found so far */
|
||||
const wchar_t *ap = buff, *bp = buff + bufflen;
|
||||
const wchar_t *pos = buff;
|
||||
for (;;)
|
||||
{
|
||||
*b = (wchar_t *)buff+wcslen(buff);
|
||||
}
|
||||
|
||||
pos = (wchar_t *)buff;
|
||||
|
||||
while (1)
|
||||
wchar_t *begin = NULL, *end = NULL;
|
||||
if (parse_util_locate_cmdsubst(pos, &begin, &end, true) <= 0)
|
||||
{
|
||||
if (parse_util_locate_cmdsubst(pos,
|
||||
&begin,
|
||||
&end,
|
||||
1) <= 0)
|
||||
{
|
||||
/*
|
||||
No subshell found
|
||||
*/
|
||||
/* No subshell found, all done */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!end)
|
||||
/* Intrepret NULL to mean the end */
|
||||
if (end == NULL)
|
||||
{
|
||||
end = (wchar_t *)buff + wcslen(buff);
|
||||
end = const_cast<wchar_t *>(buff) + bufflen;
|
||||
}
|
||||
|
||||
if ((begin < cursor) && (end >= cursor))
|
||||
if (begin < cursor && end >= cursor)
|
||||
{
|
||||
/* This command substitution surrounds the cursor, so it's a tighter fit */
|
||||
begin++;
|
||||
|
||||
if (a)
|
||||
{
|
||||
*a = begin;
|
||||
ap = begin;
|
||||
bp = end;
|
||||
pos = begin + 1;
|
||||
}
|
||||
|
||||
if (b)
|
||||
else if (begin >= cursor)
|
||||
{
|
||||
*b = end;
|
||||
}
|
||||
|
||||
/* This command substitution starts at or after the cursor. Since it was the first command substitution in the string, we're done. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (!*end)
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* This command substitution ends before the cursor. Skip it. */
|
||||
assert(end < cursor);
|
||||
pos = end + 1;
|
||||
assert(pos <= buff + bufflen);
|
||||
}
|
||||
}
|
||||
|
||||
if (a != NULL) *a = ap;
|
||||
if (b != NULL) *b = bp;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -432,7 +413,6 @@ void parse_util_token_extent(const wchar_t *buff,
|
|||
{
|
||||
const wchar_t *begin, *end;
|
||||
long pos;
|
||||
wchar_t *buffcpy;
|
||||
|
||||
const wchar_t *a = NULL, *b = NULL, *pa = NULL, *pb = NULL;
|
||||
|
||||
|
@ -459,14 +439,9 @@ void parse_util_token_extent(const wchar_t *buff,
|
|||
assert(end >= begin);
|
||||
assert(end <= (buff+wcslen(buff)));
|
||||
|
||||
buffcpy = wcsndup(begin, end-begin);
|
||||
const wcstring buffcpy = wcstring(begin, end-begin);
|
||||
|
||||
if (!buffcpy)
|
||||
{
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
tokenizer_t tok(buffcpy, TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS);
|
||||
tokenizer_t tok(buffcpy.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS);
|
||||
for (; tok_has_next(&tok); tok_next(&tok))
|
||||
{
|
||||
size_t tok_begin = tok_get_pos(&tok);
|
||||
|
@ -512,8 +487,6 @@ void parse_util_token_extent(const wchar_t *buff,
|
|||
}
|
||||
}
|
||||
|
||||
free(buffcpy);
|
||||
|
||||
if (tok_begin)
|
||||
{
|
||||
*tok_begin = a;
|
||||
|
@ -568,7 +541,6 @@ void parse_util_set_argv(const wchar_t * const *argv, const wcstring_list_t &nam
|
|||
{
|
||||
const wchar_t * const *arg;
|
||||
size_t i;
|
||||
|
||||
for (i=0, arg=argv; i < named_arguments.size(); i++)
|
||||
{
|
||||
env_set(named_arguments.at(i).c_str(), *arg, ENV_LOCAL);
|
||||
|
@ -576,10 +548,7 @@ void parse_util_set_argv(const wchar_t * const *argv, const wcstring_list_t &nam
|
|||
if (*arg)
|
||||
arg++;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
wchar_t *parse_util_unescape_wildcards(const wchar_t *str)
|
||||
|
@ -679,7 +648,7 @@ static wchar_t get_quote(const wchar_t *cmd, size_t len)
|
|||
{
|
||||
const wchar_t *end = quote_end(&cmd[i]);
|
||||
//fwprintf( stderr, L"Jump %d\n", end-cmd );
|
||||
if ((end == 0) || (!*end) || (end-cmd > len))
|
||||
if ((end == 0) || (!*end) || (end > cmd + len))
|
||||
{
|
||||
res = cmd[i];
|
||||
break;
|
||||
|
|
|
@ -18,14 +18,14 @@
|
|||
\param in the string to search for subshells
|
||||
\param begin the starting paranthesis of the subshell
|
||||
\param end the ending paranthesis of the subshell
|
||||
\param flags set this variable to ACCEPT_INCOMPLETE if in tab_completion mode
|
||||
\param accept_incomplete whether to permit missing closing parenthesis
|
||||
\return -1 on syntax error, 0 if no subshells exist and 1 on sucess
|
||||
*/
|
||||
|
||||
int parse_util_locate_cmdsubst(const wchar_t *in,
|
||||
wchar_t **begin,
|
||||
wchar_t **end,
|
||||
int flags);
|
||||
bool accept_incomplete);
|
||||
|
||||
/**
|
||||
Find the beginning and end of the command substitution under the
|
||||
|
|
18
parser.cpp
18
parser.cpp
|
@ -2025,6 +2025,7 @@ int parser_t::parse_job(process_t *p,
|
|||
for this, used by other shells like bash
|
||||
and zsh).
|
||||
*/
|
||||
|
||||
if (wcschr(cmd, L'='))
|
||||
{
|
||||
wchar_t *cpy = wcsdup(cmd);
|
||||
|
@ -2074,9 +2075,15 @@ int parser_t::parse_job(process_t *p,
|
|||
}
|
||||
else
|
||||
{
|
||||
debug(0,
|
||||
_(L"Unknown command '%ls'"),
|
||||
cmd?cmd:L"UNKNOWN");
|
||||
/*
|
||||
Handle unrecognized commands with standard
|
||||
command not found handler that can make better
|
||||
error messages
|
||||
*/
|
||||
|
||||
wcstring_list_t event_args;
|
||||
event_args.push_back(args.at(0).completion);
|
||||
event_fire_generic(L"fish_command_not_found", &event_args);
|
||||
}
|
||||
|
||||
tmp = current_tokenizer_pos;
|
||||
|
@ -2088,9 +2095,6 @@ int parser_t::parse_job(process_t *p,
|
|||
|
||||
job_set_flag(j, JOB_SKIP, 1);
|
||||
|
||||
wcstring_list_t event_args;
|
||||
event_args.push_back(args.at(0).completion);
|
||||
event_fire_generic(L"fish_command_not_found", &event_args);
|
||||
proc_set_last_status(err==ENOENT?STATUS_UNKNOWN_COMMAND:STATUS_NOT_EXECUTABLE);
|
||||
}
|
||||
}
|
||||
|
@ -2714,7 +2718,7 @@ int parser_t::parser_test_argument(const wchar_t *arg, wcstring *out, const wcha
|
|||
switch (parse_util_locate_cmdsubst(arg_cpy,
|
||||
¶n_begin,
|
||||
¶n_end,
|
||||
0))
|
||||
false))
|
||||
{
|
||||
case -1:
|
||||
err=1;
|
||||
|
|
202
reader.cpp
202
reader.cpp
|
@ -97,8 +97,8 @@ commence.
|
|||
#include "iothread.h"
|
||||
#include "intern.h"
|
||||
#include "path.h"
|
||||
|
||||
#include "parse_util.h"
|
||||
#include "parser_keywords.h"
|
||||
|
||||
/**
|
||||
Maximum length of prefix string when printing completion
|
||||
|
@ -182,6 +182,8 @@ static pthread_key_t generation_count_key;
|
|||
/* A color is an int */
|
||||
typedef int color_t;
|
||||
|
||||
static void set_command_line_and_position(const wcstring &new_str, size_t pos);
|
||||
|
||||
/**
|
||||
A struct describing the state of the interactive reader. These
|
||||
states can be stacked, in case reader_readline() calls are
|
||||
|
@ -203,6 +205,9 @@ public:
|
|||
/** When backspacing, we temporarily suppress autosuggestions */
|
||||
bool suppress_autosuggestion;
|
||||
|
||||
/** Whether abbreviations are expanded */
|
||||
bool expand_abbreviations;
|
||||
|
||||
/** The representation of the current screen contents */
|
||||
screen_t screen;
|
||||
|
||||
|
@ -244,6 +249,9 @@ public:
|
|||
/** Do what we need to do whenever our command line changes */
|
||||
void command_line_changed(void);
|
||||
|
||||
/** Expand abbreviations at the current cursor position. */
|
||||
bool expand_abbreviation_as_necessary();
|
||||
|
||||
/** The current position of the cursor in buff. */
|
||||
size_t buff_pos;
|
||||
|
||||
|
@ -326,6 +334,7 @@ public:
|
|||
reader_data_t() :
|
||||
allow_autosuggestion(0),
|
||||
suppress_autosuggestion(0),
|
||||
expand_abbreviations(0),
|
||||
history(0),
|
||||
token_history_pos(0),
|
||||
search_pos(0),
|
||||
|
@ -635,6 +644,159 @@ void reader_data_t::command_line_changed()
|
|||
s_generation_count++;
|
||||
}
|
||||
|
||||
/* Expand abbreviations at the given cursor position. Does NOT inspect 'data'. */
|
||||
bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t cursor_pos, wcstring *output)
|
||||
{
|
||||
/* See if we are at "command position". Get the surrounding command substitution, and get the extent of the first token. */
|
||||
const wchar_t * const buff = cmdline.c_str();
|
||||
const wchar_t *cmdsub_begin = NULL, *cmdsub_end = NULL;
|
||||
parse_util_cmdsubst_extent(buff, cursor_pos, &cmdsub_begin, &cmdsub_end);
|
||||
assert(cmdsub_begin != NULL && cmdsub_begin >= buff);
|
||||
assert(cmdsub_end != NULL && cmdsub_end >= cmdsub_begin);
|
||||
|
||||
/* Determine the offset of this command substitution */
|
||||
const size_t subcmd_offset = cmdsub_begin - buff;
|
||||
|
||||
const wcstring subcmd = wcstring(cmdsub_begin, cmdsub_end - cmdsub_begin);
|
||||
const wchar_t *subcmd_cstr = subcmd.c_str();
|
||||
|
||||
/* Get the token before the cursor */
|
||||
const wchar_t *subcmd_tok_begin = NULL, *subcmd_tok_end = NULL;
|
||||
assert(cursor_pos >= subcmd_offset);
|
||||
size_t subcmd_cursor_pos = cursor_pos - subcmd_offset;
|
||||
parse_util_token_extent(subcmd_cstr, subcmd_cursor_pos, &subcmd_tok_begin, &subcmd_tok_end, NULL, NULL);
|
||||
|
||||
/* Compute the offset of the token before the cursor within the subcmd */
|
||||
assert(subcmd_tok_begin >= subcmd_cstr);
|
||||
assert(subcmd_tok_end >= subcmd_tok_begin);
|
||||
const size_t subcmd_tok_begin_offset = subcmd_tok_begin - subcmd_cstr;
|
||||
const size_t subcmd_tok_length = subcmd_tok_end - subcmd_tok_begin;
|
||||
|
||||
/* Now parse the subcmd, looking for commands */
|
||||
bool had_cmd = false, previous_token_is_cmd = false;
|
||||
tokenizer_t tok(subcmd_cstr, TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS);
|
||||
for (; tok_has_next(&tok); tok_next(&tok))
|
||||
{
|
||||
size_t tok_pos = static_cast<size_t>(tok_get_pos(&tok));
|
||||
if (tok_pos > subcmd_tok_begin_offset)
|
||||
{
|
||||
/* We've passed the token we're interested in */
|
||||
break;
|
||||
}
|
||||
|
||||
int last_type = tok_last_type(&tok);
|
||||
|
||||
switch (last_type)
|
||||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
if (had_cmd)
|
||||
{
|
||||
/* Parameter to the command. */
|
||||
}
|
||||
else
|
||||
{
|
||||
const wcstring potential_cmd = tok_last(&tok);
|
||||
if (parser_keywords_is_subcommand(potential_cmd))
|
||||
{
|
||||
if (potential_cmd == L"command" || potential_cmd == L"builtin")
|
||||
{
|
||||
/* 'command' and 'builtin' defeat abbreviation expansion. Skip this command. */
|
||||
had_cmd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Other subcommand. Pretend it doesn't exist so that we can expand the following command */
|
||||
had_cmd = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's a normal command */
|
||||
had_cmd = true;
|
||||
if (tok_pos == subcmd_tok_begin_offset)
|
||||
{
|
||||
/* This is the token we care about! */
|
||||
previous_token_is_cmd = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_REDIRECT_NOCLOB:
|
||||
case TOK_REDIRECT_OUT:
|
||||
case TOK_REDIRECT_IN:
|
||||
case TOK_REDIRECT_APPEND:
|
||||
case TOK_REDIRECT_FD:
|
||||
{
|
||||
if (!had_cmd)
|
||||
{
|
||||
break;
|
||||
}
|
||||
tok_next(&tok);
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_PIPE:
|
||||
case TOK_BACKGROUND:
|
||||
case TOK_END:
|
||||
{
|
||||
had_cmd = false;
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_COMMENT:
|
||||
case TOK_ERROR:
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool result = false;
|
||||
if (previous_token_is_cmd)
|
||||
{
|
||||
/* The token is a command. Try expanding it as an abbreviation. */
|
||||
const wcstring token = wcstring(subcmd, subcmd_tok_begin_offset, subcmd_tok_length);
|
||||
wcstring abbreviation;
|
||||
if (expand_abbreviation(token, &abbreviation))
|
||||
{
|
||||
/* There was an abbreviation! Replace the token in the full command. Maintain the relative position of the cursor. */
|
||||
if (output != NULL)
|
||||
{
|
||||
size_t cmd_tok_begin_offset = subcmd_tok_begin_offset + subcmd_offset;
|
||||
output->assign(cmdline);
|
||||
output->replace(cmd_tok_begin_offset, subcmd_tok_length, abbreviation);
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Expand abbreviations. This may change the command line but does NOT repaint it. This is to allow the caller to coalesce repaints. */
|
||||
bool reader_data_t::expand_abbreviation_as_necessary()
|
||||
{
|
||||
bool result = false;
|
||||
if (this->expand_abbreviations)
|
||||
{
|
||||
/* Try expanding abbreviations */
|
||||
wcstring new_cmdline;
|
||||
if (reader_expand_abbreviation_in_command(this->command_line, this->buff_pos, &new_cmdline))
|
||||
{
|
||||
/* We expanded an abbreviation! The cursor moves by the difference in the command line lengths. */
|
||||
size_t new_buff_pos = this->buff_pos + new_cmdline.size() - this->command_line.size();
|
||||
|
||||
this->command_line.swap(new_cmdline);
|
||||
data->buff_pos = new_buff_pos;
|
||||
data->command_line_changed();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Sorts and remove any duplicate completions in the list. */
|
||||
static void sort_and_make_unique(std::vector<completion_t> &l)
|
||||
|
@ -1980,8 +2142,7 @@ void reader_sanity_check()
|
|||
}
|
||||
|
||||
/**
|
||||
Set the specified string from the history as the current buffer. Do
|
||||
not modify prefix_width.
|
||||
Set the specified string as the current buffer.
|
||||
*/
|
||||
static void set_command_line_and_position(const wcstring &new_str, size_t pos)
|
||||
{
|
||||
|
@ -2462,6 +2623,11 @@ void reader_set_allow_autosuggesting(bool flag)
|
|||
data->allow_autosuggestion = flag;
|
||||
}
|
||||
|
||||
void reader_set_expand_abbreviations(bool flag)
|
||||
{
|
||||
data->expand_abbreviations = flag;
|
||||
}
|
||||
|
||||
void reader_set_complete_function(complete_function_t f)
|
||||
{
|
||||
data->complete_func = f;
|
||||
|
@ -2712,6 +2878,7 @@ static int read_i(void)
|
|||
reader_set_highlight_function(&highlight_shell);
|
||||
reader_set_test_function(&reader_shell_test);
|
||||
reader_set_allow_autosuggesting(true);
|
||||
reader_set_expand_abbreviations(true);
|
||||
reader_import_history_if_necessary();
|
||||
|
||||
parser_t &parser = parser_t::principal_parser();
|
||||
|
@ -2851,7 +3018,6 @@ const wchar_t *reader_readline(void)
|
|||
data->search_buff.clear();
|
||||
data->search_mode = NO_SEARCH;
|
||||
|
||||
|
||||
exec_prompt();
|
||||
|
||||
reader_super_highlight_me_plenty(data->buff_pos);
|
||||
|
@ -3261,7 +3427,21 @@ const wchar_t *reader_readline(void)
|
|||
}
|
||||
}
|
||||
|
||||
switch (data->test_func(data->command_line.c_str()))
|
||||
/* See if this command is valid */
|
||||
int command_test_result = data->test_func(data->command_line.c_str());
|
||||
if (command_test_result == 0 || command_test_result == PARSER_TEST_INCOMPLETE)
|
||||
{
|
||||
/* This command is valid, but an abbreviation may make it invalid. If so, we will have to test again. */
|
||||
bool abbreviation_expanded = data->expand_abbreviation_as_necessary();
|
||||
if (abbreviation_expanded)
|
||||
{
|
||||
/* It's our reponsibility to rehighlight and repaint. But everything we do below triggers a repaint. */
|
||||
reader_super_highlight_me_plenty(data->buff_pos);
|
||||
command_test_result = data->test_func(data->command_line.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
switch (command_test_result)
|
||||
{
|
||||
|
||||
case 0:
|
||||
|
@ -3597,9 +3777,14 @@ const wchar_t *reader_readline(void)
|
|||
/* Other, if a normal character, we add it to the command */
|
||||
default:
|
||||
{
|
||||
|
||||
if ((!wchar_private(c)) && (((c>31) || (c==L'\n'))&& (c != 127)))
|
||||
{
|
||||
/* Expand abbreviations on space */
|
||||
if (c == L' ')
|
||||
{
|
||||
data->expand_abbreviation_as_necessary();
|
||||
}
|
||||
|
||||
/* Regular character */
|
||||
insert_char(c);
|
||||
}
|
||||
|
@ -3633,10 +3818,7 @@ const wchar_t *reader_readline(void)
|
|||
}
|
||||
|
||||
writestr(L"\n");
|
||||
/*
|
||||
if( comp )
|
||||
halloc_free( comp );
|
||||
*/
|
||||
|
||||
if (!reader_exit_forced())
|
||||
{
|
||||
if (tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
||||
|
|
7
reader.h
7
reader.h
|
@ -204,6 +204,10 @@ void reader_set_right_prompt(const wcstring &prompt);
|
|||
/** Sets whether autosuggesting is allowed. */
|
||||
void reader_set_allow_autosuggesting(bool flag);
|
||||
|
||||
/** Sets whether abbreviation expansion is performed. */
|
||||
void reader_set_expand_abbreviations(bool flag);
|
||||
|
||||
|
||||
/** Sets whether the reader should exit on ^C. */
|
||||
void reader_set_exit_on_interrupt(bool flag);
|
||||
|
||||
|
@ -243,6 +247,9 @@ int reader_search_mode();
|
|||
/* Given a command line and an autosuggestion, return the string that gets shown to the user. Exposed for testing purposes only. */
|
||||
wcstring combine_command_and_autosuggestion(const wcstring &cmdline, const wcstring &autosuggestion);
|
||||
|
||||
/* Expand abbreviations at the given cursor position. Exposed for testing purposes only. */
|
||||
bool reader_expand_abbreviation_in_command(const wcstring &cmdline, size_t cursor_pos, wcstring *output);
|
||||
|
||||
/* Apply a completion string. Exposed for testing only. */
|
||||
wcstring completion_apply_to_command_line(const wcstring &val_str, complete_flags_t flags, const wcstring &command_line, size_t *inout_cursor_pos, bool append_only);
|
||||
|
||||
|
|
35
share/completions/canto.fish
Normal file
35
share/completions/canto.fish
Normal file
|
@ -0,0 +1,35 @@
|
|||
|
||||
function __fish_canto_using_command
|
||||
set cmd (commandline -opc)
|
||||
if [ (count $cmd) -gt 1 ]
|
||||
if [ $argv[1] = $cmd[2] ]
|
||||
return 0
|
||||
end
|
||||
if [ count $argv -gt 2 ]
|
||||
if [ $argv[2] = $cmd[2] ]
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
|
||||
complete -f -c canto -s h -l help -d 'Show Help'
|
||||
complete -f -c canto -s v -l version -d 'Show version'
|
||||
complete -f -c canto -s u -l update -d 'Update before running'
|
||||
complete -f -c canto -s l -l list -d 'List feeds'
|
||||
complete -f -c canto -s a -l checkall -d 'Show number of new items'
|
||||
|
||||
complete -f -c canto -s n -l checknew -d 'Show number of new items for feed'
|
||||
complete -f -c canto -n '__fish_canto_using_command -l --checknew' -d 'Feed' -a '(command canto -l)'
|
||||
|
||||
complete -c canto -s o -l opml -d 'Print conf as OPML'
|
||||
complete -c cnato -s i -l import -d 'Import from OPML'
|
||||
complete -f -c canto -s r -l url -d 'Add feed'
|
||||
|
||||
complete -c canto -s D -l dir -d 'Set configuration directory'
|
||||
complete -c canto -s C -l conf -d 'Set configuration file'
|
||||
complete -c canto -s L -l log -d 'Set client log file'
|
||||
complete -c canto -s F -l fdir -d 'Set feed directory'
|
||||
complete -c canto -s S -l sdir -d 'Set script directory'
|
|
@ -41,7 +41,7 @@ complete -c darcs -n '__fish_use_subcommand' -x -a obliterate --description 'Del
|
|||
complete -c darcs -n '__fish_use_subcommand' -x -a rollback --description 'Record a new patch reversing some recorded changes'
|
||||
complete -c darcs -n '__fish_use_subcommand' -x -a push --description 'Copy and apply patches from this repository to another one'
|
||||
complete -c darcs -n '__fish_use_subcommand' -x -a send --description 'Send by email a bundle of one or more patches'
|
||||
complete -c darcs -n '__fish_use_subcommand' -x -a apply --description 'Apply a patch bundle created by `darcs send''
|
||||
complete -c darcs -n '__fish_use_subcommand' -x -a apply --description 'Apply a patch bundle created by `darcs send\''
|
||||
complete -c darcs -n '__fish_use_subcommand' -x -a get --description 'Create a local copy of a repository'
|
||||
complete -c darcs -n '__fish_use_subcommand' -x -a put --description 'Makes a copy of the repository'
|
||||
complete -c darcs -n '__fish_use_subcommand' -x -a initialize --description 'Make the current directory a repository'
|
||||
|
|
|
@ -1,22 +1,14 @@
|
|||
function __fish_complete_ftp -d 'Complete ftp, pftp' --argument-names ftp
|
||||
complete -c $ftp -xa "(__fish_print_hostnames)" -d 'Hostname'
|
||||
tname'
|
||||
complete -c $ftp -s 4 -d 'Use only IPv4 to contact any host'
|
||||
host'
|
||||
complete -c $ftp -s 6 -d 'Use IPv6 only'
|
||||
only'
|
||||
complete -c $ftp -s p -d 'Use passive mode for data transfers'
|
||||
sfers'
|
||||
complete -c $ftp -s A -d 'Use active mode for data transfers'
|
||||
sfers'
|
||||
complete -c $ftp -s i -d 'Turn off interactive prompting during multiple file transfers'
|
||||
complete -c $ftp -s i -d 'Turn off interactive prompting during multiple file transfers.'
|
||||
complete -c $ftp -s n -d 'Restrain ftp from attempting "auto-login" upon initial connection'
|
||||
complete -c $ftp -s e -d 'Disable command editing and history support'
|
||||
complete -c $ftp -s g -d 'Disable file name globbing'
|
||||
Disable file name globbing'
|
||||
m -d 'Do not explicitly bind data and control channels to same interface'
|
||||
channels to same interface'
|
||||
v -d 'Verbose. Show all server responses and data transfer stats'
|
||||
es and data transfer stats'
|
||||
d -d 'Enable debugging'
|
||||
complete -c $ftp -s m -d 'Do not explicitly bind data and control channels to same interface'
|
||||
complete -c $ftp -s v -d 'Verbose. Show all server responses and data transfer stats'
|
||||
complete -c $ftp -s d -d 'Enable debugging'
|
||||
end
|
||||
|
|
|
@ -224,15 +224,17 @@ function __fish_config_interactive -d "Initializations that should be performed
|
|||
function fish_command_not_found_handler --on-event fish_command_not_found
|
||||
/usr/lib/command-not-found $argv
|
||||
end
|
||||
fish_command_not_found_handler $argv
|
||||
else
|
||||
# Ubuntu Feisty places this command in the regular path instead
|
||||
if type -p command-not-found > /dev/null 2> /dev/null
|
||||
else if type -p command-not-found > /dev/null 2> /dev/null
|
||||
function fish_command_not_found_handler --on-event fish_command_not_found
|
||||
command-not-found $argv
|
||||
end
|
||||
# Use standard fish command not found handler otherwise
|
||||
else
|
||||
function fish_command_not_found_handler --on-event fish_command_not_found
|
||||
echo fish: Unknown command "'$argv'" >&2
|
||||
end
|
||||
end
|
||||
fish_command_not_found_handler $argv
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
# 'upstream_equal', 'upstream_behind', 'upstream_ahead', and
|
||||
# 'upstream_diverged'.
|
||||
|
||||
set -g ___fish_git_prompt_status_order stagedstate invalidstate dirtystate untrackedfiles
|
||||
|
||||
function __fish_git_prompt_show_upstream --description "Helper function for __fish_git_prompt"
|
||||
# Ask git-config for some config options
|
||||
set -l svn_remote
|
||||
|
@ -82,6 +84,7 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi
|
|||
set -l upstream git
|
||||
set -l legacy
|
||||
set -l verbose
|
||||
set -l informative
|
||||
set -l svn_url_pattern
|
||||
set -l show_upstream $__fish_git_prompt_showupstream
|
||||
git config -z --get-regexp '^(svn-remote\..*\.url|bash\.showUpstream)$' ^/dev/null | tr '\0\n' '\n ' | while read -l key value
|
||||
|
@ -109,6 +112,8 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi
|
|||
set upstream $option
|
||||
case verbose
|
||||
set verbose 1
|
||||
case informative
|
||||
set informative 1
|
||||
case legacy
|
||||
set legacy 1
|
||||
end
|
||||
|
@ -176,30 +181,42 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi
|
|||
end
|
||||
|
||||
# calculate the result
|
||||
if test -z "$verbose"
|
||||
switch "$count"
|
||||
case '' # no upstream
|
||||
case "0 0" # equal to upstream
|
||||
echo $___fish_git_prompt_char_upstream_equal
|
||||
case "0 *" # ahead of upstream
|
||||
echo $___fish_git_prompt_char_upstream_ahead
|
||||
case "* 0" # behind upstream
|
||||
echo $___fish_git_prompt_char_upstream_behind
|
||||
case '*' # diverged from upstream
|
||||
echo $___fish_git_prompt_char_upstream_diverged
|
||||
end
|
||||
else
|
||||
if test -n "$verbose"
|
||||
echo $count | read -l behind ahead
|
||||
switch "$count"
|
||||
case '' # no upstream
|
||||
case "0 0" # equal to upstream
|
||||
echo " $___fish_git_prompt_char_upstream_equal"
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_equal"
|
||||
case "0 *" # ahead of upstream
|
||||
echo " $___fish_git_prompt_char_upstream_ahead$ahead"
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead"
|
||||
case "* 0" # behind upstream
|
||||
echo " $___fish_git_prompt_char_upstream_behind$behind"
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind$behind"
|
||||
case '*' # diverged from upstream
|
||||
echo " $__fish_git_prompt_char_upstream_diverged$ahead-$behind"
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_diverged$ahead-$behind"
|
||||
end
|
||||
else if test -n informative
|
||||
echo $count | read -l behind ahead
|
||||
switch "$count"
|
||||
case '' # no upstream
|
||||
case "0 0" # equal to upstream
|
||||
case "0 *" # ahead of upstream
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead"
|
||||
case "* 0" # behind upstream
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind$behind"
|
||||
case '*' # diverged from upstream
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead$___fish_git_prompt_char_upstream_behind$behind"
|
||||
end
|
||||
else
|
||||
switch "$count"
|
||||
case '' # no upstream
|
||||
case "0 0" # equal to upstream
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_equal"
|
||||
case "0 *" # ahead of upstream
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_ahead$ahead"
|
||||
case "* 0" # behind upstream
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_behind$behind"
|
||||
case '*' # diverged from upstream
|
||||
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_diverged$ahead-$behind"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -216,10 +233,15 @@ function __fish_git_prompt --description "Prompt function for Git"
|
|||
set -l u #untracked
|
||||
set -l c (__fish_git_prompt_current_branch_bare)
|
||||
set -l p #upstream
|
||||
set -l informative_status
|
||||
|
||||
__fish_git_prompt_validate_chars
|
||||
|
||||
if test "true" = (git rev-parse --is-inside-work-tree ^/dev/null)
|
||||
|
||||
if test -n "$__fish_git_prompt_show_informative_status"
|
||||
set informative_status "|"(__fish_git_prompt_informative_status)
|
||||
else
|
||||
if test -n "$__fish_git_prompt_showdirtystate"
|
||||
set -l config (git config --bool bash.showDirtyState)
|
||||
if test "$config" != "false"
|
||||
|
@ -238,10 +260,12 @@ function __fish_git_prompt --description "Prompt function for Git"
|
|||
set u $___fish_git_prompt_char_untrackedfiles
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if test -n "$__fish_git_prompt_showupstream"
|
||||
set p (__fish_git_prompt_show_upstream)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
__fish_git_prompt_validate_colors
|
||||
|
@ -282,7 +306,7 @@ function __fish_git_prompt --description "Prompt function for Git"
|
|||
set format " (%s)"
|
||||
end
|
||||
|
||||
printf "%s$format%s" "$___fish_git_prompt_color_prefix" "$___fish_git_prompt_color_prefix_done$c$b$f$r$p$___fish_git_prompt_color_suffix" "$___git_ps_color_suffix_done"
|
||||
printf "%s$format%s" "$___fish_git_prompt_color_prefix" "$___fish_git_prompt_color_prefix_done$c$b$f$r$p$informative_status$___fish_git_prompt_color_suffix" "$___git_ps_color_suffix_done"
|
||||
end
|
||||
|
||||
### helper functions
|
||||
|
@ -310,6 +334,46 @@ function __fish_git_prompt_dirty --description "__fish_git_prompt helper, tells
|
|||
echo $dirty
|
||||
end
|
||||
|
||||
function __fish_git_prompt_informative_status
|
||||
|
||||
set -l changedFiles (git diff --name-status | cut -c 1-2)
|
||||
set -l stagedFiles (git diff --staged --name-status | cut -c 1-2)
|
||||
|
||||
set -l dirtystate (math (count $changedFiles) - (count (echo $changedFiles | grep "U")))
|
||||
set -l invalidstate (count (echo $stagedFiles | grep "U"))
|
||||
set -l stagedstate (math (count $stagedFiles) - $invalidstate)
|
||||
set -l untrackedfiles (count (git ls-files --others --exclude-standard))
|
||||
|
||||
set -l info
|
||||
|
||||
if [ (math $dirtystate + $invalidstate + $stagedstate + $untrackedfiles) = 0 ]
|
||||
set info $___fish_git_prompt_color_cleanstate$___fish_git_prompt_char_cleanstate$___fish_git_prompt_color_cleanstate_done
|
||||
else
|
||||
for i in $___fish_git_prompt_status_order
|
||||
if [ $$i != "0" ]
|
||||
set -l color_var ___fish_git_prompt_color_$i
|
||||
set -l color_done_var ___fish_git_prompt_color_$i
|
||||
set -l symbol_var ___fish_git_prompt_char_$i
|
||||
|
||||
set -l color $$color_var
|
||||
set -l color_done $$color_done_var
|
||||
set -l symbol $$symbol_var
|
||||
|
||||
set -l count
|
||||
|
||||
if not set -q __fish_git_prompt_hide_$i
|
||||
set count $$i
|
||||
end
|
||||
|
||||
set info "$info$color$symbol$count$color_done"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
echo $info
|
||||
|
||||
end
|
||||
|
||||
function __fish_git_prompt_current_branch_bare --description "__fish_git_prompt helper, tells wheter or not the current branch is bare"
|
||||
set -l bare
|
||||
|
||||
|
@ -388,145 +452,81 @@ function __fish_git_prompt_git_dir --description "__fish_git_prompt helper, retu
|
|||
echo (git rev-parse --git-dir ^/dev/null)
|
||||
end
|
||||
|
||||
function __fish_git_prompt_set_char
|
||||
set -l user_variable_name "$argv[1]"
|
||||
set -l char $argv[2]
|
||||
set -l user_variable $$user_variable_name
|
||||
|
||||
set -l variable _$user_variable_name
|
||||
set -l variable_done "$variable"_done
|
||||
|
||||
if not set -q $variable
|
||||
set -g $variable (set -q $user_variable_name; and echo $user_variable; or echo $char)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function __fish_git_prompt_validate_chars --description "__fish_git_prompt helper, checks char variables"
|
||||
if not set -q ___fish_git_prompt_char_dirtystate
|
||||
set -g ___fish_git_prompt_char_dirtystate (set -q __fish_git_prompt_char_dirtystate; and echo $__fish_git_prompt_char_dirtystate; or echo '*')
|
||||
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_cleanstate '.'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_dirtystate '*'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_stagedstate '+'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_invalidstate '#'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_stashstate '$'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_untrackedfiles '%'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_equal '='
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_behind '<'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_ahead '>'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_diverged '<>'
|
||||
__fish_git_prompt_set_char __fish_git_prompt_char_upstream_prefix ' '
|
||||
|
||||
end
|
||||
if not set -q ___fish_git_prompt_char_stagedstate
|
||||
set -g ___fish_git_prompt_char_stagedstate (set -q __fish_git_prompt_char_stagedstate; and echo $__fish_git_prompt_char_stagedstate; or echo '+')
|
||||
|
||||
function __fish_git_prompt_set_color
|
||||
set -l user_variable_name "$argv[1]"
|
||||
set -l user_variable $$user_variable_name
|
||||
set -l user_variable_bright
|
||||
|
||||
if test (count $user_variable) -eq 2
|
||||
set user_variable_bright $user_variable[2]
|
||||
set user_variable $user_variable[1]
|
||||
end
|
||||
if not set -q ___fish_git_prompt_char_invalidstate
|
||||
set -g ___fish_git_prompt_char_invalidstate (set -q __fish_git_prompt_char_invalidstate; and echo $__fish_git_prompt_char_invalidstate; or echo '#')
|
||||
|
||||
set -l variable _$user_variable_name
|
||||
set -l variable_done "$variable"_done
|
||||
|
||||
if not set -q $variable
|
||||
if test -n "$user_variable"
|
||||
if test -n "$user_variable_bright"
|
||||
set -g $variable (set_color -o $user_variable)
|
||||
else
|
||||
set -g $variable (set_color $user_variable)
|
||||
end
|
||||
if not set -q ___fish_git_prompt_char_stashstate
|
||||
set -g ___fish_git_prompt_char_stashstate (set -q __fish_git_prompt_char_stashstate; and echo $__fish_git_prompt_char_stashstate; or echo '$')
|
||||
end
|
||||
if not set -q ___fish_git_prompt_char_untrackedfiles
|
||||
set -g ___fish_git_prompt_char_untrackedfiles (set -q __fish_git_prompt_char_untrackedfiles; and echo $__fish_git_prompt_char_untrackedfiles; or echo '%')
|
||||
end
|
||||
if not set -q ___fish_git_prompt_char_upstream_equal
|
||||
set -g ___fish_git_prompt_char_upstream_equal (set -q __fish_git_prompt_char_upstream_equal; and echo $__fish_git_prompt_char_upstream_equal; or echo '=')
|
||||
end
|
||||
if not set -q ___fish_git_prompt_char_upstream_behind
|
||||
set -g ___fish_git_prompt_char_upstream_behind (set -q __fish_git_prompt_char_upstream_behind; and echo $__fish_git_prompt_char_upstream_behind; or echo '<')
|
||||
end
|
||||
if not set -q ___fish_git_prompt_char_upstream_ahead
|
||||
set -g ___fish_git_prompt_char_upstream_ahead (set -q __fish_git_prompt_char_upstream_ahead; and echo $__fish_git_prompt_char_upstream_ahead; or echo '>')
|
||||
end
|
||||
if not set -q ___fish_git_prompt_char_upstream_diverged
|
||||
set -g ___fish_git_prompt_char_upstream_diverged (set -q __fish_git_prompt_char_upstream_diverged; and echo $__fish_git_prompt_char_upstream_diverged; or echo '<>')
|
||||
set -g $variable_done (set_color normal)
|
||||
else
|
||||
set -g $variable ''
|
||||
set -g $variable_done ''
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function __fish_git_prompt_validate_colors --description "__fish_git_prompt helper, checks color variables"
|
||||
if not set -q ___fish_git_prompt_color
|
||||
if test -n "$__fish_git_prompt_color"
|
||||
set -g ___fish_git_prompt_color (set_color $__fish_git_prompt_color)
|
||||
set -g ___fish_git_prompt_color_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color ''
|
||||
set -g ___fish_git_prompt_color_done ''
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_prefix
|
||||
if test -n "$__fish_git_prompt_color_prefix"
|
||||
set -g ___fish_git_prompt_color_prefix (set_color $__fish_git_prompt_color_prefix)
|
||||
set -g ___fish_git_prompt_color_prefix_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_prefix $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_prefix_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_suffix
|
||||
if test -n "$__fish_git_prompt_color_suffix"
|
||||
set -g ___fish_git_prompt_color_suffix (set_color $__fish_git_prompt_color_suffix)
|
||||
set -g ___fish_git_prompt_color_suffix_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_suffix $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_suffix_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_bare
|
||||
if test -n "$__fish_git_prompt_color_bare"
|
||||
set -g ___fish_git_prompt_color_bare (set_color $__fish_git_prompt_color_bare)
|
||||
set -g ___fish_git_prompt_color_bare_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_bare $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_bare_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_merging
|
||||
if test -n "$__fish_git_prompt_color_merging"
|
||||
set -g ___fish_git_prompt_color_merging (set_color $__fish_git_prompt_color_merging)
|
||||
set -g ___fish_git_prompt_color_merging_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_merging $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_merging_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_branch
|
||||
if test -n "$__fish_git_prompt_color_branch"
|
||||
set -g ___fish_git_prompt_color_branch (set_color $__fish_git_prompt_color_branch)
|
||||
set -g ___fish_git_prompt_color_branch_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_branch $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_branch_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_dirtystate
|
||||
if test -n "$__fish_git_prompt_color_dirtystate"
|
||||
set -g ___fish_git_prompt_color_dirtystate (set_color $__fish_git_prompt_color_dirtystate)
|
||||
set -g ___fish_git_prompt_color_dirtystate_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_dirtystate $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_dirtystate_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_stagedstate
|
||||
if test -n "$__fish_git_prompt_color_stagedstate"
|
||||
set -g ___fish_git_prompt_color_stagedstate (set_color $__fish_git_prompt_color_stagedstate)
|
||||
set -g ___fish_git_prompt_color_stagedstate_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_stagedstate $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_stagedstate_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_invalidstate
|
||||
if test -n "$__fish_git_prompt_color_invalidstate"
|
||||
set -g ___fish_git_prompt_color_invalidstate (set_color $__fish_git_prompt_color_invalidstate)
|
||||
set -g ___fish_git_prompt_color_invalidstate_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_invalidstate $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_invalidstate_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_stashstate
|
||||
if test -n "$__fish_git_prompt_color_stashstate"
|
||||
set -g ___fish_git_prompt_color_stashstate (set_color $__fish_git_prompt_color_stashstate)
|
||||
set -g ___fish_git_prompt_color_stashstate_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_stashstate $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_stashstate_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_untrackedfiles
|
||||
if test -n "$__fish_git_prompt_color_untrackedfiles"
|
||||
set -g ___fish_git_prompt_color_untrackedfiles (set_color $__fish_git_prompt_color_untrackedfiles)
|
||||
set -g ___fish_git_prompt_color_untrackedfiles_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_untrackedfiles $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_untrackedfiles_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
if not set -q ___fish_git_prompt_color_upstream
|
||||
if test -n "$__fish_git_prompt_color_upstream"
|
||||
set -g ___fish_git_prompt_color_upstream (set_color $__fish_git_prompt_color_upstream)
|
||||
set -g ___fish_git_prompt_color_upstream_done (set_color normal)
|
||||
else
|
||||
set -g ___fish_git_prompt_color_upstream $___fish_git_prompt_color
|
||||
set -g ___fish_git_prompt_color_upstream_done $___fish_git_prompt_color_done
|
||||
end
|
||||
end
|
||||
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_prefix
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_suffix
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_bare
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_merging
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_branch
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_cleanstate
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_dirtystate
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_stagedstate
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_invalidstate
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_stashstate
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_untrackedfiles
|
||||
__fish_git_prompt_set_color __fish_git_prompt_color_upstream
|
||||
|
||||
end
|
||||
|
||||
set -l varargs
|
||||
|
|
|
@ -59,19 +59,19 @@ def flush_diagnostics(where):
|
|||
# This maps commands to lists of completions
|
||||
already_output_completions = {}
|
||||
|
||||
def compileAndSearch(regex, input):
|
||||
def compile_and_search(regex, input):
|
||||
options_section_regex = re.compile(regex , re.DOTALL)
|
||||
options_section_matched = re.search( options_section_regex, input)
|
||||
return options_section_matched
|
||||
|
||||
def unquoteDoubleQuotes(data):
|
||||
def unquote_double_quotes(data):
|
||||
if (len(data) < 2):
|
||||
return data
|
||||
if data[0] == '"' and data[len(data)-1] == '"':
|
||||
data = data[1:len(data)-1]
|
||||
return data
|
||||
|
||||
def unquoteSingleQuotes(data):
|
||||
def unquote_single_quotes(data):
|
||||
if (len(data) < 2):
|
||||
return data
|
||||
if data[0] == '`' and data[len(data)-1] == '\'':
|
||||
|
@ -188,11 +188,7 @@ def built_command(options, description):
|
|||
|
||||
output_complete_command(escaped_cmd, fish_options, truncated_description, built_command_output)
|
||||
|
||||
|
||||
|
||||
def removeGroffFormatting(data):
|
||||
# data = data.replace("\fI","")
|
||||
# data = data.replace("\fP","")
|
||||
def remove_groff_formatting(data):
|
||||
data = data.replace("\\fI","")
|
||||
data = data.replace("\\fP","")
|
||||
data = data.replace("\\f1","")
|
||||
|
@ -217,26 +213,26 @@ def removeGroffFormatting(data):
|
|||
return data
|
||||
|
||||
class ManParser:
|
||||
def isMyType(self, manpage):
|
||||
def is_my_type(self, manpage):
|
||||
return False
|
||||
|
||||
def parseManPage(self, manpage):
|
||||
def parse_man_page(self, manpage):
|
||||
return False
|
||||
|
||||
def name(self):
|
||||
return "no-name"
|
||||
|
||||
class Type1ManParser(ManParser):
|
||||
def isMyType(self, manpage):
|
||||
def is_my_type(self, manpage):
|
||||
# print manpage
|
||||
options_section_matched = compileAndSearch("\.SH \"OPTIONS\"(.*?)", manpage)
|
||||
options_section_matched = compile_and_search("\.SH \"OPTIONS\"(.*?)", manpage)
|
||||
|
||||
if options_section_matched == None:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def parseManPage(self, manpage):
|
||||
def parse_man_page(self, manpage):
|
||||
options_section_regex = re.compile( "\.SH \"OPTIONS\"(.*?)(\.SH|\Z)", re.DOTALL)
|
||||
options_section_matched = re.search( options_section_regex, manpage)
|
||||
|
||||
|
@ -256,27 +252,22 @@ class Type1ManParser(ManParser):
|
|||
return False
|
||||
|
||||
while (options_matched != None):
|
||||
# print len(options_matched.groups())
|
||||
# print options_matched.group()
|
||||
data = options_matched.group(1)
|
||||
last_dotpp_index = data.rfind(".PP")
|
||||
if (last_dotpp_index != -1):
|
||||
data = data[last_dotpp_index+3:]
|
||||
|
||||
data = removeGroffFormatting(data)
|
||||
data = remove_groff_formatting(data)
|
||||
data = data.split(".RS 4")
|
||||
# print data
|
||||
if (len (data) > 1): #and len(data[1]) <= 300):
|
||||
optionName = data[0].strip()
|
||||
|
||||
if ( optionName.find("-") == -1):
|
||||
add_diagnostic(optionName + " doesn't contain - ")
|
||||
# return False
|
||||
else:
|
||||
optionName = unquoteDoubleQuotes(optionName)
|
||||
optionName = unquoteSingleQuotes(optionName)
|
||||
optionName = unquote_double_quotes(optionName)
|
||||
optionName = unquote_single_quotes(optionName)
|
||||
optionDescription = data[1].strip().replace("\n"," ")
|
||||
# print >> sys.stderr, "Option: ", optionName," Description: ", optionDescription , '\n'
|
||||
built_command(optionName, optionDescription)
|
||||
|
||||
else:
|
||||
|
@ -295,7 +286,7 @@ class Type1ManParser(ManParser):
|
|||
return False
|
||||
while options_matched != None:
|
||||
data = options_matched.group(2)
|
||||
data = removeGroffFormatting(data)
|
||||
data = remove_groff_formatting(data)
|
||||
data = data.strip()
|
||||
data = data.split("\n",1)
|
||||
if (len(data)>1 and len(data[1].strip())>0): # and len(data[1])<400):
|
||||
|
@ -303,10 +294,9 @@ class Type1ManParser(ManParser):
|
|||
if ( optionName.find("-") == -1):
|
||||
add_diagnostic(optionName + "doesn't contains -")
|
||||
else:
|
||||
optionName = unquoteDoubleQuotes(optionName)
|
||||
optionName = unquoteSingleQuotes(optionName)
|
||||
optionName = unquote_double_quotes(optionName)
|
||||
optionName = unquote_single_quotes(optionName)
|
||||
optionDescription = data[1].strip().replace("\n"," ")
|
||||
# print "Option: ", optionName," Description: ", optionDescription , '\n'
|
||||
built_command(optionName, optionDescription)
|
||||
else:
|
||||
add_diagnostic('Unable to split option from description')
|
||||
|
@ -330,27 +320,21 @@ class Type1ManParser(ManParser):
|
|||
while options_matched != None:
|
||||
data = options_matched.group(1)
|
||||
|
||||
# print "Data is : ", data
|
||||
data = removeGroffFormatting(data)
|
||||
data = remove_groff_formatting(data)
|
||||
data = data.strip()
|
||||
data = data.split("\n",1)
|
||||
if (len(data)>1 and len(data[1].strip())>0): # and len(data[1])<400):
|
||||
# print "Data[0] is: ", data[0]
|
||||
|
||||
# data = re.sub(trailing_num_regex, "", data)
|
||||
optionName = re.sub(trailing_num_regex, "", data[0].strip())
|
||||
|
||||
if ('-' not in optionName):
|
||||
add_diagnostic(optionName + " doesn't contain -")
|
||||
else:
|
||||
optionName = optionName.strip()
|
||||
optionName = unquoteDoubleQuotes(optionName)
|
||||
optionName = unquoteSingleQuotes(optionName)
|
||||
optionName = unquote_double_quotes(optionName)
|
||||
optionName = unquote_single_quotes(optionName)
|
||||
optionDescription = data[1].strip().replace("\n"," ")
|
||||
# print "Option: ", optionName," Description: ", optionDescription , '\n'
|
||||
built_command(optionName, optionDescription)
|
||||
else:
|
||||
# print data
|
||||
add_diagnostic('Unable to split option from description')
|
||||
return False
|
||||
|
||||
|
@ -363,31 +347,21 @@ class Type1ManParser(ManParser):
|
|||
|
||||
|
||||
class Type2ManParser(ManParser):
|
||||
def isMyType(self, manpage):
|
||||
options_section_matched = compileAndSearch("\.SH OPTIONS(.*?)", manpage)
|
||||
def is_my_type(self, manpage):
|
||||
options_section_matched = compile_and_search("\.SH OPTIONS(.*?)", manpage)
|
||||
|
||||
if options_section_matched == None:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def parseManPage(self, manpage):
|
||||
def parse_man_page(self, manpage):
|
||||
options_section_regex = re.compile( "\.SH OPTIONS(.*?)(\.SH|\Z)", re.DOTALL)
|
||||
options_section_matched = re.search( options_section_regex, manpage)
|
||||
|
||||
# if (options_section_matched == None):
|
||||
# print "Falling Back"
|
||||
# options_section_regex = re.compile( "\.SH OPTIONS(.*?)$", re.DOTALL)
|
||||
# options_section_matched = re.search( options_section_regex, manpage)
|
||||
# print manpage
|
||||
options_section = options_section_matched.group(1)
|
||||
# print options_section
|
||||
# print options_section
|
||||
# sys.exit(1)
|
||||
|
||||
# options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL)
|
||||
options_parts_regex = re.compile("\.[I|T]P( \d+(\.\d)?i?)?(.*?)\.[I|T]P", re.DOTALL)
|
||||
# options_parts_regex = re.compile("\.TP(.*?)[(\.TP)|(\.SH)]", re.DOTALL)
|
||||
options_matched = re.search(options_parts_regex, options_section)
|
||||
add_diagnostic('Command is ' + CMDNAME)
|
||||
|
||||
|
@ -396,56 +370,46 @@ class Type2ManParser(ManParser):
|
|||
return False
|
||||
|
||||
while (options_matched != None):
|
||||
# print len(options_matched.groups())
|
||||
data = options_matched.group(3)
|
||||
|
||||
data = removeGroffFormatting(data)
|
||||
data = remove_groff_formatting(data)
|
||||
|
||||
data = data.strip()
|
||||
|
||||
data = data.split("\n",1)
|
||||
# print >> sys.stderr, data
|
||||
if (len(data)>1 and len(data[1].strip())>0): # and len(data[1])<400):
|
||||
optionName = data[0].strip()
|
||||
if '-' not in optionName:
|
||||
add_diagnostic(optionName + " doesn't contain -")
|
||||
else:
|
||||
optionName = unquoteDoubleQuotes(optionName)
|
||||
optionName = unquoteSingleQuotes(optionName)
|
||||
optionName = unquote_double_quotes(optionName)
|
||||
optionName = unquote_single_quotes(optionName)
|
||||
optionDescription = data[1].strip().replace("\n"," ")
|
||||
# print "Option: ", optionName," Description: ", optionDescription , '\n'
|
||||
built_command(optionName, optionDescription)
|
||||
else:
|
||||
# print >> sys.stderr, data
|
||||
add_diagnostic('Unable to split option from description')
|
||||
|
||||
# return False
|
||||
|
||||
options_section = options_section[options_matched.end()-3:]
|
||||
options_matched = re.search(options_parts_regex, options_section)
|
||||
|
||||
|
||||
|
||||
def name(self):
|
||||
return "Type2"
|
||||
|
||||
|
||||
class Type3ManParser(ManParser):
|
||||
def isMyType(self, manpage):
|
||||
options_section_matched = compileAndSearch("\.SH DESCRIPTION(.*?)", manpage)
|
||||
def is_my_type(self, manpage):
|
||||
options_section_matched = compile_and_search("\.SH DESCRIPTION(.*?)", manpage)
|
||||
|
||||
if options_section_matched == None:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def parseManPage(self, manpage):
|
||||
def parse_man_page(self, manpage):
|
||||
options_section_regex = re.compile( "\.SH DESCRIPTION(.*?)(\.SH|\Z)", re.DOTALL)
|
||||
options_section_matched = re.search( options_section_regex, manpage)
|
||||
|
||||
options_section = options_section_matched.group(1)
|
||||
# print options_section
|
||||
# sys.exit(1)
|
||||
options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL)
|
||||
options_matched = re.search(options_parts_regex, options_section)
|
||||
add_diagnostic('Command is ' + CMDNAME)
|
||||
|
@ -455,10 +419,9 @@ class Type3ManParser(ManParser):
|
|||
return False
|
||||
|
||||
while (options_matched != None):
|
||||
# print len(options_matched.groups())
|
||||
data = options_matched.group(1)
|
||||
|
||||
data = removeGroffFormatting(data)
|
||||
data = remove_groff_formatting(data)
|
||||
data = data.strip()
|
||||
data = data.split("\n",1)
|
||||
|
||||
|
@ -467,10 +430,9 @@ class Type3ManParser(ManParser):
|
|||
if ( optionName.find("-") == -1):
|
||||
add_diagnostic(optionName + "doesn't contain -")
|
||||
else:
|
||||
optionName = unquoteDoubleQuotes(optionName)
|
||||
optionName = unquoteSingleQuotes(optionName)
|
||||
optionName = unquote_double_quotes(optionName)
|
||||
optionName = unquote_single_quotes(optionName)
|
||||
optionDescription = data[1].strip().replace("\n"," ")
|
||||
# print >> sys.stderr, "Option: ", optionName," Description: ", optionDescription , '\n'
|
||||
built_command(optionName, optionDescription)
|
||||
|
||||
else:
|
||||
|
@ -481,27 +443,24 @@ class Type3ManParser(ManParser):
|
|||
options_matched = re.search(options_parts_regex, options_section)
|
||||
|
||||
|
||||
|
||||
def name(self):
|
||||
return "Type3"
|
||||
|
||||
|
||||
class Type4ManParser(ManParser):
|
||||
def isMyType(self, manpage):
|
||||
options_section_matched = compileAndSearch("\.SH FUNCTION LETTERS(.*?)", manpage)
|
||||
def is_my_type(self, manpage):
|
||||
options_section_matched = compile_and_search("\.SH FUNCTION LETTERS(.*?)", manpage)
|
||||
|
||||
if options_section_matched == None:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def parseManPage(self, manpage):
|
||||
def parse_man_page(self, manpage):
|
||||
options_section_regex = re.compile( "\.SH FUNCTION LETTERS(.*?)(\.SH|\Z)", re.DOTALL)
|
||||
options_section_matched = re.search( options_section_regex, manpage)
|
||||
|
||||
options_section = options_section_matched.group(1)
|
||||
# print options_section
|
||||
# sys.exit(1)
|
||||
options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL)
|
||||
options_matched = re.search(options_parts_regex, options_section)
|
||||
add_diagnostic('Command is ' + CMDNAME)
|
||||
|
@ -511,10 +470,9 @@ class Type4ManParser(ManParser):
|
|||
return False
|
||||
|
||||
while (options_matched != None):
|
||||
# print len(options_matched.groups())
|
||||
data = options_matched.group(1)
|
||||
|
||||
data = removeGroffFormatting(data)
|
||||
data = remove_groff_formatting(data)
|
||||
data = data.strip()
|
||||
data = data.split("\n",1)
|
||||
|
||||
|
@ -523,10 +481,9 @@ class Type4ManParser(ManParser):
|
|||
if ( optionName.find("-") == -1):
|
||||
add_diagnostic(optionName + " doesn't contain - ")
|
||||
else:
|
||||
optionName = unquoteDoubleQuotes(optionName)
|
||||
optionName = unquoteSingleQuotes(optionName)
|
||||
optionName = unquote_double_quotes(optionName)
|
||||
optionName = unquote_single_quotes(optionName)
|
||||
optionDescription = data[1].strip().replace("\n"," ")
|
||||
# print "Option: ", optionName," Description: ", optionDescription , '\n'
|
||||
built_command(optionName, optionDescription)
|
||||
|
||||
else:
|
||||
|
@ -542,8 +499,8 @@ class Type4ManParser(ManParser):
|
|||
return "Type4"
|
||||
|
||||
class TypeDarwinManParser(ManParser):
|
||||
def isMyType(self, manpage):
|
||||
options_section_matched = compileAndSearch("\.S[hH] DESCRIPTION", manpage)
|
||||
def is_my_type(self, manpage):
|
||||
options_section_matched = compile_and_search("\.S[hH] DESCRIPTION", manpage)
|
||||
return options_section_matched != None
|
||||
|
||||
def trim_groff(self, line):
|
||||
|
@ -572,9 +529,6 @@ class TypeDarwinManParser(ManParser):
|
|||
line = line[3:]
|
||||
return result
|
||||
|
||||
|
||||
|
||||
|
||||
# Replace some groff escapes. There's a lot we don't bother to handle.
|
||||
def groff_replace_escapes(self, line):
|
||||
line = line.replace('.Nm', CMDNAME)
|
||||
|
@ -586,7 +540,7 @@ class TypeDarwinManParser(ManParser):
|
|||
def is_option(self, line):
|
||||
return line.startswith('.It Fl')
|
||||
|
||||
def parseManPage(self, manpage):
|
||||
def parse_man_page(self, manpage):
|
||||
got_something = False
|
||||
lines = manpage.splitlines()
|
||||
# Discard lines until we get to ".sh Description"
|
||||
|
@ -626,9 +580,6 @@ class TypeDarwinManParser(ManParser):
|
|||
desc_lines.append(line)
|
||||
desc = ' '.join(desc_lines)
|
||||
|
||||
# print "name: ", name
|
||||
# print "desc: ", desc
|
||||
|
||||
if name == '-':
|
||||
# Skip double -- arguments
|
||||
continue
|
||||
|
@ -647,7 +598,7 @@ class TypeDarwinManParser(ManParser):
|
|||
|
||||
|
||||
class TypeDeroffManParser(ManParser):
|
||||
def isMyType(self, manpage):
|
||||
def is_my_type(self, manpage):
|
||||
return True # We're optimists
|
||||
|
||||
def is_option(self, line):
|
||||
|
@ -656,7 +607,7 @@ class TypeDeroffManParser(ManParser):
|
|||
def could_be_description(self, line):
|
||||
return len(line) > 0 and not line.startswith('-')
|
||||
|
||||
def parseManPage(self, manpage):
|
||||
def parse_man_page(self, manpage):
|
||||
d = Deroffer()
|
||||
d.deroff(manpage)
|
||||
output = d.get_output()
|
||||
|
@ -697,7 +648,6 @@ class TypeDeroffManParser(ManParser):
|
|||
|
||||
return got_something
|
||||
|
||||
|
||||
def name(self):
|
||||
return "Deroffing man parser"
|
||||
|
||||
|
@ -800,7 +750,7 @@ def parse_manpage_at_path(manpage_path, output_directory):
|
|||
parsers = [TypeDeroffManParser()]
|
||||
else:
|
||||
parsers = [Type1ManParser(), Type2ManParser(), Type4ManParser(), Type3ManParser(), TypeDarwinManParser(), TypeDeroffManParser()]
|
||||
parsersToTry = [p for p in parsers if p.isMyType(manpage)]
|
||||
parsersToTry = [p for p in parsers if p.is_my_type(manpage)]
|
||||
|
||||
success = False
|
||||
if not parsersToTry:
|
||||
|
@ -810,7 +760,7 @@ def parse_manpage_at_path(manpage_path, output_directory):
|
|||
parser_name = parser.name()
|
||||
add_diagnostic('Trying parser ' + parser_name)
|
||||
diagnostic_indent += 1
|
||||
success = parser.parseManPage(manpage)
|
||||
success = parser.parse_man_page(manpage)
|
||||
diagnostic_indent -= 1
|
||||
# Make sure empty files aren't reported as success
|
||||
if not built_command_output:
|
||||
|
|
47
share/tools/web_config/sample_prompts/informative_git.fish
Normal file
47
share/tools/web_config/sample_prompts/informative_git.fish
Normal file
|
@ -0,0 +1,47 @@
|
|||
# name: Informative Git Prompt
|
||||
# author: Mariusz Smykula <mariuszs at gmail.com>
|
||||
|
||||
set -g __fish_git_prompt_show_informative_status 1
|
||||
set -g __fish_git_prompt_hide_untrackedfiles 1
|
||||
|
||||
set -g __fish_git_prompt_color_branch magenta bold
|
||||
set -g __fish_git_prompt_showupstream "informative"
|
||||
set -g __fish_git_prompt_char_upstream_ahead "↑"
|
||||
set -g __fish_git_prompt_char_upstream_behind "↓"
|
||||
set -g __fish_git_prompt_char_upstream_prefix ""
|
||||
|
||||
set -g __fish_git_prompt_char_stagedstate "●"
|
||||
set -g __fish_git_prompt_char_dirtystate "✚"
|
||||
set -g __fish_git_prompt_char_untrackedfiles "…"
|
||||
set -g __fish_git_prompt_char_conflictedstate "✖"
|
||||
set -g __fish_git_prompt_char_cleanstate "✔"
|
||||
|
||||
set -g __fish_git_prompt_color_dirtystate blue
|
||||
set -g __fish_git_prompt_color_stagedstate yellow
|
||||
set -g __fish_git_prompt_color_invalidstate red
|
||||
set -g __fish_git_prompt_color_untrackedfiles $fish_color_normal
|
||||
set -g __fish_git_prompt_color_cleanstate green bold
|
||||
|
||||
|
||||
function fish_prompt --description 'Write out the prompt'
|
||||
|
||||
set -l last_status $status
|
||||
|
||||
if not set -q __fish_prompt_normal
|
||||
set -g __fish_prompt_normal (set_color normal)
|
||||
end
|
||||
|
||||
# PWD
|
||||
set_color $fish_color_cwd
|
||||
echo -n (prompt_pwd)
|
||||
set_color normal
|
||||
|
||||
printf '%s ' (__fish_git_prompt)
|
||||
|
||||
if not test $last_status -eq 0
|
||||
set_color $fish_color_error
|
||||
end
|
||||
|
||||
echo -n '$ '
|
||||
|
||||
end
|
|
@ -75,7 +75,6 @@ def better_color(c1, c2):
|
|||
if c1 in named_colors: return c2
|
||||
return c1
|
||||
|
||||
|
||||
def parse_color(color_str):
|
||||
""" A basic function to parse a color string, for example, 'red' '--bold' """
|
||||
comps = color_str.split(' ')
|
||||
|
@ -98,7 +97,6 @@ def parse_color(color_str):
|
|||
|
||||
return [color, background_color, bold, underline]
|
||||
|
||||
|
||||
def parse_bool(val):
|
||||
val = val.lower()
|
||||
if val.startswith('f') or val.startswith('0'): return False
|
||||
|
|
Loading…
Reference in a new issue