mirror of
https://github.com/fish-shell/fish-shell
synced 2024-12-27 05:13:10 +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';
|
wc = L'\b';
|
||||||
break;
|
break;
|
||||||
case L'e':
|
case L'e':
|
||||||
wc = L'\e';
|
wc = L'\x1B';
|
||||||
break;
|
break;
|
||||||
case L'f':
|
case L'f':
|
||||||
wc = 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_highlight_function(&highlight_shell);
|
||||||
reader_set_test_function(&reader_shell_test);
|
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_allow_autosuggesting(false);
|
||||||
|
reader_set_expand_abbreviations(false);
|
||||||
reader_set_exit_on_interrupt(true);
|
reader_set_exit_on_interrupt(true);
|
||||||
|
|
||||||
reader_set_buffer(commandline, wcslen(commandline));
|
reader_set_buffer(commandline, wcslen(commandline));
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
\a = alert (bell)
|
\a = alert (bell)
|
||||||
\b = backspace
|
\b = backspace
|
||||||
\c = produce no further output
|
\c = produce no further output
|
||||||
|
\e = escape
|
||||||
\f = form feed
|
\f = form feed
|
||||||
\n = new line
|
\n = new line
|
||||||
\r = carriage return
|
\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. */
|
case L'c': /* Cancel the rest of the output. */
|
||||||
this->early_exit = true;
|
this->early_exit = true;
|
||||||
break;
|
break;
|
||||||
|
case L'e': /* Escape */
|
||||||
|
this->append_output(L'\x1B');
|
||||||
|
break;
|
||||||
case L'f': /* Form feed. */
|
case L'f': /* Form feed. */
|
||||||
this->append_output(L'\f');
|
this->append_output(L'\f');
|
||||||
break;
|
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);
|
esc_value = esc_value * 16 + hex_to_bin(*p);
|
||||||
if (esc_length == 0)
|
if (esc_length == 0)
|
||||||
this->fatal_error(_(L"missing hexadecimal number in escape"));
|
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))
|
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. */
|
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)
|
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);
|
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++);
|
print_esc_char(*p++);
|
||||||
|
}
|
||||||
else if (*p == L'u' || *p == L'U')
|
else if (*p == L'u' || *p == L'U')
|
||||||
{
|
{
|
||||||
wchar_t esc_char = *p;
|
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
|
/* Print the text in FORMAT, using ARGV (with ARGC elements) for
|
||||||
arguments to any `%' directives.
|
arguments to any `%' directives.
|
||||||
Return the number of elements of ARGV used. */
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok['a'] = ok['A'] = ok['c'] = ok['d'] = ok['e'] = ok['E'] =
|
modify_allowed_format_specifiers(ok, "aAcdeEfFgGiosuxX", true);
|
||||||
ok['f'] = ok['F'] = ok['g'] = ok['G'] = ok['i'] = ok['o'] =
|
|
||||||
ok['s'] = ok['u'] = ok['x'] = ok['X'] = true;
|
|
||||||
|
|
||||||
for (;; f++, direc_length++)
|
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'I':
|
||||||
case L'\'':
|
case L'\'':
|
||||||
ok['a'] = ok['A'] = ok['c'] = ok['e'] = ok['E'] =
|
modify_allowed_format_specifiers(ok, "aAceEosxX", false);
|
||||||
ok['o'] = ok['s'] = ok['x'] = ok['X'] = false;
|
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
case '+':
|
case '+':
|
||||||
case ' ':
|
case ' ':
|
||||||
break;
|
break;
|
||||||
case L'#':
|
case L'#':
|
||||||
ok['c'] = ok['d'] = ok['i'] = ok['s'] = ok['u'] = false;
|
modify_allowed_format_specifiers(ok, "cdisu", false);
|
||||||
break;
|
break;
|
||||||
case '0':
|
case '0':
|
||||||
ok['c'] = ok['s'] = false;
|
modify_allowed_format_specifiers(ok, "cs", false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto no_more_flag_characters;
|
goto no_more_flag_characters;
|
||||||
|
@ -679,7 +692,7 @@ no_more_flag_characters:
|
||||||
{
|
{
|
||||||
++f;
|
++f;
|
||||||
++direc_length;
|
++direc_length;
|
||||||
ok['c'] = false;
|
modify_allowed_format_specifiers(ok, "c", false);
|
||||||
if (*f == L'*')
|
if (*f == L'*')
|
||||||
{
|
{
|
||||||
++f;
|
++f;
|
||||||
|
|
1
env.cpp
1
env.cpp
|
@ -137,7 +137,6 @@ struct env_node_t
|
||||||
|
|
||||||
class variable_entry_t
|
class variable_entry_t
|
||||||
{
|
{
|
||||||
bool exportv; /**< Whether the variable should be exported */
|
|
||||||
wcstring value; /**< Value of the variable */
|
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();
|
const wchar_t * const in = input.c_str();
|
||||||
|
|
||||||
int parse_ret;
|
int parse_ret;
|
||||||
switch (parse_ret = parse_util_locate_cmdsubst(in,
|
switch (parse_ret = parse_util_locate_cmdsubst(in, ¶n_begin, ¶n_end, false))
|
||||||
¶n_begin,
|
|
||||||
¶n_end,
|
|
||||||
0))
|
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
parser.error(SYNTAX_ERROR,
|
parser.error(SYNTAX_ERROR,
|
||||||
|
@ -1628,10 +1625,7 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
|
||||||
{
|
{
|
||||||
wchar_t *begin, *end;
|
wchar_t *begin, *end;
|
||||||
|
|
||||||
if (parse_util_locate_cmdsubst(input.c_str(),
|
if (parse_util_locate_cmdsubst(input.c_str(), &begin, &end, true) != 0)
|
||||||
&begin,
|
|
||||||
&end,
|
|
||||||
1) != 0)
|
|
||||||
{
|
{
|
||||||
parser.error(CMDSUBST_ERROR, -1, L"Command substitutions not allowed");
|
parser.error(CMDSUBST_ERROR, -1, L"Command substitutions not allowed");
|
||||||
return EXPAND_ERROR;
|
return EXPAND_ERROR;
|
||||||
|
@ -1939,3 +1933,42 @@ bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector<completion_t> *args)
|
||||||
}
|
}
|
||||||
return result;
|
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);
|
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 */
|
/* Terrible hacks */
|
||||||
bool fish_xdm_login_hack_hack_hack_hack(std::vector<std::string> *cmds, int argc, const char * const *argv);
|
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);
|
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;
|
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;
|
extern int g_fork_count;
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1209,6 +1209,7 @@
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
MACOSX_DEPLOYMENT_TARGET = 10.7;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
||||||
|
WARNING_CFLAGS = "-Wall";
|
||||||
};
|
};
|
||||||
name = "Release_C++11";
|
name = "Release_C++11";
|
||||||
};
|
};
|
||||||
|
@ -1361,6 +1362,7 @@
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
||||||
|
WARNING_CFLAGS = "-Wall";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
|
@ -1385,6 +1387,7 @@
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
MACOSX_DEPLOYMENT_TARGET = 10.6;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
USER_HEADER_SEARCH_PATHS = "$(SRCROOT)/osx/**";
|
||||||
|
WARNING_CFLAGS = "-Wall";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
#include "highlight.h"
|
#include "highlight.h"
|
||||||
#include "parse_tree.h"
|
#include "parse_tree.h"
|
||||||
#include "parse_exec.h"
|
#include "parse_exec.h"
|
||||||
|
#include "parse_util.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
The number of tests to run
|
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
|
class lru_node_test_t : public lru_node_t
|
||||||
{
|
{
|
||||||
public:
|
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__);
|
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 */
|
/** Test path functions */
|
||||||
static void test_path()
|
static void test_path()
|
||||||
{
|
{
|
||||||
|
@ -1771,9 +1853,11 @@ int main(int argc, char **argv)
|
||||||
test_tok();
|
test_tok();
|
||||||
test_fork();
|
test_fork();
|
||||||
test_parser();
|
test_parser();
|
||||||
|
test_utils();
|
||||||
test_lru();
|
test_lru();
|
||||||
test_expand();
|
test_expand();
|
||||||
test_fuzzy_match();
|
test_fuzzy_match();
|
||||||
|
test_abbreviations();
|
||||||
test_test();
|
test_test();
|
||||||
test_path();
|
test_path();
|
||||||
test_word_motion();
|
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)
|
if (! is_cmd && use_function)
|
||||||
is_cmd = function_exists_no_autoload(cmd, vars);
|
is_cmd = function_exists_no_autoload(cmd, vars);
|
||||||
|
|
||||||
|
if (! is_cmd)
|
||||||
|
is_cmd = expand_abbreviation(cmd, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Moving on to expensive tests
|
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);
|
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();
|
const wcstring working_directory = env_get_pwd_slash();
|
||||||
|
|
||||||
/* Tokenize the string */
|
/* Tokenize the string */
|
||||||
|
@ -1335,7 +1338,7 @@ void highlight_shell(const wcstring &buff, std::vector<int> &color, size_t pos,
|
||||||
{
|
{
|
||||||
wchar_t *begin, *end;
|
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;
|
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,
|
int parse_util_locate_cmdsubst(const wchar_t *in, wchar_t **begin, wchar_t **end, bool allow_incomplete)
|
||||||
wchar_t **begin,
|
|
||||||
wchar_t **end,
|
|
||||||
int allow_incomplete)
|
|
||||||
{
|
{
|
||||||
wchar_t *pos;
|
wchar_t *pos;
|
||||||
wchar_t prev=0;
|
wchar_t prev=0;
|
||||||
|
@ -243,73 +240,57 @@ int parse_util_locate_cmdsubst(const wchar_t *in,
|
||||||
return 1;
|
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;
|
const wchar_t * const cursor = buff + cursor_pos;
|
||||||
wchar_t *pos;
|
|
||||||
const wchar_t *cursor = buff + cursor_pos;
|
|
||||||
|
|
||||||
CHECK(buff,);
|
CHECK(buff,);
|
||||||
|
|
||||||
if (a)
|
const size_t bufflen = wcslen(buff);
|
||||||
{
|
assert(cursor_pos <= bufflen);
|
||||||
*a = (wchar_t *)buff;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
wchar_t *begin = NULL, *end = NULL;
|
||||||
}
|
if (parse_util_locate_cmdsubst(pos, &begin, &end, true) <= 0)
|
||||||
|
|
||||||
pos = (wchar_t *)buff;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
{
|
||||||
if (parse_util_locate_cmdsubst(pos,
|
/* No subshell found, all done */
|
||||||
&begin,
|
|
||||||
&end,
|
|
||||||
1) <= 0)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
No subshell found
|
|
||||||
*/
|
|
||||||
break;
|
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++;
|
begin++;
|
||||||
|
ap = begin;
|
||||||
if (a)
|
bp = end;
|
||||||
{
|
pos = begin + 1;
|
||||||
*a = begin;
|
|
||||||
}
|
}
|
||||||
|
else if (begin >= cursor)
|
||||||
if (b)
|
|
||||||
{
|
{
|
||||||
*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;
|
break;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (!*end)
|
|
||||||
{
|
{
|
||||||
break;
|
/* This command substitution ends before the cursor. Skip it. */
|
||||||
}
|
assert(end < cursor);
|
||||||
|
|
||||||
pos = end + 1;
|
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;
|
const wchar_t *begin, *end;
|
||||||
long pos;
|
long pos;
|
||||||
wchar_t *buffcpy;
|
|
||||||
|
|
||||||
const wchar_t *a = NULL, *b = NULL, *pa = NULL, *pb = NULL;
|
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 >= begin);
|
||||||
assert(end <= (buff+wcslen(buff)));
|
assert(end <= (buff+wcslen(buff)));
|
||||||
|
|
||||||
buffcpy = wcsndup(begin, end-begin);
|
const wcstring buffcpy = wcstring(begin, end-begin);
|
||||||
|
|
||||||
if (!buffcpy)
|
tokenizer_t tok(buffcpy.c_str(), TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS);
|
||||||
{
|
|
||||||
DIE_MEM();
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenizer_t tok(buffcpy, TOK_ACCEPT_UNFINISHED | TOK_SQUASH_ERRORS);
|
|
||||||
for (; tok_has_next(&tok); tok_next(&tok))
|
for (; tok_has_next(&tok); tok_next(&tok))
|
||||||
{
|
{
|
||||||
size_t tok_begin = tok_get_pos(&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)
|
if (tok_begin)
|
||||||
{
|
{
|
||||||
*tok_begin = a;
|
*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;
|
const wchar_t * const *arg;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
for (i=0, arg=argv; i < named_arguments.size(); i++)
|
for (i=0, arg=argv; i < named_arguments.size(); i++)
|
||||||
{
|
{
|
||||||
env_set(named_arguments.at(i).c_str(), *arg, ENV_LOCAL);
|
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)
|
if (*arg)
|
||||||
arg++;
|
arg++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *parse_util_unescape_wildcards(const wchar_t *str)
|
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]);
|
const wchar_t *end = quote_end(&cmd[i]);
|
||||||
//fwprintf( stderr, L"Jump %d\n", end-cmd );
|
//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];
|
res = cmd[i];
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -18,14 +18,14 @@
|
||||||
\param in the string to search for subshells
|
\param in the string to search for subshells
|
||||||
\param begin the starting paranthesis of the subshell
|
\param begin the starting paranthesis of the subshell
|
||||||
\param end the ending 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
|
\return -1 on syntax error, 0 if no subshells exist and 1 on sucess
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int parse_util_locate_cmdsubst(const wchar_t *in,
|
int parse_util_locate_cmdsubst(const wchar_t *in,
|
||||||
wchar_t **begin,
|
wchar_t **begin,
|
||||||
wchar_t **end,
|
wchar_t **end,
|
||||||
int flags);
|
bool accept_incomplete);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Find the beginning and end of the command substitution under the
|
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
|
for this, used by other shells like bash
|
||||||
and zsh).
|
and zsh).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (wcschr(cmd, L'='))
|
if (wcschr(cmd, L'='))
|
||||||
{
|
{
|
||||||
wchar_t *cpy = wcsdup(cmd);
|
wchar_t *cpy = wcsdup(cmd);
|
||||||
|
@ -2074,9 +2075,15 @@ int parser_t::parse_job(process_t *p,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
debug(0,
|
/*
|
||||||
_(L"Unknown command '%ls'"),
|
Handle unrecognized commands with standard
|
||||||
cmd?cmd:L"UNKNOWN");
|
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;
|
tmp = current_tokenizer_pos;
|
||||||
|
@ -2088,9 +2095,6 @@ int parser_t::parse_job(process_t *p,
|
||||||
|
|
||||||
job_set_flag(j, JOB_SKIP, 1);
|
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);
|
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,
|
switch (parse_util_locate_cmdsubst(arg_cpy,
|
||||||
¶n_begin,
|
¶n_begin,
|
||||||
¶n_end,
|
¶n_end,
|
||||||
0))
|
false))
|
||||||
{
|
{
|
||||||
case -1:
|
case -1:
|
||||||
err=1;
|
err=1;
|
||||||
|
|
202
reader.cpp
202
reader.cpp
|
@ -97,8 +97,8 @@ commence.
|
||||||
#include "iothread.h"
|
#include "iothread.h"
|
||||||
#include "intern.h"
|
#include "intern.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
|
|
||||||
#include "parse_util.h"
|
#include "parse_util.h"
|
||||||
|
#include "parser_keywords.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Maximum length of prefix string when printing completion
|
Maximum length of prefix string when printing completion
|
||||||
|
@ -182,6 +182,8 @@ static pthread_key_t generation_count_key;
|
||||||
/* A color is an int */
|
/* A color is an int */
|
||||||
typedef int color_t;
|
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
|
A struct describing the state of the interactive reader. These
|
||||||
states can be stacked, in case reader_readline() calls are
|
states can be stacked, in case reader_readline() calls are
|
||||||
|
@ -203,6 +205,9 @@ public:
|
||||||
/** When backspacing, we temporarily suppress autosuggestions */
|
/** When backspacing, we temporarily suppress autosuggestions */
|
||||||
bool suppress_autosuggestion;
|
bool suppress_autosuggestion;
|
||||||
|
|
||||||
|
/** Whether abbreviations are expanded */
|
||||||
|
bool expand_abbreviations;
|
||||||
|
|
||||||
/** The representation of the current screen contents */
|
/** The representation of the current screen contents */
|
||||||
screen_t screen;
|
screen_t screen;
|
||||||
|
|
||||||
|
@ -244,6 +249,9 @@ public:
|
||||||
/** Do what we need to do whenever our command line changes */
|
/** Do what we need to do whenever our command line changes */
|
||||||
void command_line_changed(void);
|
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. */
|
/** The current position of the cursor in buff. */
|
||||||
size_t buff_pos;
|
size_t buff_pos;
|
||||||
|
|
||||||
|
@ -326,6 +334,7 @@ public:
|
||||||
reader_data_t() :
|
reader_data_t() :
|
||||||
allow_autosuggestion(0),
|
allow_autosuggestion(0),
|
||||||
suppress_autosuggestion(0),
|
suppress_autosuggestion(0),
|
||||||
|
expand_abbreviations(0),
|
||||||
history(0),
|
history(0),
|
||||||
token_history_pos(0),
|
token_history_pos(0),
|
||||||
search_pos(0),
|
search_pos(0),
|
||||||
|
@ -635,6 +644,159 @@ void reader_data_t::command_line_changed()
|
||||||
s_generation_count++;
|
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. */
|
/** Sorts and remove any duplicate completions in the list. */
|
||||||
static void sort_and_make_unique(std::vector<completion_t> &l)
|
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
|
Set the specified string as the current buffer.
|
||||||
not modify prefix_width.
|
|
||||||
*/
|
*/
|
||||||
static void set_command_line_and_position(const wcstring &new_str, size_t pos)
|
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;
|
data->allow_autosuggestion = flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void reader_set_expand_abbreviations(bool flag)
|
||||||
|
{
|
||||||
|
data->expand_abbreviations = flag;
|
||||||
|
}
|
||||||
|
|
||||||
void reader_set_complete_function(complete_function_t f)
|
void reader_set_complete_function(complete_function_t f)
|
||||||
{
|
{
|
||||||
data->complete_func = f;
|
data->complete_func = f;
|
||||||
|
@ -2712,6 +2878,7 @@ static int read_i(void)
|
||||||
reader_set_highlight_function(&highlight_shell);
|
reader_set_highlight_function(&highlight_shell);
|
||||||
reader_set_test_function(&reader_shell_test);
|
reader_set_test_function(&reader_shell_test);
|
||||||
reader_set_allow_autosuggesting(true);
|
reader_set_allow_autosuggesting(true);
|
||||||
|
reader_set_expand_abbreviations(true);
|
||||||
reader_import_history_if_necessary();
|
reader_import_history_if_necessary();
|
||||||
|
|
||||||
parser_t &parser = parser_t::principal_parser();
|
parser_t &parser = parser_t::principal_parser();
|
||||||
|
@ -2851,7 +3018,6 @@ const wchar_t *reader_readline(void)
|
||||||
data->search_buff.clear();
|
data->search_buff.clear();
|
||||||
data->search_mode = NO_SEARCH;
|
data->search_mode = NO_SEARCH;
|
||||||
|
|
||||||
|
|
||||||
exec_prompt();
|
exec_prompt();
|
||||||
|
|
||||||
reader_super_highlight_me_plenty(data->buff_pos);
|
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:
|
case 0:
|
||||||
|
@ -3597,9 +3777,14 @@ const wchar_t *reader_readline(void)
|
||||||
/* Other, if a normal character, we add it to the command */
|
/* Other, if a normal character, we add it to the command */
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((!wchar_private(c)) && (((c>31) || (c==L'\n'))&& (c != 127)))
|
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 */
|
/* Regular character */
|
||||||
insert_char(c);
|
insert_char(c);
|
||||||
}
|
}
|
||||||
|
@ -3633,10 +3818,7 @@ const wchar_t *reader_readline(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
writestr(L"\n");
|
writestr(L"\n");
|
||||||
/*
|
|
||||||
if( comp )
|
|
||||||
halloc_free( comp );
|
|
||||||
*/
|
|
||||||
if (!reader_exit_forced())
|
if (!reader_exit_forced())
|
||||||
{
|
{
|
||||||
if (tcsetattr(0,TCSANOW,&old_modes)) /* return to previous mode */
|
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. */
|
/** Sets whether autosuggesting is allowed. */
|
||||||
void reader_set_allow_autosuggesting(bool flag);
|
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. */
|
/** Sets whether the reader should exit on ^C. */
|
||||||
void reader_set_exit_on_interrupt(bool flag);
|
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. */
|
/* 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);
|
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. */
|
/* 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);
|
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 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 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 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 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 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'
|
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
|
function __fish_complete_ftp -d 'Complete ftp, pftp' --argument-names ftp
|
||||||
complete -c $ftp -xa "(__fish_print_hostnames)" -d 'Hostname'
|
complete -c $ftp -xa "(__fish_print_hostnames)" -d 'Hostname'
|
||||||
tname'
|
|
||||||
complete -c $ftp -s 4 -d 'Use only IPv4 to contact any host'
|
complete -c $ftp -s 4 -d 'Use only IPv4 to contact any host'
|
||||||
host'
|
|
||||||
complete -c $ftp -s 6 -d 'Use IPv6 only'
|
complete -c $ftp -s 6 -d 'Use IPv6 only'
|
||||||
only'
|
|
||||||
complete -c $ftp -s p -d 'Use passive mode for data transfers'
|
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'
|
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 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 e -d 'Disable command editing and history support'
|
||||||
complete -c $ftp -s g -d 'Disable file name globbing'
|
complete -c $ftp -s g -d 'Disable file name globbing'
|
||||||
Disable file name globbing'
|
complete -c $ftp -s m -d 'Do not explicitly bind data and control channels to same interface'
|
||||||
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'
|
||||||
channels to same interface'
|
complete -c $ftp -s d -d 'Enable debugging'
|
||||||
v -d 'Verbose. Show all server responses and data transfer stats'
|
|
||||||
es and data transfer stats'
|
|
||||||
d -d 'Enable debugging'
|
|
||||||
end
|
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
|
function fish_command_not_found_handler --on-event fish_command_not_found
|
||||||
/usr/lib/command-not-found $argv
|
/usr/lib/command-not-found $argv
|
||||||
end
|
end
|
||||||
fish_command_not_found_handler $argv
|
|
||||||
else
|
|
||||||
# Ubuntu Feisty places this command in the regular path instead
|
# 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
|
function fish_command_not_found_handler --on-event fish_command_not_found
|
||||||
command-not-found $argv
|
command-not-found $argv
|
||||||
end
|
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
|
fish_command_not_found_handler $argv
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
|
@ -75,6 +75,8 @@
|
||||||
# 'upstream_equal', 'upstream_behind', 'upstream_ahead', and
|
# 'upstream_equal', 'upstream_behind', 'upstream_ahead', and
|
||||||
# 'upstream_diverged'.
|
# '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"
|
function __fish_git_prompt_show_upstream --description "Helper function for __fish_git_prompt"
|
||||||
# Ask git-config for some config options
|
# Ask git-config for some config options
|
||||||
set -l svn_remote
|
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 upstream git
|
||||||
set -l legacy
|
set -l legacy
|
||||||
set -l verbose
|
set -l verbose
|
||||||
|
set -l informative
|
||||||
set -l svn_url_pattern
|
set -l svn_url_pattern
|
||||||
set -l show_upstream $__fish_git_prompt_showupstream
|
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
|
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
|
set upstream $option
|
||||||
case verbose
|
case verbose
|
||||||
set verbose 1
|
set verbose 1
|
||||||
|
case informative
|
||||||
|
set informative 1
|
||||||
case legacy
|
case legacy
|
||||||
set legacy 1
|
set legacy 1
|
||||||
end
|
end
|
||||||
|
@ -176,30 +181,42 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi
|
||||||
end
|
end
|
||||||
|
|
||||||
# calculate the result
|
# calculate the result
|
||||||
if test -z "$verbose"
|
if test -n "$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
|
|
||||||
echo $count | read -l behind ahead
|
echo $count | read -l behind ahead
|
||||||
switch "$count"
|
switch "$count"
|
||||||
case '' # no upstream
|
case '' # no upstream
|
||||||
case "0 0" # equal to 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
|
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
|
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
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -216,10 +233,15 @@ function __fish_git_prompt --description "Prompt function for Git"
|
||||||
set -l u #untracked
|
set -l u #untracked
|
||||||
set -l c (__fish_git_prompt_current_branch_bare)
|
set -l c (__fish_git_prompt_current_branch_bare)
|
||||||
set -l p #upstream
|
set -l p #upstream
|
||||||
|
set -l informative_status
|
||||||
|
|
||||||
__fish_git_prompt_validate_chars
|
__fish_git_prompt_validate_chars
|
||||||
|
|
||||||
if test "true" = (git rev-parse --is-inside-work-tree ^/dev/null)
|
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"
|
if test -n "$__fish_git_prompt_showdirtystate"
|
||||||
set -l config (git config --bool bash.showDirtyState)
|
set -l config (git config --bool bash.showDirtyState)
|
||||||
if test "$config" != "false"
|
if test "$config" != "false"
|
||||||
|
@ -238,10 +260,12 @@ function __fish_git_prompt --description "Prompt function for Git"
|
||||||
set u $___fish_git_prompt_char_untrackedfiles
|
set u $___fish_git_prompt_char_untrackedfiles
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if test -n "$__fish_git_prompt_showupstream"
|
if test -n "$__fish_git_prompt_showupstream"
|
||||||
set p (__fish_git_prompt_show_upstream)
|
set p (__fish_git_prompt_show_upstream)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
__fish_git_prompt_validate_colors
|
__fish_git_prompt_validate_colors
|
||||||
|
@ -282,7 +306,7 @@ function __fish_git_prompt --description "Prompt function for Git"
|
||||||
set format " (%s)"
|
set format " (%s)"
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
### helper functions
|
### helper functions
|
||||||
|
@ -310,6 +334,46 @@ function __fish_git_prompt_dirty --description "__fish_git_prompt helper, tells
|
||||||
echo $dirty
|
echo $dirty
|
||||||
end
|
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"
|
function __fish_git_prompt_current_branch_bare --description "__fish_git_prompt helper, tells wheter or not the current branch is bare"
|
||||||
set -l 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)
|
echo (git rev-parse --git-dir ^/dev/null)
|
||||||
end
|
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"
|
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
|
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
|
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
|
end
|
||||||
if not set -q ___fish_git_prompt_char_stashstate
|
set -g $variable_done (set_color normal)
|
||||||
set -g ___fish_git_prompt_char_stashstate (set -q __fish_git_prompt_char_stashstate; and echo $__fish_git_prompt_char_stashstate; or echo '$')
|
else
|
||||||
end
|
set -g $variable ''
|
||||||
if not set -q ___fish_git_prompt_char_untrackedfiles
|
set -g $variable_done ''
|
||||||
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 '<>')
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
function __fish_git_prompt_validate_colors --description "__fish_git_prompt helper, checks color variables"
|
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"
|
__fish_git_prompt_set_color __fish_git_prompt_color
|
||||||
set -g ___fish_git_prompt_color (set_color $__fish_git_prompt_color)
|
__fish_git_prompt_set_color __fish_git_prompt_color_prefix
|
||||||
set -g ___fish_git_prompt_color_done (set_color normal)
|
__fish_git_prompt_set_color __fish_git_prompt_color_suffix
|
||||||
else
|
__fish_git_prompt_set_color __fish_git_prompt_color_bare
|
||||||
set -g ___fish_git_prompt_color ''
|
__fish_git_prompt_set_color __fish_git_prompt_color_merging
|
||||||
set -g ___fish_git_prompt_color_done ''
|
__fish_git_prompt_set_color __fish_git_prompt_color_branch
|
||||||
end
|
__fish_git_prompt_set_color __fish_git_prompt_color_cleanstate
|
||||||
end
|
__fish_git_prompt_set_color __fish_git_prompt_color_dirtystate
|
||||||
if not set -q ___fish_git_prompt_color_prefix
|
__fish_git_prompt_set_color __fish_git_prompt_color_stagedstate
|
||||||
if test -n "$__fish_git_prompt_color_prefix"
|
__fish_git_prompt_set_color __fish_git_prompt_color_invalidstate
|
||||||
set -g ___fish_git_prompt_color_prefix (set_color $__fish_git_prompt_color_prefix)
|
__fish_git_prompt_set_color __fish_git_prompt_color_stashstate
|
||||||
set -g ___fish_git_prompt_color_prefix_done (set_color normal)
|
__fish_git_prompt_set_color __fish_git_prompt_color_untrackedfiles
|
||||||
else
|
__fish_git_prompt_set_color __fish_git_prompt_color_upstream
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
set -l varargs
|
set -l varargs
|
||||||
|
|
|
@ -59,19 +59,19 @@ def flush_diagnostics(where):
|
||||||
# This maps commands to lists of completions
|
# This maps commands to lists of completions
|
||||||
already_output_completions = {}
|
already_output_completions = {}
|
||||||
|
|
||||||
def compileAndSearch(regex, input):
|
def compile_and_search(regex, input):
|
||||||
options_section_regex = re.compile(regex , re.DOTALL)
|
options_section_regex = re.compile(regex , re.DOTALL)
|
||||||
options_section_matched = re.search( options_section_regex, input)
|
options_section_matched = re.search( options_section_regex, input)
|
||||||
return options_section_matched
|
return options_section_matched
|
||||||
|
|
||||||
def unquoteDoubleQuotes(data):
|
def unquote_double_quotes(data):
|
||||||
if (len(data) < 2):
|
if (len(data) < 2):
|
||||||
return data
|
return data
|
||||||
if data[0] == '"' and data[len(data)-1] == '"':
|
if data[0] == '"' and data[len(data)-1] == '"':
|
||||||
data = data[1:len(data)-1]
|
data = data[1:len(data)-1]
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def unquoteSingleQuotes(data):
|
def unquote_single_quotes(data):
|
||||||
if (len(data) < 2):
|
if (len(data) < 2):
|
||||||
return data
|
return data
|
||||||
if data[0] == '`' and data[len(data)-1] == '\'':
|
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)
|
output_complete_command(escaped_cmd, fish_options, truncated_description, built_command_output)
|
||||||
|
|
||||||
|
def remove_groff_formatting(data):
|
||||||
|
|
||||||
def removeGroffFormatting(data):
|
|
||||||
# data = data.replace("\fI","")
|
|
||||||
# data = data.replace("\fP","")
|
|
||||||
data = data.replace("\\fI","")
|
data = data.replace("\\fI","")
|
||||||
data = data.replace("\\fP","")
|
data = data.replace("\\fP","")
|
||||||
data = data.replace("\\f1","")
|
data = data.replace("\\f1","")
|
||||||
|
@ -217,26 +213,26 @@ def removeGroffFormatting(data):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
class ManParser:
|
class ManParser:
|
||||||
def isMyType(self, manpage):
|
def is_my_type(self, manpage):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def parseManPage(self, manpage):
|
def parse_man_page(self, manpage):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return "no-name"
|
return "no-name"
|
||||||
|
|
||||||
class Type1ManParser(ManParser):
|
class Type1ManParser(ManParser):
|
||||||
def isMyType(self, manpage):
|
def is_my_type(self, manpage):
|
||||||
# print manpage
|
# print manpage
|
||||||
options_section_matched = compileAndSearch("\.SH \"OPTIONS\"(.*?)", manpage)
|
options_section_matched = compile_and_search("\.SH \"OPTIONS\"(.*?)", manpage)
|
||||||
|
|
||||||
if options_section_matched == None:
|
if options_section_matched == None:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
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_regex = re.compile( "\.SH \"OPTIONS\"(.*?)(\.SH|\Z)", re.DOTALL)
|
||||||
options_section_matched = re.search( options_section_regex, manpage)
|
options_section_matched = re.search( options_section_regex, manpage)
|
||||||
|
|
||||||
|
@ -256,27 +252,22 @@ class Type1ManParser(ManParser):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
while (options_matched != None):
|
while (options_matched != None):
|
||||||
# print len(options_matched.groups())
|
|
||||||
# print options_matched.group()
|
|
||||||
data = options_matched.group(1)
|
data = options_matched.group(1)
|
||||||
last_dotpp_index = data.rfind(".PP")
|
last_dotpp_index = data.rfind(".PP")
|
||||||
if (last_dotpp_index != -1):
|
if (last_dotpp_index != -1):
|
||||||
data = data[last_dotpp_index+3:]
|
data = data[last_dotpp_index+3:]
|
||||||
|
|
||||||
data = removeGroffFormatting(data)
|
data = remove_groff_formatting(data)
|
||||||
data = data.split(".RS 4")
|
data = data.split(".RS 4")
|
||||||
# print data
|
|
||||||
if (len (data) > 1): #and len(data[1]) <= 300):
|
if (len (data) > 1): #and len(data[1]) <= 300):
|
||||||
optionName = data[0].strip()
|
optionName = data[0].strip()
|
||||||
|
|
||||||
if ( optionName.find("-") == -1):
|
if ( optionName.find("-") == -1):
|
||||||
add_diagnostic(optionName + " doesn't contain - ")
|
add_diagnostic(optionName + " doesn't contain - ")
|
||||||
# return False
|
|
||||||
else:
|
else:
|
||||||
optionName = unquoteDoubleQuotes(optionName)
|
optionName = unquote_double_quotes(optionName)
|
||||||
optionName = unquoteSingleQuotes(optionName)
|
optionName = unquote_single_quotes(optionName)
|
||||||
optionDescription = data[1].strip().replace("\n"," ")
|
optionDescription = data[1].strip().replace("\n"," ")
|
||||||
# print >> sys.stderr, "Option: ", optionName," Description: ", optionDescription , '\n'
|
|
||||||
built_command(optionName, optionDescription)
|
built_command(optionName, optionDescription)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -295,7 +286,7 @@ class Type1ManParser(ManParser):
|
||||||
return False
|
return False
|
||||||
while options_matched != None:
|
while options_matched != None:
|
||||||
data = options_matched.group(2)
|
data = options_matched.group(2)
|
||||||
data = removeGroffFormatting(data)
|
data = remove_groff_formatting(data)
|
||||||
data = data.strip()
|
data = data.strip()
|
||||||
data = data.split("\n",1)
|
data = data.split("\n",1)
|
||||||
if (len(data)>1 and len(data[1].strip())>0): # and len(data[1])<400):
|
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):
|
if ( optionName.find("-") == -1):
|
||||||
add_diagnostic(optionName + "doesn't contains -")
|
add_diagnostic(optionName + "doesn't contains -")
|
||||||
else:
|
else:
|
||||||
optionName = unquoteDoubleQuotes(optionName)
|
optionName = unquote_double_quotes(optionName)
|
||||||
optionName = unquoteSingleQuotes(optionName)
|
optionName = unquote_single_quotes(optionName)
|
||||||
optionDescription = data[1].strip().replace("\n"," ")
|
optionDescription = data[1].strip().replace("\n"," ")
|
||||||
# print "Option: ", optionName," Description: ", optionDescription , '\n'
|
|
||||||
built_command(optionName, optionDescription)
|
built_command(optionName, optionDescription)
|
||||||
else:
|
else:
|
||||||
add_diagnostic('Unable to split option from description')
|
add_diagnostic('Unable to split option from description')
|
||||||
|
@ -330,27 +320,21 @@ class Type1ManParser(ManParser):
|
||||||
while options_matched != None:
|
while options_matched != None:
|
||||||
data = options_matched.group(1)
|
data = options_matched.group(1)
|
||||||
|
|
||||||
# print "Data is : ", data
|
data = remove_groff_formatting(data)
|
||||||
data = removeGroffFormatting(data)
|
|
||||||
data = data.strip()
|
data = data.strip()
|
||||||
data = data.split("\n",1)
|
data = data.split("\n",1)
|
||||||
if (len(data)>1 and len(data[1].strip())>0): # and len(data[1])<400):
|
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())
|
optionName = re.sub(trailing_num_regex, "", data[0].strip())
|
||||||
|
|
||||||
if ('-' not in optionName):
|
if ('-' not in optionName):
|
||||||
add_diagnostic(optionName + " doesn't contain -")
|
add_diagnostic(optionName + " doesn't contain -")
|
||||||
else:
|
else:
|
||||||
optionName = optionName.strip()
|
optionName = optionName.strip()
|
||||||
optionName = unquoteDoubleQuotes(optionName)
|
optionName = unquote_double_quotes(optionName)
|
||||||
optionName = unquoteSingleQuotes(optionName)
|
optionName = unquote_single_quotes(optionName)
|
||||||
optionDescription = data[1].strip().replace("\n"," ")
|
optionDescription = data[1].strip().replace("\n"," ")
|
||||||
# print "Option: ", optionName," Description: ", optionDescription , '\n'
|
|
||||||
built_command(optionName, optionDescription)
|
built_command(optionName, optionDescription)
|
||||||
else:
|
else:
|
||||||
# print data
|
|
||||||
add_diagnostic('Unable to split option from description')
|
add_diagnostic('Unable to split option from description')
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -363,31 +347,21 @@ class Type1ManParser(ManParser):
|
||||||
|
|
||||||
|
|
||||||
class Type2ManParser(ManParser):
|
class Type2ManParser(ManParser):
|
||||||
def isMyType(self, manpage):
|
def is_my_type(self, manpage):
|
||||||
options_section_matched = compileAndSearch("\.SH OPTIONS(.*?)", manpage)
|
options_section_matched = compile_and_search("\.SH OPTIONS(.*?)", manpage)
|
||||||
|
|
||||||
if options_section_matched == None:
|
if options_section_matched == None:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
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_regex = re.compile( "\.SH OPTIONS(.*?)(\.SH|\Z)", re.DOTALL)
|
||||||
options_section_matched = re.search( options_section_regex, manpage)
|
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)
|
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("\.[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)
|
options_matched = re.search(options_parts_regex, options_section)
|
||||||
add_diagnostic('Command is ' + CMDNAME)
|
add_diagnostic('Command is ' + CMDNAME)
|
||||||
|
|
||||||
|
@ -396,56 +370,46 @@ class Type2ManParser(ManParser):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
while (options_matched != None):
|
while (options_matched != None):
|
||||||
# print len(options_matched.groups())
|
|
||||||
data = options_matched.group(3)
|
data = options_matched.group(3)
|
||||||
|
|
||||||
data = removeGroffFormatting(data)
|
data = remove_groff_formatting(data)
|
||||||
|
|
||||||
data = data.strip()
|
data = data.strip()
|
||||||
|
|
||||||
data = data.split("\n",1)
|
data = data.split("\n",1)
|
||||||
# print >> sys.stderr, data
|
|
||||||
if (len(data)>1 and len(data[1].strip())>0): # and len(data[1])<400):
|
if (len(data)>1 and len(data[1].strip())>0): # and len(data[1])<400):
|
||||||
optionName = data[0].strip()
|
optionName = data[0].strip()
|
||||||
if '-' not in optionName:
|
if '-' not in optionName:
|
||||||
add_diagnostic(optionName + " doesn't contain -")
|
add_diagnostic(optionName + " doesn't contain -")
|
||||||
else:
|
else:
|
||||||
optionName = unquoteDoubleQuotes(optionName)
|
optionName = unquote_double_quotes(optionName)
|
||||||
optionName = unquoteSingleQuotes(optionName)
|
optionName = unquote_single_quotes(optionName)
|
||||||
optionDescription = data[1].strip().replace("\n"," ")
|
optionDescription = data[1].strip().replace("\n"," ")
|
||||||
# print "Option: ", optionName," Description: ", optionDescription , '\n'
|
|
||||||
built_command(optionName, optionDescription)
|
built_command(optionName, optionDescription)
|
||||||
else:
|
else:
|
||||||
# print >> sys.stderr, data
|
|
||||||
add_diagnostic('Unable to split option from description')
|
add_diagnostic('Unable to split option from description')
|
||||||
|
|
||||||
# return False
|
|
||||||
|
|
||||||
options_section = options_section[options_matched.end()-3:]
|
options_section = options_section[options_matched.end()-3:]
|
||||||
options_matched = re.search(options_parts_regex, options_section)
|
options_matched = re.search(options_parts_regex, options_section)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return "Type2"
|
return "Type2"
|
||||||
|
|
||||||
|
|
||||||
class Type3ManParser(ManParser):
|
class Type3ManParser(ManParser):
|
||||||
def isMyType(self, manpage):
|
def is_my_type(self, manpage):
|
||||||
options_section_matched = compileAndSearch("\.SH DESCRIPTION(.*?)", manpage)
|
options_section_matched = compile_and_search("\.SH DESCRIPTION(.*?)", manpage)
|
||||||
|
|
||||||
if options_section_matched == None:
|
if options_section_matched == None:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
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_regex = re.compile( "\.SH DESCRIPTION(.*?)(\.SH|\Z)", re.DOTALL)
|
||||||
options_section_matched = re.search( options_section_regex, manpage)
|
options_section_matched = re.search( options_section_regex, manpage)
|
||||||
|
|
||||||
options_section = options_section_matched.group(1)
|
options_section = options_section_matched.group(1)
|
||||||
# print options_section
|
|
||||||
# sys.exit(1)
|
|
||||||
options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL)
|
options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL)
|
||||||
options_matched = re.search(options_parts_regex, options_section)
|
options_matched = re.search(options_parts_regex, options_section)
|
||||||
add_diagnostic('Command is ' + CMDNAME)
|
add_diagnostic('Command is ' + CMDNAME)
|
||||||
|
@ -455,10 +419,9 @@ class Type3ManParser(ManParser):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
while (options_matched != None):
|
while (options_matched != None):
|
||||||
# print len(options_matched.groups())
|
|
||||||
data = options_matched.group(1)
|
data = options_matched.group(1)
|
||||||
|
|
||||||
data = removeGroffFormatting(data)
|
data = remove_groff_formatting(data)
|
||||||
data = data.strip()
|
data = data.strip()
|
||||||
data = data.split("\n",1)
|
data = data.split("\n",1)
|
||||||
|
|
||||||
|
@ -467,10 +430,9 @@ class Type3ManParser(ManParser):
|
||||||
if ( optionName.find("-") == -1):
|
if ( optionName.find("-") == -1):
|
||||||
add_diagnostic(optionName + "doesn't contain -")
|
add_diagnostic(optionName + "doesn't contain -")
|
||||||
else:
|
else:
|
||||||
optionName = unquoteDoubleQuotes(optionName)
|
optionName = unquote_double_quotes(optionName)
|
||||||
optionName = unquoteSingleQuotes(optionName)
|
optionName = unquote_single_quotes(optionName)
|
||||||
optionDescription = data[1].strip().replace("\n"," ")
|
optionDescription = data[1].strip().replace("\n"," ")
|
||||||
# print >> sys.stderr, "Option: ", optionName," Description: ", optionDescription , '\n'
|
|
||||||
built_command(optionName, optionDescription)
|
built_command(optionName, optionDescription)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -481,27 +443,24 @@ class Type3ManParser(ManParser):
|
||||||
options_matched = re.search(options_parts_regex, options_section)
|
options_matched = re.search(options_parts_regex, options_section)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return "Type3"
|
return "Type3"
|
||||||
|
|
||||||
|
|
||||||
class Type4ManParser(ManParser):
|
class Type4ManParser(ManParser):
|
||||||
def isMyType(self, manpage):
|
def is_my_type(self, manpage):
|
||||||
options_section_matched = compileAndSearch("\.SH FUNCTION LETTERS(.*?)", manpage)
|
options_section_matched = compile_and_search("\.SH FUNCTION LETTERS(.*?)", manpage)
|
||||||
|
|
||||||
if options_section_matched == None:
|
if options_section_matched == None:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
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_regex = re.compile( "\.SH FUNCTION LETTERS(.*?)(\.SH|\Z)", re.DOTALL)
|
||||||
options_section_matched = re.search( options_section_regex, manpage)
|
options_section_matched = re.search( options_section_regex, manpage)
|
||||||
|
|
||||||
options_section = options_section_matched.group(1)
|
options_section = options_section_matched.group(1)
|
||||||
# print options_section
|
|
||||||
# sys.exit(1)
|
|
||||||
options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL)
|
options_parts_regex = re.compile("\.TP(.*?)\.TP", re.DOTALL)
|
||||||
options_matched = re.search(options_parts_regex, options_section)
|
options_matched = re.search(options_parts_regex, options_section)
|
||||||
add_diagnostic('Command is ' + CMDNAME)
|
add_diagnostic('Command is ' + CMDNAME)
|
||||||
|
@ -511,10 +470,9 @@ class Type4ManParser(ManParser):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
while (options_matched != None):
|
while (options_matched != None):
|
||||||
# print len(options_matched.groups())
|
|
||||||
data = options_matched.group(1)
|
data = options_matched.group(1)
|
||||||
|
|
||||||
data = removeGroffFormatting(data)
|
data = remove_groff_formatting(data)
|
||||||
data = data.strip()
|
data = data.strip()
|
||||||
data = data.split("\n",1)
|
data = data.split("\n",1)
|
||||||
|
|
||||||
|
@ -523,10 +481,9 @@ class Type4ManParser(ManParser):
|
||||||
if ( optionName.find("-") == -1):
|
if ( optionName.find("-") == -1):
|
||||||
add_diagnostic(optionName + " doesn't contain - ")
|
add_diagnostic(optionName + " doesn't contain - ")
|
||||||
else:
|
else:
|
||||||
optionName = unquoteDoubleQuotes(optionName)
|
optionName = unquote_double_quotes(optionName)
|
||||||
optionName = unquoteSingleQuotes(optionName)
|
optionName = unquote_single_quotes(optionName)
|
||||||
optionDescription = data[1].strip().replace("\n"," ")
|
optionDescription = data[1].strip().replace("\n"," ")
|
||||||
# print "Option: ", optionName," Description: ", optionDescription , '\n'
|
|
||||||
built_command(optionName, optionDescription)
|
built_command(optionName, optionDescription)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
@ -542,8 +499,8 @@ class Type4ManParser(ManParser):
|
||||||
return "Type4"
|
return "Type4"
|
||||||
|
|
||||||
class TypeDarwinManParser(ManParser):
|
class TypeDarwinManParser(ManParser):
|
||||||
def isMyType(self, manpage):
|
def is_my_type(self, manpage):
|
||||||
options_section_matched = compileAndSearch("\.S[hH] DESCRIPTION", manpage)
|
options_section_matched = compile_and_search("\.S[hH] DESCRIPTION", manpage)
|
||||||
return options_section_matched != None
|
return options_section_matched != None
|
||||||
|
|
||||||
def trim_groff(self, line):
|
def trim_groff(self, line):
|
||||||
|
@ -572,9 +529,6 @@ class TypeDarwinManParser(ManParser):
|
||||||
line = line[3:]
|
line = line[3:]
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Replace some groff escapes. There's a lot we don't bother to handle.
|
# Replace some groff escapes. There's a lot we don't bother to handle.
|
||||||
def groff_replace_escapes(self, line):
|
def groff_replace_escapes(self, line):
|
||||||
line = line.replace('.Nm', CMDNAME)
|
line = line.replace('.Nm', CMDNAME)
|
||||||
|
@ -586,7 +540,7 @@ class TypeDarwinManParser(ManParser):
|
||||||
def is_option(self, line):
|
def is_option(self, line):
|
||||||
return line.startswith('.It Fl')
|
return line.startswith('.It Fl')
|
||||||
|
|
||||||
def parseManPage(self, manpage):
|
def parse_man_page(self, manpage):
|
||||||
got_something = False
|
got_something = False
|
||||||
lines = manpage.splitlines()
|
lines = manpage.splitlines()
|
||||||
# Discard lines until we get to ".sh Description"
|
# Discard lines until we get to ".sh Description"
|
||||||
|
@ -626,9 +580,6 @@ class TypeDarwinManParser(ManParser):
|
||||||
desc_lines.append(line)
|
desc_lines.append(line)
|
||||||
desc = ' '.join(desc_lines)
|
desc = ' '.join(desc_lines)
|
||||||
|
|
||||||
# print "name: ", name
|
|
||||||
# print "desc: ", desc
|
|
||||||
|
|
||||||
if name == '-':
|
if name == '-':
|
||||||
# Skip double -- arguments
|
# Skip double -- arguments
|
||||||
continue
|
continue
|
||||||
|
@ -647,7 +598,7 @@ class TypeDarwinManParser(ManParser):
|
||||||
|
|
||||||
|
|
||||||
class TypeDeroffManParser(ManParser):
|
class TypeDeroffManParser(ManParser):
|
||||||
def isMyType(self, manpage):
|
def is_my_type(self, manpage):
|
||||||
return True # We're optimists
|
return True # We're optimists
|
||||||
|
|
||||||
def is_option(self, line):
|
def is_option(self, line):
|
||||||
|
@ -656,7 +607,7 @@ class TypeDeroffManParser(ManParser):
|
||||||
def could_be_description(self, line):
|
def could_be_description(self, line):
|
||||||
return len(line) > 0 and not line.startswith('-')
|
return len(line) > 0 and not line.startswith('-')
|
||||||
|
|
||||||
def parseManPage(self, manpage):
|
def parse_man_page(self, manpage):
|
||||||
d = Deroffer()
|
d = Deroffer()
|
||||||
d.deroff(manpage)
|
d.deroff(manpage)
|
||||||
output = d.get_output()
|
output = d.get_output()
|
||||||
|
@ -697,7 +648,6 @@ class TypeDeroffManParser(ManParser):
|
||||||
|
|
||||||
return got_something
|
return got_something
|
||||||
|
|
||||||
|
|
||||||
def name(self):
|
def name(self):
|
||||||
return "Deroffing man parser"
|
return "Deroffing man parser"
|
||||||
|
|
||||||
|
@ -800,7 +750,7 @@ def parse_manpage_at_path(manpage_path, output_directory):
|
||||||
parsers = [TypeDeroffManParser()]
|
parsers = [TypeDeroffManParser()]
|
||||||
else:
|
else:
|
||||||
parsers = [Type1ManParser(), Type2ManParser(), Type4ManParser(), Type3ManParser(), TypeDarwinManParser(), TypeDeroffManParser()]
|
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
|
success = False
|
||||||
if not parsersToTry:
|
if not parsersToTry:
|
||||||
|
@ -810,7 +760,7 @@ def parse_manpage_at_path(manpage_path, output_directory):
|
||||||
parser_name = parser.name()
|
parser_name = parser.name()
|
||||||
add_diagnostic('Trying parser ' + parser_name)
|
add_diagnostic('Trying parser ' + parser_name)
|
||||||
diagnostic_indent += 1
|
diagnostic_indent += 1
|
||||||
success = parser.parseManPage(manpage)
|
success = parser.parse_man_page(manpage)
|
||||||
diagnostic_indent -= 1
|
diagnostic_indent -= 1
|
||||||
# Make sure empty files aren't reported as success
|
# Make sure empty files aren't reported as success
|
||||||
if not built_command_output:
|
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
|
if c1 in named_colors: return c2
|
||||||
return c1
|
return c1
|
||||||
|
|
||||||
|
|
||||||
def parse_color(color_str):
|
def parse_color(color_str):
|
||||||
""" A basic function to parse a color string, for example, 'red' '--bold' """
|
""" A basic function to parse a color string, for example, 'red' '--bold' """
|
||||||
comps = color_str.split(' ')
|
comps = color_str.split(' ')
|
||||||
|
@ -98,7 +97,6 @@ def parse_color(color_str):
|
||||||
|
|
||||||
return [color, background_color, bold, underline]
|
return [color, background_color, bold, underline]
|
||||||
|
|
||||||
|
|
||||||
def parse_bool(val):
|
def parse_bool(val):
|
||||||
val = val.lower()
|
val = val.lower()
|
||||||
if val.startswith('f') or val.startswith('0'): return False
|
if val.startswith('f') or val.startswith('0'): return False
|
||||||
|
|
Loading…
Reference in a new issue