Merge branch 'master' into ast

Conflicts:
	complete.cpp
This commit is contained in:
ridiculousfish 2013-10-27 13:37:14 -07:00
commit 964c7e6f3b
28 changed files with 167 additions and 107 deletions

View file

@ -66,6 +66,12 @@ To switch your default shell back, you can run:
Substitute /bin/bash with /bin/tcsh or /bin/zsh as appropriate.
## Optional Dependencies
In order to generate completions from man pages compressed with either lzma or xz, you may need to install an extra Python package.
Python versions prior to 2.6 are not supported. For Python versions 2.6 to 3.2 you need to install the module `backports.lzma`. How to install it depends on your system and how you installed Python. Most Linux distributions should include it as a package named `backports-lzma` (or similar). From version 3.3 onwards, Python already includes the required module.
## Contact Us
Questions, comments, rants and raves can be posted to the official fish mailing list at <https://lists.sourceforge.net/lists/listinfo/fish-users> or join us on our IRC channel [#fish at irc.oftc.net](https://webchat.oftc.net/?channels=fish).

View file

@ -1618,24 +1618,24 @@ static int builtin_echo(parser_t &parser, wchar_t **argv)
{
case L'n':
print_newline = false;
break;
break;
case L'e':
interpret_special_chars = true;
break;
break;
case L's':
// fish-specific extension,
// which we should try to nix
print_spaces = false;
break;
break;
case L'E':
interpret_special_chars = false;
break;
break;
}
}
}
else
{
invalid_echo_option:
invalid_echo_option:
break;
}
argv++;

View file

@ -169,7 +169,7 @@ static void write_part(const wchar_t *begin,
out.push_back(L'\n');
break;
}
default:
{
break;

View file

@ -698,7 +698,6 @@ static int builtin_set(parser_t &parser, wchar_t **argv)
Slice mode
*/
size_t idx_count, val_count;
wcstring_list_t values;
std::vector<long> indexes;
wcstring_list_t result;

View file

@ -1630,7 +1630,7 @@ void completer_t::complete_param_expand(const wcstring &sstr, bool do_file)
if (expand_string(comp_str,
this->completions,
flags ) == EXPAND_ERROR)
flags) == EXPAND_ERROR)
{
debug(3, L"Error while expanding string '%ls'", comp_str);
}

View file

@ -127,7 +127,7 @@ public:
completion_t(const wcstring &comp, const wcstring &desc = L"", string_fuzzy_match_t match = string_fuzzy_match_t(fuzzy_match_exact), int flags_val = 0);
completion_t(const completion_t &);
completion_t &operator=(const completion_t &);
/* Compare two completions. No operating overlaoding to make this always explicit (there's potentially multiple ways to compare completions). */
static bool is_alphabetically_less_than(const completion_t &a, const completion_t &b);
static bool is_alphabetically_equal_to(const completion_t &a, const completion_t &b);

View file

@ -398,6 +398,9 @@ start_conversion:
{
debug(0, L"%d %d", in_len, out_len);
debug(0, L"Error while converting from to string");
/* Terminate the output string. */
free(out);
return 0;
}

View file

@ -790,11 +790,11 @@ void exec_job(parser_t &parser, job_t *j)
echo alpha | cat < beta.txt
Should cat output alpha or beta? bash and ksh output 'beta', tcsh gets it right and complains about ambiguity, and zsh outputs both (!). No shells appear to output 'alpha', so we match bash here. That would mean putting the pipe first, so that it gets trumped by the file redirection.
However, eval does this:
echo "begin; $argv "\n" ;end eval2_inner <&3 3<&-" | source 3<&0
which depends on the redirection being evaluated before the pipe. So the write end of the pipe comes first, the read pipe of the pipe comes last. See issue #966.
*/
@ -811,7 +811,7 @@ void exec_job(parser_t &parser, job_t *j)
/* The explicit IO redirections associated with the process */
process_net_io_chain.append(p->io_chain());
/* Read pipe goes last */
if (p != j->first_process)
{
@ -820,7 +820,7 @@ void exec_job(parser_t &parser, job_t *j)
pipe_read->pipe_fd[0] = pipe_current_read;
process_net_io_chain.push_back(pipe_read);
}
/*
This call is used so the global environment variable array
@ -1243,10 +1243,10 @@ void exec_job(parser_t &parser, job_t *j)
*/
bool fork_was_skipped = false;
const shared_ptr<io_data_t> stdout_io = process_net_io_chain.get_io_for_fd(STDOUT_FILENO);
const shared_ptr<io_data_t> stderr_io = process_net_io_chain.get_io_for_fd(STDERR_FILENO);
/* If we are outputting to a file, we have to actually do it, even if we have no output, so that we can truncate the file. Does not apply to /dev/null. */
bool must_fork = redirection_is_to_real_file(stdout_io.get()) || redirection_is_to_real_file(stderr_io.get());
if (! must_fork)

View file

@ -1752,15 +1752,15 @@ int expand_string(const wcstring &input, std::vector<completion_t> &output, expa
remove_internal_separator(next_str, (EXPAND_SKIP_WILDCARDS & flags) ? true : false);
const wchar_t *next = next_str.c_str();
const bool has_wildcard = wildcard_has(next, 1);
if (has_wildcard && (flags & EXECUTABLES_ONLY))
{
// Don't do wildcard expansion for executables. See #785. So do nothing here.
}
else if (((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) ||
has_wildcard)
has_wildcard)
{
const wchar_t *start, *rest;

View file

@ -98,8 +98,6 @@ char *tparm_solaris_kludge(char *str, ...)
|| (enter_reverse_mode && ! strcmp(str, enter_reverse_mode))
|| (enter_shadow_mode && ! strcmp(str, enter_shadow_mode))
|| (exit_shadow_mode && ! strcmp(str, exit_shadow_mode))
|| (enter_standout_mode && ! strcmp(str, enter_standout_mode))
|| (exit_standout_mode && ! strcmp(str, exit_standout_mode))
|| (enter_secure_mode && ! strcmp(str, enter_secure_mode))
|| (enter_bold_mode && ! strcmp(str, enter_bold_mode)))
{
@ -1508,7 +1506,7 @@ static int mk_wcswidth(const wchar_t *pwcs, size_t n)
{
if (pwcs[i] == L'\0')
break;
int w = mk_wcwidth(pwcs[i]);
if (w < 0)
{

View file

@ -365,18 +365,15 @@ static int fish_parse_opt(int argc, char **argv, std::vector<std::string> *out_c
is_login |= (strcmp(argv[0], "-fish") == 0);
/*
We are an interactive session if we have not been given an
explicit command to execute, _and_ stdin is a tty.
*/
is_interactive_session &= ! has_cmd;
is_interactive_session &= (my_optind == argc);
is_interactive_session &= isatty(STDIN_FILENO);
/*
We are also an interactive session if we have are forced-
*/
is_interactive_session |= force_interactive;
/* We are an interactive session if we are either forced, or have not been given an explicit command to execute and stdin is a tty. */
if (force_interactive)
{
is_interactive_session = true;
}
else if (is_interactive_session)
{
is_interactive_session = ! has_cmd && (my_optind == argc) && isatty(STDIN_FILENO);
}
return my_optind;
}
@ -389,7 +386,6 @@ int main(int argc, char **argv)
set_main_thread();
setup_fork_guards();
save_term_foreground_process_group();
wsetlocale(LC_ALL, L"");
is_interactive_session=1;
@ -410,6 +406,12 @@ int main(int argc, char **argv)
no_exec = 0;
}
/* Only save (and therefore restore) the fg process group if we are interactive. See #197, #1002 */
if (is_interactive_session)
{
save_term_foreground_process_group();
}
const struct config_paths_t paths = determine_config_directory_paths(argv[0]);
proc_init();
@ -511,6 +513,7 @@ int main(int argc, char **argv)
proc_fire_event(L"PROCESS_EXIT", EVENT_EXIT, getpid(), res);
restore_term_mode();
restore_term_foreground_process_group();
history_destroy();
proc_destroy();

View file

@ -826,7 +826,7 @@ static void test_path()
{
err(L"Bug in canonical PATH code");
}
if (paths_are_equivalent(L"/foo/bar/baz", L"foo/bar/baz")) err(L"Bug in canonical PATH code on line %ld", (long)__LINE__);
if (! paths_are_equivalent(L"///foo///bar/baz", L"/foo/bar////baz//")) err(L"Bug in canonical PATH code on line %ld", (long)__LINE__);
if (! paths_are_equivalent(L"/foo/bar/baz", L"/foo/bar/baz")) err(L"Bug in canonical PATH code on line %ld", (long)__LINE__);

View file

@ -694,7 +694,7 @@ static void daemonize()
}
/*
Put ourself in out own processing group
Put ourself in our own process group
*/
setsid();

View file

@ -629,7 +629,7 @@ void history_t::get_string_representation(wcstring &result, const wcstring &sepa
scoped_lock locker(lock);
bool first = true;
std::set<wcstring> seen;
/* Append new items. Note that in principle we could use const_reverse_iterator, but we do not because reverse_iterator is not convertible to const_reverse_iterator ( http://github.com/fish-shell/fish-shell/issues/431 ) */
@ -638,7 +638,7 @@ void history_t::get_string_representation(wcstring &result, const wcstring &sepa
/* Skip duplicates */
if (! seen.insert(iter->str()).second)
continue;
if (! first)
result.append(separator);
result.append(iter->str());
@ -651,11 +651,11 @@ void history_t::get_string_representation(wcstring &result, const wcstring &sepa
{
size_t offset = *iter;
const history_item_t item = history_t::decode_item(mmap_start + offset, mmap_length - offset, mmap_type);
/* Skip duplicates */
if (! seen.insert(item.str()).second)
continue;
if (! first)
result.append(separator);
result.append(item.str());

View file

@ -419,7 +419,7 @@ static void job_or_process_extent(const wchar_t *buff,
break;
}
default:
{
break;

View file

@ -2011,7 +2011,7 @@ int parser_t::parse_job(process_t *p,
{
const wchar_t *cmd = args.at(0).completion.c_str();
/*
We couldn't find the specified command.
@ -2034,20 +2034,20 @@ int parser_t::parse_job(process_t *p,
if (equals_ptr != NULL)
{
/* Try to figure out if this is a pure variable assignment (foo=bar), or if this appears to be running a command (foo=bar ruby...) */
const wcstring name_str = wcstring(cmd, equals_ptr - cmd); //variable name, up to the =
const wcstring val_str = wcstring(equals_ptr + 1); //variable value, past the =
wcstring next_str;
if (tok_peek_next(tok, &next_str) == TOK_STRING && ! next_str.empty())
{
wcstring ellipsis_str = wcstring(1, ellipsis_char);
if (ellipsis_str == L"$")
ellipsis_str = L"...";
/* Looks like a command */
debug(0,
_( L"Unknown command '%ls'. Did you mean to run %ls with a modified environment? Try 'env %ls=%ls %ls%ls'. See the help section on the set command by typing 'help set'."),
_(L"Unknown command '%ls'. Did you mean to run %ls with a modified environment? Try 'env %ls=%ls %ls%ls'. See the help section on the set command by typing 'help set'."),
cmd,
next_str.c_str(),
name_str.c_str(),

View file

@ -400,7 +400,7 @@ void path_make_canonical(wcstring &path)
path.at(trailing++) = c;
}
prev_was_slash = is_slash;
}
}
assert(trailing <= len);
if (trailing < len)
path.resize(trailing);
@ -410,32 +410,32 @@ bool paths_are_equivalent(const wcstring &p1, const wcstring &p2)
{
if (p1 == p2)
return true;
size_t len1 = p1.size(), len2 = p2.size();
// Ignore trailing slashes after the first character
while (len1 > 1 && p1.at(len1 - 1) == L'/') len1--;
while (len2 > 1 && p2.at(len2 - 1) == L'/') len2--;
// Start walking
size_t idx1 = 0, idx2 = 0;
while (idx1 < len1 && idx2 < len2)
{
wchar_t c1 = p1.at(idx1), c2 = p2.at(idx2);
// If the characters are different, the strings are not equivalent
if (c1 != c2)
break;
idx1++;
idx2++;
// If the character was a slash, walk forwards until we hit the end of the string, or a non-slash
// Note the first condition is invariant within the loop
while (c1 == L'/' && idx1 < len1 && p1.at(idx1) == L'/') idx1++;
while (c2 == L'/' && idx2 < len2 && p2.at(idx2) == L'/') idx2++;
}
// We matched if we consumed all of the characters in both strings
return idx1 == len1 && idx2 == len2;
}

5
proc.h
View file

@ -373,7 +373,10 @@ public:
unsigned int flags;
/* Returns the block IO redirections associated with the job. These are things like the IO redirections associated with the begin...end statement. */
const io_chain_t &block_io_chain() const { return this->block_io; }
const io_chain_t &block_io_chain() const
{
return this->block_io;
}
/* Fetch all the IO redirections associated with the job */
io_chain_t all_io_redirections() const;

View file

@ -923,19 +923,27 @@ void reader_init()
// PCA disable VDSUSP (typically control-Y), which is a funny job control
// function available only on OS X and BSD systems
// This lets us use control-Y for yank instead
#ifdef VDSUSP
#ifdef VDSUSP
shell_modes.c_cc[VDSUSP] = _POSIX_VDISABLE;
#endif
#endif
#endif
}
void reader_destroy()
{
tcsetattr(0, TCSANOW, &terminal_mode_on_startup);
pthread_key_delete(generation_count_key);
}
void restore_term_mode()
{
// Restore the term mode if we own the terminal
// It's important we do this before restore_foreground_process_group, otherwise we won't think we own the terminal
if (getpid() == tcgetpgrp(STDIN_FILENO))
{
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_mode_on_startup);
}
}
void reader_exit(int do_exit, int forced)
{
@ -1654,7 +1662,7 @@ static const completion_t *cycle_competions(const std::vector<completion_t> &com
// note start_idx will be set to -1 initially, so that when it gets incremented we start at 0
const size_t start_idx = *inout_idx;
size_t idx = start_idx;
const completion_t *result = NULL;
size_t remaining = comp.size();
while (remaining--)
@ -2271,7 +2279,7 @@ static void handle_token_history(int forward, int reset)
}
}
break;
default:
{
break;
@ -3748,34 +3756,34 @@ const wchar_t *reader_readline(void)
}
break;
}
case R_UPCASE_WORD:
case R_DOWNCASE_WORD:
case R_CAPITALIZE_WORD:
{
// For capitalize_word, whether we've capitalized a character so far
bool capitalized_first = false;
// We apply the operation from the current location to the end of the word
size_t pos = data->buff_pos;
move_word(MOVE_DIR_RIGHT, false, move_word_style_punctuation, false);
for (; pos < data->buff_pos; pos++)
{
wchar_t chr = data->command_line.at(pos);
// We always change the case; this decides whether we go uppercase (true) or lowercase (false)
bool make_uppercase;
if (c == R_CAPITALIZE_WORD)
make_uppercase = ! capitalized_first && iswalnum(chr);
else
make_uppercase = (c == R_UPCASE_WORD);
// Apply the operation and then record what we did
if (make_uppercase)
chr = towupper(chr);
else
chr = towlower(chr);
data->command_line.at(pos) = chr;
capitalized_first = capitalized_first || make_uppercase;
}
@ -3784,7 +3792,7 @@ const wchar_t *reader_readline(void)
reader_repaint();
break;
}
/* Other, if a normal character, we add it to the command */
default:
{

View file

@ -46,6 +46,9 @@ void reader_init();
*/
void reader_destroy();
/** Restore the term mode at startup */
void restore_term_mode();
/**
Returns the filename of the file currently read
*/

View file

@ -137,14 +137,14 @@ static bool allow_soft_wrap(void)
size_t escape_code_length(const wchar_t *code)
{
assert(code != NULL);
/* The only escape codes we recognize start with \x1b */
if (code[0] != L'\x1b')
return 0;
size_t resulting_length = 0;
bool found = false;
if (cur_term != NULL)
{
/*
@ -158,12 +158,12 @@ size_t escape_code_length(const wchar_t *code)
set_foreground,
set_background,
};
for (size_t p=0; p < sizeof esc / sizeof *esc && !found; p++)
{
if (!esc[p])
continue;
for (size_t k=0; k<8; k++)
{
size_t len = try_sequence(tparm(esc[p],k), code);
@ -176,7 +176,7 @@ size_t escape_code_length(const wchar_t *code)
}
}
}
if (cur_term != NULL)
{
/*
@ -206,9 +206,9 @@ size_t escape_code_length(const wchar_t *code)
exit_standout_mode,
enter_secure_mode
};
for (size_t p=0; p < sizeof esc2 / sizeof *esc2 && !found; p++)
{
if (!esc2[p])
@ -226,7 +226,7 @@ size_t escape_code_length(const wchar_t *code)
}
}
}
if (!found)
{
if (code[1] == L'k')
@ -251,7 +251,7 @@ size_t escape_code_length(const wchar_t *code)
}
}
}
if (! found)
{
/* Generic VT100 one byte sequence: CSI followed by something in the range @ through _ */
@ -261,7 +261,7 @@ size_t escape_code_length(const wchar_t *code)
found = true;
}
}
if (! found)
{
/* Generic VT100 CSI-style sequence. <esc>, followed by zero or more ASCII characters NOT in the range [@,_], followed by one character in that range */
@ -273,11 +273,11 @@ size_t escape_code_length(const wchar_t *code)
{
/* Consume a sequence of ASCII characters not in the range [@, ~] */
wchar_t c = code[cursor];
/* If we're not in ASCII, just stop */
if (c > 127)
break;
/* If we're the end character, then consume it and then stop */
if (c >= L'@' && c <= L'~')
{
@ -290,7 +290,7 @@ size_t escape_code_length(const wchar_t *code)
resulting_length = cursor;
}
}
if (! found)
{
/* Generic VT100 two byte sequence: <esc> followed by something in the range @ through _ */
@ -300,7 +300,7 @@ size_t escape_code_length(const wchar_t *code)
found = true;
}
}
return resulting_length;
}
@ -1060,7 +1060,7 @@ struct screen_layout_t
wcstring autosuggestion;
/* Whether the prompts get their own line or not */
bool prompts_get_own_line;
bool prompts_get_own_line;
};
/* Given a vector whose indexes are offsets and whose values are the widths of the string if truncated at that offset, return the offset that fits in the given width. Returns width_by_offset.size() - 1 if they all fit. The first value in width_by_offset is assumed to be 0. */

View file

@ -140,7 +140,7 @@ public:
/** If we support soft wrapping, we can output to this location without any cursor motion. */
screen_data_t::cursor_t soft_wrap_location;
/** Whether the last-drawn autosuggestion (if any) is truncated, or hidden entirely */
bool autosuggestion_is_truncated;
@ -158,7 +158,7 @@ public:
/** If we need to clear, this is how many lines the actual screen had, before we reset it. This is used when resizing the window larger: if the cursor jumps to the line above, we need to remember to clear the subsequent lines. */
size_t actual_lines_before_reset;
/**
These status buffers are used to check if any output has occurred
other than from fish's main loop, in which case we need to redraw.

View file

@ -2,7 +2,7 @@ begin
set -l unicode 'commandline | sgrep -qe "-[a-zA-Z]*C[a-zA-Z]*\$"'
set -l noopt 'commandline | not sgrep -qe "-[a-zA-Z]*C[a-zA-Z]*\$"'
set -l modules "(find (perl -lE'print for @INC') -name '*.pm' -printf '%P\n' \
| awk '{ gsub(\"/\", \"::\") } !/-/' RS=.pm\n | sort | uniq)"
| awk '{ gsub(\"/\", \"::\") } /[^-.]/' RS=.pm\n | sort | uniq)"
complete -c perl -s 0 -n $noopt --description 'Specify record separator'
complete -c perl -s a -n $noopt --description 'Turn on autosplit mode'
complete -c perl -s c -n $noopt --description 'Check syntax'

View file

@ -51,6 +51,7 @@
# __fish_git_prompt_showupstream to a space-separated list of values:
#
# verbose show number of commits ahead/behind (+/-) upstream
# name if verbose, then also show the upstream abbrev name
# informative similar to verbose, but shows nothing when equal (fish only)
# legacy don't use the '--count' option available in recent versions
# of git-rev-list
@ -155,7 +156,8 @@
#
# The separator before the upstream information can be customized via
# __fish_git_prompt_char_upstream_prefix. It is colored like the rest of
# the upstream information. It defaults to nothing ().
# the upstream information. It normally defaults to nothing () and defaults
# to a space ( ) when __fish_git_prompt_showupstream contains verbose.
#
#
# Turning on __fish_git_prompt_showcolorhints changes the colors as follows to
@ -178,6 +180,7 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi
set -l upstream git
set -l legacy
set -l verbose
set -l name
# Default to informative if show_informative_status is set
if test -n "$__fish_git_prompt_show_informative_status"
@ -222,6 +225,8 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi
case legacy
set legacy 1
set -e informative
case name
set name 1
case none
return
end
@ -291,17 +296,27 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi
# calculate the result
if test -n "$verbose"
# Verbose has a space by default
set -l prefix "$___fish_git_prompt_char_upstream_prefix"
# Using two underscore version to check if user explicitly set to nothing
if not set -q __fish_git_prompt_char_upstream_prefix
set -l prefix " "
end
echo $count | read -l behind ahead
switch "$count"
case '' # no upstream
case "0 0" # equal to upstream
echo "$___fish_git_prompt_char_upstream_prefix$___fish_git_prompt_char_upstream_equal"
echo "$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"
echo "$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"
echo "$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"
echo "$prefix$___fish_git_prompt_char_upstream_diverged$ahead-$behind"
end
if test -n "$count" -a -n "$name"
echo " "(command git rev-parse --abbrev-ref "$upstream" ^/dev/null)
end
else if test -n "$informative"
echo $count | read -l behind ahead
@ -657,21 +672,12 @@ function __fish_git_prompt_set_color
set default_done "$argv[3]"
end
if test (count $user_variable) -eq 2
set user_variable_bright $user_variable[2]
set user_variable $user_variable[1]
end
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 --bold $user_variable)
else
set -g $variable (set_color $user_variable)
end
set -g $variable (set_color $user_variable)
set -g $variable_done (set_color normal)
else
set -g $variable $default

View file

@ -17,9 +17,18 @@ Redistributions in binary form must reproduce the above copyright notice, this l
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""
import string, sys, re, os.path, gzip, traceback, getopt, errno, codecs
import string, sys, re, os.path, bz2, gzip, traceback, getopt, errno, codecs
from deroff import Deroffer
lzma_available = True
try:
try:
import backports.lzma as lzma
except ImportError:
import lzma
except ImportError:
lzma_available = False
# Whether we're Python 3
IS_PY3 = sys.version_info[0] >= 3
@ -717,6 +726,16 @@ def parse_manpage_at_path(manpage_path, output_directory):
fd = gzip.open(manpage_path, 'r')
manpage = fd.read()
if IS_PY3: manpage = manpage.decode('latin-1')
elif manpage_path.endswith('.bz2'):
fd = bz2.BZ2File(manpage_path, 'r')
manpage = fd.read()
if IS_PY3: manpage = manpage.decode('latin-1')
elif manpage_path.endswith('.xz') or manpage_path.endswith('.lzma'):
if not lzma_available:
return
fd = lzma.LZMAFile(str(manpage_path), 'r')
manpage = fd.read()
if IS_PY3: manpage = manpage.decode('latin-1')
else:
if IS_PY3:
fd = open(manpage_path, 'r', encoding='latin-1')
@ -816,6 +835,15 @@ def parse_and_output_man_pages(paths, output_directory, show_progress):
last_progress_string_length = 0
if show_progress and not WRITE_TO_STDOUT:
print("Parsing man pages and writing completions to {0}".format(output_directory))
man_page_suffixes = set([os.path.splitext(m)[1][1:] for m in paths])
lzma_xz_occurs = "xz" in man_page_suffixes or "lzma" in man_page_suffixes
if lzma_xz_occurs and not lzma_available:
add_diagnostic('At least one man page is compressed with lzma or xz, but the "lzma" module is not available.'
' Any man page compressed with either will be skipped.',
NOT_VERBOSE)
flush_diagnostics(sys.stderr)
for manpage_path in paths:
index += 1

View file

@ -710,20 +710,20 @@ enum token_type tok_peek_next(tokenizer_t *tok, wcstring *out_next_string)
{
out_next_string->clear();
}
enum token_type result = TOK_END;
if (tok_has_next(tok))
{
int saved = tok_get_pos(tok);
tok_next(tok);
result = tok_last_type(tok);
if (out_next_string != NULL)
{
const wchar_t *last = tok_last(tok);
out_next_string->assign(last ? last : L"");
}
tok_set_pos(tok, saved);
}
return result;

View file

@ -317,7 +317,7 @@ static bool wildcard_complete_internal(const wcstring &orig,
if (wildcard_complete_internal(orig, str + i, wc+1, false, desc, desc_func, out, expand_flags, flags))
{
res = true;
/* #929: if the recursive call gives us a prefix match, just stop. This is sloppy - what we really want to do is say, once we've seen a match of a particular type, ignore all matches of that type further down the string, such that the wildcard produces the "minimal match." */
bool has_prefix_match = false;
const size_t after_count = out.size();

View file

@ -276,7 +276,10 @@ _xdg_mime_magic_parse_header(FILE *magic_file, XdgMimeMagicMatch *match)
buffer = _xdg_mime_magic_read_to_newline(magic_file, &end_of_file);
if (end_of_file)
{
free(buffer);
return XDG_MIME_MAGIC_EOF;
}
end_ptr = buffer;
while (*end_ptr != ']' && *end_ptr != '\000' && *end_ptr != '\n')