Merge branch 'master' into coverity_scan_master

This commit is contained in:
Aaron Gyes
2016-10-17 14:15:28 -07:00
57 changed files with 637 additions and 291 deletions

View File

@@ -1,25 +1,45 @@
# next-2.x
## Significant changes
- The clipboard integration has been revamped with explicit bindings. OS X clipboard support provided for out of the box in addition to X11. (#3061)
- Vi-style bindings no longer build upon the default emacs-style bindings, instead they share some definitions (#3068).
- Fish will now try to set the locale when it doesn't inherit one by reading system configuration (#277)
- A number followed by a caret is no longer treated as a redirection (#1873)
- The clipboard integration has been revamped with explicit bindings. The killring commands no longer copy from, or paste to, the X11 clipboard - use the new copy (`C-x`) and paste (`C-v`) bindings instead. The clipboard is now available on OS X as well as systems using X11 (e.g. Linux). (#3061)
- `history` uses subcommands (`history delete`) rather than options (`history --delete`) for its actions (#3367). You can no longer specify multiple actions via flags (e.g., `history --delete --save something`).
- New `history` options have been added, including `--max=n` to limit the number of history entries, `--show-time` option to show timestamps (#3175, #3244), and `--null` to null terminate history entries in the search output.
- `history search` is now case-insensitive by default (which also affects `history delete`) (#3236).
- `history delete` now correctly handles multiline commands (#31).
- Vi-style bindings no longer include all of the default emacs-style bindings; instead, they share some definitions (#3068).
- If there is no locale set in the environment, various known system configuration files will be checked for a default, otherwise forcing en_US-UTF.8 (#277).
- A number followed by a caret (e.g. `5^`) is no longer treated as a redirection (#1873).
- The `$version` special variable can be overwritten, so that it can be used for other purposes if required.
## Notable fixes and improvements
- Completions that don't match the prefix will no longer expand to a common prefix (#3090)
- Suggestions will be offered more often, like after removing characters (#3069)
- The argument handling for the `history` function has been revamped (#3293, #3224, #3220, #3182)
- Improved argument handling for the `abbr` function (#2997, #3267)
- `history --merge` now correctly interleaves items in chronological order (#2312)
- `history` gained a new "--with-time" ("-t") option to show timestamps (#3175)
- The "-d" option to `fish_indent` was removed (#3191)
- A bug where fish would sometimes hang using 100% CPU in the C locale (#3214)
- Fish now uses the $TZ variable for its idea of localtime (#3181)
- Some performance improvments to the git prompt (#3294, 3083)
- Working completion after an escaped space character (#2447)
- Less output to fish's build (#3248)
- Some additions or fixes to the completions for `brew` (#3309), `git` (#3274, #3226, #3225, #3094, #3087, #3035, #3021, #2982, #3230), `aura` (#3297)
- New completions for perforce ("p4") (#3314)
- The `fish_realpath` builtin has been renamed to `realpath` and made compatible with GNU `realpath` when run without arguments (#3400). It is used only for systems without a `realpath` or `grealpath` utility (#3374).
- `fish_indent` can now read from named files, rather than just standard input (#3037).
- Fuzzy tab completions behave in a less surprising manner (#3090, #3211).
- `jobs` should only print its header line once (#3127).
- Improved color handling on terminals with limited colors (#3176, #3260).
- Wildcards in redirections are highlighted appropriately (#2789).
- Suggestions will be offered more often, like after removing characters (#3069).
- `history --merge` now correctly interleaves items in chronological order (#2312).
- Options for `fish_indent` have been aligned with the other binaries - in particular, `-d` now means `--debug`. The `--dump` option has been renamed to `--dump-parse-tree` (#3191).
- The display of bindings in the Web-based configuration has been greatly improved (#3325), as has the rendering of prompts (#2924).
- fish should no longer hang using 100% CPU in the C locale (#3214).
- A bug in FreeBSD 11 & 12, Dragonfly BSD & illumos prevented fish from working correctly on these platforms under UTF-8 locales; fish now avoids the buggy behaviour (#3050).
- Prompts which show git repository information (via `__fish_git_prompt`) are faster in large repositories (#3294) and slow filesystems (#3083).
- fish 2.3.0 reintroduced a problem where the greeting was printed even when using `read`; this has been corrected again (#3261).
- Vi mode changes the cursor depending on the current mode (#3215).
- Command lines with escaped space characters at the end tab-complete correctly (#2447).
- Added completions for:
- `arcanist` (#3256)
- `connmanctl` (#3419)
- `figlet` (#3378)
- `mdbook` (#3378)
- `ninja` (#3415)
- `p4`, the Perforce client (#3314)
- `pygmentize` (#3378)
- `ranger` (#3378)
- Improved completions for `aura` (#3297), `abbr` (#3267), `brew` (#3309), `chown` (#3380, #3383),`cygport` (#3392), `git` (#3274, #3226, #3225, #3094, #3087, #3035, #3021, #2982, #3230), `kill & `pkill` (#3200) `screen` (#3271), and `xz` (#3378).
- Distributors, packagers and developers will notice that the build process produces more succinct output by default; use `make V=1` to get verbose output (#3248).
- Improved compatibility with minor platforms including musl (#2988), Cygwin (#2993), Android (#3441, #3442), Haiku (#3322) and Solaris .
---

View File

@@ -85,11 +85,10 @@ fi
# Set up various programs needed for install
# Note AC_PROG_CXX sets CXXFLAGS if not set, which we want
# So ensure this happens before we modify CXXFLAGS below
# Do CC also, because PCRE2 will use it. Prefer clang++,
# targets like FreeBSD ship an ancient one.
AC_PROG_CC([clang llvm-gcc gcc cc])
# Do CC also, because PCRE2 will use it.
AC_PROG_CC
AC_PROG_CC_STDC # c99
AC_PROG_CXX([clang++ llvm-g++ g++ c++])
AC_PROG_CXX
AC_LANG(C++)
AC_PROG_INSTALL
AC_PROG_LN_S
@@ -285,6 +284,7 @@ AC_DEFINE_UNQUOTED([WCHAR_T_BITS], [$WCHAR_T_BITS], [The size of wchar_t in bits
#
# Detect nanoseconds fields in struct stat
#
AC_CHECK_MEMBERS([struct stat.st_ctime_nsec])
AC_CHECK_MEMBERS([struct stat.st_mtimespec.tv_nsec])
AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec])
@@ -302,6 +302,7 @@ AC_CHECK_FUNCS( futimes )
AC_CHECK_FUNCS( wcslcpy lrand48_r killpg )
AC_CHECK_FUNCS( backtrace_symbols getifaddrs )
AC_CHECK_FUNCS( futimens clock_gettime )
AC_CHECK_FUNCS( getpwent )
AC_CHECK_DECL( [mkostemp], [ AC_CHECK_FUNCS([mkostemp]) ] )

View File

@@ -2,10 +2,10 @@
\subsection abbr-synopsis Synopsis
\fish{synopsis}
abbr -a word phrase...
abbr -s
abbr -l
abbr -e word
abbr --add word phrase...
abbr --show
abbr --list
abbr --erase word
\endfish
\subsection abbr-description Description
@@ -14,11 +14,24 @@ abbr -e word
Abbreviations are user-defined character sequences or words that are replaced with longer phrases after they are entered. For example, a frequently-run command such as `git checkout` can be abbreviated to `gco`. After entering `gco` and pressing @key{Space} or @key{Enter}, the full text `git checkout` will appear in the command line.
Abbreviations are stored using universal variables. You can create abbreviations directly on the command line, and they will be saved automatically. Calling `abbr -a` in config.fish will lead to slightly worse startup performance.
Abbreviations are stored in a variable named `fish_user_abbreviations`. This is automatically created as a universal variable the first time an abbreviation is created. If you want your abbreviations to be private to a particular fish session you can put the following in your *~/.config/fish/config.fish* file before you define your first abbrevation:
\fish
if status --is-interactive
set -g fish_user_abbreviations
abbr --add first 'echo my first abbreviation'
abbr --add second 'echo my second abbreviation'
# etcetera
end
\endfish
You can create abbreviations directly on the command line and they will be saved automatically and made visible to other fish sessions if `fish_user_abbreviations` is a universal variable. If you keep the variable as universal, `abbr --add` statements in <a href="tutorial.html#tut_startup">config.fish</a> will do nothing but slow down startup slightly.
\subsection abbr-options Options
The following parameters are available:
- `-a WORD PHRASE` or `--add WORD PHRASE` Adds a new abbreviation, where WORD will be expanded to PHRASE.
- `-a WORD PHRASE` or `--add WORD PHRASE` Adds a new abbreviation, causing WORD to be expanded to PHRASE.
- `-s` or `--show` Show all abbreviated words and their expanded phrases in a manner suitable for export and import.

View File

@@ -131,7 +131,7 @@ The following special input functions are available:
\subsection bind-example Examples
\fish
bind \\cd 'exit'
bind <asis>\\cd</asis> 'exit'
\endfish
Causes `fish` to exit when @key{Control,D} is pressed.

View File

@@ -2,8 +2,8 @@
\subsection history-synopsis Synopsis
\fish{synopsis}
history search [ --show-time ] [ --exact | --prefix | --contains ] [ --max=n ] [ "search string"... ]
history delete [ --show-time ] [ --exact | --prefix | --contains ] "search string"...
history search [ --show-time ] [ --case-sensitive ] [ --exact | --prefix | --contains ] [ --max=n ] [ --null ] [ "search string"... ]
history delete [ --show-time ] [ --case-sensitive ] [ --exact | --prefix | --contains ] "search string"...
history merge
history save
history clear
@@ -20,7 +20,7 @@ The following operations (sub-commands) are available:
- `search` returns history items matching the search string. If no search string is provided it returns all history items. This is the default operation if no other operation is specified. You only have to explicitly say `history search` if you wish to search for one of the subcommands. The `--contains` search option will be used if you don't specify a different search option. Entries are ordered newest to oldest. If stdout is attached to a tty the output will be piped through your pager by the history function. The history builtin simply writes the results to stdout.
- `delete` deletes history items. Without the `--prefix` or `--contains` options, the exact match will be deleted. With either of these options, a prompt will be displayed before any items are deleted asking you which entries are to be deleted. You can enter the word "all" to delete all matching entries. You can enter a single ID (the number in square brackets) to delete just that single entry. You can enter more than one ID separated by a space to delete multiple entries. Just press [enter] to not delete anything. Note that the interactive delete behavior is a feature of the history function. The history builtin only supports bulk deletion.
- `delete` deletes history items. Without the `--prefix` or `--contains` options, the exact match of the specified text will be deleted. If you don't specify `--exact` a prompt will be displayed before any items are deleted asking you which entries are to be deleted. You can enter the word "all" to delete all matching entries. You can enter a single ID (the number in square brackets) to delete just that single entry. You can enter more than one ID separated by a space to delete multiple entries. Just press [enter] to not delete anything. Note that the interactive delete behavior is a feature of the history function. The history builtin only supports `--exact --case-sensitive` deletion.
- `merge` immediately incorporates history changes from other sessions. Ordinarily `fish` ignores history changes from sessions started after the current one. This command applies those changes immediately.
@@ -32,14 +32,18 @@ The following options are available:
These flags can appear before or immediately after one of the sub-commands listed above.
- `-C` or `--case-sensitive` does a case-sensitive search. The default is case-insensitive. Note that prior to fish 2.4.0 the default was case-sensitive.
- `-c` or `--contains` searches or deletes items in the history that contain the specified text string. This is the default for the `--search` flag. This is not currently supported by the `--delete` flag.
- `-e` or `--exact` searches or deletes items in the history that exactly match the specified text string. This is the default for the `--delete` flag.
- `-e` or `--exact` searches or deletes items in the history that exactly match the specified text string. This is the default for the `--delete` flag. Note that the match is case-insensitive by default. If you really want an exact match, including letter case, you must use the `-C` or `--case-sensitive` flag.
- `-p` or `--prefix` searches or deletes items in the history that begin with the specified text string. This is not currently supported by the `--delete` flag.
- `-t` or `--show-time` prepends each history entry with the date and time the entry was recorded . By default it uses the strftime format `# %c%n`. You can specify another format; e.g., `--show-time='%Y-%m-%d %H:%M:%S '` or `--show-time='%a%I%p'`. The short option, `-t` doesn't accept a stftime format string; it only uses the default format. Any strftime format is allowed, including `%s` to get the raw UNIX seconds since the epoch. Note that `--with-time` is also allowed but is deprecated and will be removed at a future date.
- `-z` or `--null` causes history entries written by the search operations to be terminated by a NUL character rather than a newline. This allows the output to be processed by `read -z` to correctly handle multiline history entries.
- `-<number>` `-n <number>` or `--max=<number>` limits the matched history items to the first "n" matching entries. This is only valid for `history search`.
- `-h` or `--help` display help for this command.

View File

@@ -506,7 +506,7 @@ A dollar sign followed by a string of characters is expanded into the value of t
Undefined and empty variables expand to nothing.
To separate a variable name from text it should immediately be followed by, encase the variable within quotes.
To separate a variable name from text encase the variable within double-quotes or braces.
Examples:
\fish
@@ -813,7 +813,7 @@ The user can change the settings of `fish` by changing the values of certain var
- `BROWSER`, the user's preferred web browser. If this variable is set, fish will use the specified browser instead of the system default browser to display the fish documentation.
- `CDPATH`, an array of directories in which to search for the new directory for the `cd` builtin. By default, the fish configuration defines `CDPATH` to be a universal variable with the values `.` and `~`.
- `CDPATH`, an array of directories in which to search for the new directory for the `cd` builtin.
- `LANG`, `LC_ALL`, `LC_COLLATE`, `LC_CTYPE`, `LC_MESSAGES`, `LC_MONETARY`, `LC_NUMERIC` and `LC_TIME` set the language option for the shell and subprograms. See the section <a href='#variables-locale'>Locale variables</a> for more information.
@@ -1105,7 +1105,7 @@ History searches can be aborted by pressing the escape key.
Prefixing the commandline with a space will prevent the entire line from being stored in the history.
The history is stored in the file `~/.config/fish/fish_history`.
The history is stored in the file `~/.local/share/fish/fish_history` (or `$XDG_DATA_HOME/fish/fish_history` if that variable is set).
Examples:
@@ -1170,7 +1170,7 @@ If you want to add the directory `~/linux/bin` to your PATH variable when using
\fish
if status --is-login
set PATH $PATH ~/linux/bin
set -x PATH $PATH ~/linux/bin
end
\endfish

View File

@@ -42,7 +42,7 @@ The following subcommands are available:
- `trim` removes leading and trailing whitespace from each STRING. If `-l` or `--left` is given, only leading whitespace is removed. If `-r` or `--right` is given, only trailing whitespace is trimmed. The `-c` or `--chars` switch causes the characters in CHARS to be removed instead of whitespace. Exit status: 0 if at least one character was trimmed, or 1 otherwise.
- `escape` escapes each STRING such that it can be passed back to `eval` to produce the original argument again. By default, all special characters are escaped, and quotes are used to simplify the output when possible. If `-n` or `--no-quote` is given, the simplifying quoted format is not used. Exit status: 0 if at least one string was escaped, or 1 otherwise.
- `escape` escapes each STRING such that it can be passed back to `eval` to produce the original argument again. By default, all special characters are escaped, and quotes are used to simplify the output when possible. If `-n` or `--no-quoted` is given, the simplifying quoted format is not used. Exit status: 0 if at least one string was escaped, or 1 otherwise.
- `match` tests each STRING against PATTERN and prints matching substrings. Only the first match for each STRING is reported unless `-a` or `--all` is given, in which case all matches are reported. Matching can be made case-insensitive with `-i` or `--ignore-case`. If `-n` or `--index` is given, each match is reported as a 1-based start position and a length. By default, PATTERN is interpreted as a glob pattern matched against each entire STRING argument. A glob pattern is only considered a valid match if it matches the entire STRING. If `-r` or `--regex` is given, PATTERN is interpreted as a Perl-compatible regular expression, which does not have to match the entire STRING. For a regular expression containing capturing groups, multiple items will be reported for each match, one for the entire match and one for each capturing group. If --invert or -v is used the selected lines will be only those which do not match the given glob pattern or regular expression. Exit status: 0 if at least one match was found, or 1 otherwise.

View File

@@ -29,6 +29,9 @@
/* Define to 1 if you have the <getopt.h> header file. */
#define HAVE_GETOPT_H 1
/* Define to 1 if you have the `getpwent' function. */
#define HAVE_GETPWENT 1
/* Define to 1 if you have the `gettext' function. */
/* #undef HAVE_GETTEXT */
@@ -86,6 +89,9 @@
/* Define to 1 if `d_type' is a member of `struct dirent'. */
#define HAVE_STRUCT_DIRENT_D_TYPE 1
/* Define to 1 if `st_ctime_nsec' is a member of `struct stat'. */
/* #undef HAVE_STRUCT_STAT_ST_CTIME_NSEC */
/* Define to 1 if `st_mtimespec.tv_nsec' is a member of `struct stat'. */
#define HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC 1

View File

@@ -0,0 +1,49 @@
function __fish_print_connman_services
# connmanctl services follows this pattern (to be interpreted as a regex):
# "[\* ][A ][ORacd ] service_name +identification_string"
# where [\* ] indicates whether a service is a favorite
# [A ] indicates whether a service is in autoconnect mode
# [ORacd ] indicates the current status of the service: online, ready, association, configuration, disconnect or idle
connmanctl services | string replace -r '.{4}(.*) +(.*)' '$2\t$1'
end
function __fish_print_connman_technologies
connmanctl technologies | string match '*Type*' | string replace -r ' Type = (.*)' '$1'
end
function __fish_print_connman_vpnconnections
# formatting of the vpn connections:
# " [RCF ] service_name +identification_string"
# where [RCF ] indicates the current status which can be: ready, configuration, failure or idle
connmanctl vpnconnections | string replace -r '.{4}(.*) +(.*)' '$2\t$1'
end
# connmanctl does not accept options before commands, so requiring the commands to be in second position is okay
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "state" -d "Shows if the system is online or offline"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "technologies" -d "Display technologies"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "clock" -d "Get System Clock Properties"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "enable" -d "Enables given technology or offline mode"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] enable" -a "(__fish_print_connman_technologies) offline"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "disable" -d "Disables given technology or offline mode"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] disable" -a "(__fish_print_connman_technologies) offline"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "tether" -d "Enable, disable tethering, set SSID and passphrase for wifi"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] tether" -a "(__fish_print_connman_technologies)"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 3; and contains -- (commandline -opc)[2] tether" -a "on off"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "services" -d "Display services"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] services" -a "(__fish_print_connman_services)"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "peers" -d "Display peers"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "scan" -d "Scans for new services for given technology"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] scan" -a "(__fish_print_connman_technologies)"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "connect" -d "Connect a given service or peer"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] connect" -a "(__fish_print_connman_services)"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "disconnect" -d "Disconnect a given service or peer"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] disconnect" -a "(__fish_print_connman_services)"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "config" -d "Set service configuration options"
complete -f -c connmanctl -n "test (count (commandline -opc)) -ge 2; and contains -- (commandline -opc)[2] config" -a "(__fish_print_connman_services)"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "monitor" -d "Monitor signals from interfaces"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "vpnconnections" -d "Display VPN connections"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] vpnconnections" -a "(__fish_print_connman_vpnconnections)"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "session" -d "Enable or disable a session"
complete -f -c connmanctl -n "test (count (commandline -opc)) -eq 2; and contains -- (commandline -opc)[2] session" -a "on off connect disconnect config"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "peer_service" -d "(Un)Register a Peer Service"
complete -f -c connmanctl -n "test (count (commandline -opc)) -lt 2" -a "help" -d "Show help"

View File

@@ -77,6 +77,26 @@ complete -c wget -l post-data --description "Use POST as the method for all HTTP
complete -c wget -l post-file --description "Use POST as the method for all HTTP requests and send the specified data in the request body" -r
complete -c wget -l no-http-keep-alive --description "Turn off keep-alive for http downloads"
# HTTPS options
complete -c wget -f -r -l secure-protocol -a 'auto SSLv2 SSLv3 TLSv1 PFS' --description "Choose secure protocol"
complete -c wget -f -l https-only --description "Only follow secure HTTPS links"
complete -c wget -f -l no-check-certificate --description "Don't validate the server's certificate"
complete -c wget -r -l certificate --description "Client certificate file"
complete -c wget -f -r -l certificate-type --arguments 'PEM DER' --description "Client certificate type"
complete -c wget -r -l private-key --description "Private key file"
complete -c wget -f -r -l private-key-type --arguments 'PEM DER' --description "Private key type"
complete -c wget -r -l ca-certificate --description "File with the bundle of CAs"
complete -c wget -r -l ca-directory --description "Directory where hash list of CAs is stored"
complete -c wget -r -l crl-file --description "File with bundle of CRLs"
complete -c wget -r -l random-file --description "File with random data for seeding the SSL PRNG"
complete -c wget -r -l egd-file --description "File naming the EGD socket with random data"
# HSTS options
complete -c wget -f -l no-hsts --description "Disable HSTS"
complete -c wget -l hsts-file --description "Path of HSTS database"
#FTP options
complete -c wget -l no-remove-listing --description "Don't remove the temporary .listing files generated"

View File

@@ -1,4 +1,4 @@
function fish_update_completions --description "Update man-page based completions"
# Clean up old paths
eval (string escape $__fish_datadir/tools/create_manpage_completions.py) --manpath --progress --cleanup-in '~/.config/fish/completions' --cleanup-in '~/.config/fish/generated_completions'
python -B $__fish_datadir/tools/create_manpage_completions.py --manpath --progress --cleanup-in '~/.config/fish/completions' --cleanup-in '~/.config/fish/generated_completions'
end

View File

@@ -22,7 +22,7 @@ function __fish_unexpected_hist_args --no-scope-shadowing
return 0
end
if set -q argv[1]
printf (_ "%ls: %ls command expected %d args, got %d\n") $cmd $hist_cmd 0 (count $argv) >&2
printf (_ "%ls: %ls expected %d args, got %d\n") $cmd $hist_cmd 0 (count $argv) >&2
return 0
end
return 1
@@ -35,6 +35,8 @@ function history --description "display or manipulate interactive command histor
set -l search_mode
set -l show_time
set -l max_count
set -l case_sensitive
set -l null
# Check for a recognized subcommand as the first argument.
if set -q argv[1]
@@ -68,6 +70,8 @@ function history --description "display or manipulate interactive command histor
case --merge
__fish_set_hist_cmd merge
or return
case -C --case_sensitive
set case_sensitive --case-sensitive
case -h --help
builtin history --help
return
@@ -79,6 +83,8 @@ function history --description "display or manipulate interactive command histor
set search_mode --contains
case -e --exact
set search_mode --exact
case -z --null
set null --null
case -n --max
if string match -- '-n?*' $argv[1]
or string match -- '--max=*' $argv[1]
@@ -121,14 +127,13 @@ function history --description "display or manipulate interactive command histor
test -z "$search_mode"
and set search_mode "--contains"
echo "builtin history search $search_mode $show_time $max_count -- $argv" >>/tmp/x
if isatty stdout
set -l pager less
set -q PAGER
and set pager $PAGER
builtin history search $search_mode $show_time $max_count -- $argv | eval $pager
builtin history search $search_mode $show_time $max_count $case_sensitive $null -- $argv | eval $pager
else
builtin history search $search_mode $show_time $max_count -- $argv
builtin history search $search_mode $show_time $max_count $case_sensitive $null -- $argv
end
case delete # interactively delete history
@@ -139,16 +144,19 @@ function history --description "display or manipulate interactive command histor
end
test -z "$search_mode"
and set search_mode "--exact"
and set search_mode "--contains"
if test $search_mode = "--exact"
builtin history delete $search_mode $argv
builtin history delete $search_mode $case_sensitive $argv
return
end
# TODO: Fix this so that requesting history entries with a timestamp works:
# set -l found_items (builtin history search $search_mode $show_time -- $argv)
set -l found_items (builtin history search $search_mode -- $argv)
set -l found_items
builtin history search $search_mode $case_sensitive --null -- $argv | while read -lz x
set found_items $found_items $x
end
if set -q found_items[1]
set -l found_items_count (count $found_items)
for i in (seq $found_items_count)
@@ -169,7 +177,9 @@ function history --description "display or manipulate interactive command histor
if test "$choice" = "all"
printf "Deleting all matching entries!\n"
builtin history delete $search_mode -- $argv
for item in $found_items
builtin history delete --exact --case-sensitive -- $item
end
builtin history save
return
end
@@ -183,7 +193,7 @@ function history --description "display or manipulate interactive command histor
end
printf "Deleting history entry %s: \"%s\"\n" $i $found_items[$i]
builtin history delete "$found_items[$i]"
builtin history delete --exact --case-sensitive -- "$found_items[$i]"
end
builtin history save
end

View File

@@ -115,7 +115,7 @@ def lossy_unicode(s):
except UnicodeEncodeError:
pass
return s.decode('latin-1', 'ignore')
def output_complete_command(cmdname, args, description, output_list):
comps = ['complete -c', cmdname]
@@ -163,31 +163,31 @@ def built_command(options, description):
else:
ELLIPSIS_CODE_POINT = 0x2026
truncation_suffix = unichr(ELLIPSIS_CODE_POINT)
# Try to include as many whole sentences as will fit
# Clean up some probably bogus escapes in the process
clean_desc = description.replace("\\'", "'").replace("\\.", ".")
sentences = clean_desc.split('.')
# Clean up "sentences" that are just whitespace
# But don't let it be empty
sentences = [x for x in sentences if x.strip()]
if not sentences: sentences = ['']
udot = lossy_unicode('.')
uspace = lossy_unicode(' ')
truncated_description = lossy_unicode(sentences[0]) + udot
uspace = lossy_unicode(' ')
truncated_description = lossy_unicode(sentences[0]) + udot
for line in sentences[1:]:
if not line: continue
proposed_description = lossy_unicode(truncated_description) + uspace + lossy_unicode(line) + udot
proposed_description = lossy_unicode(truncated_description) + uspace + lossy_unicode(line) + udot
if len(proposed_description) <= max_description_width:
# It fits
truncated_description = proposed_description
else:
# No fit
break
# If the first sentence does not fit, truncate if necessary
if len(truncated_description) > max_description_width:
prefix_len = max_description_width - len(truncation_suffix)
@@ -504,7 +504,7 @@ class TypeDarwinManParser(ManParser):
# Skip leading groff crud
while re.match('[A-Z][a-z]\s', line):
line = line[3:]
# If the line ends with a space and then a period or comma, then erase the space
# This hack handles lines of the form '.Ar projectname .'
if line.endswith(' ,') or line.endswith(' .'):
@@ -551,10 +551,10 @@ class TypeDarwinManParser(ManParser):
# Get the line and clean it up
line = lines.pop(0)
# Try to guess how many dashes this argument has
dash_count = self.count_argument_dashes(line)
line = self.groff_replace_escapes(line)
line = self.trim_groff(line)
line = line.strip()
@@ -661,7 +661,7 @@ def file_is_overwritable(path):
file.close()
return result
# Remove any and all autogenerated completions in the given directory
def cleanup_autogenerated_completions_in_directory(dir):
try:
@@ -895,7 +895,7 @@ if __name__ == "__main__":
print(err.msg) # will print something like "option -a not recognized"
usage(script_name)
sys.exit(2)
# Directories within which we will clean up autogenerated completions
# This script originally wrote completions into ~/.config/fish/completions
# Now it writes them into a separate directory
@@ -935,7 +935,7 @@ if __name__ == "__main__":
if not file_paths:
print("No paths specified")
sys.exit(0)
if not WRITE_TO_STDOUT and not output_directory:
# Default to ~/.local/share/fish/generated_completions/
# Create it if it doesn't exist

View File

@@ -3,7 +3,6 @@
""" Deroff.py, ported to Python from the venerable deroff.c """
import sys, re, string
IS_PY3 = sys.version_info[0] >= 3

View File

@@ -82,7 +82,7 @@ class autoload_t : private lru_cache_t<autoload_function_t> {
protected:
/// Overridable callback for when a command is removed.
virtual void command_removed(const wcstring &cmd) {}
virtual void command_removed(const wcstring &cmd) { UNUSED(cmd); }
public:
/// Create an autoload_t for the given environment variable name.

View File

@@ -123,6 +123,7 @@ static int count_char(const wchar_t *str, wchar_t c) {
/// A wcstring with a formatted manpage.
///
wcstring builtin_help_get(parser_t &parser, io_streams_t &streams, const wchar_t *name) {
UNUSED(parser);
// This won't ever work if no_exec is set.
if (no_exec) return wcstring();
@@ -1294,6 +1295,7 @@ static bool builtin_echo_parse_numeric_sequence(const wchar_t *str, size_t *cons
/// Bash only respects -n if it's the first argument. We'll do the same. We also support a new
/// option -s to mean "no spaces"
static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
UNUSED(parser);
// Skip first arg
if (!*argv++) return STATUS_BUILTIN_ERROR;
@@ -1446,6 +1448,12 @@ static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv)
/// The pwd builtin. We don't respect -P to resolve symbolic links because we
/// try to always resolve them.
static int builtin_pwd(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
UNUSED(parser);
if (argv[1] != NULL) {
streams.err.append_format(BUILTIN_ERR_ARG_COUNT1, argv[0], 0, builtin_count_args(argv));
return STATUS_BUILTIN_ERROR;
}
wcstring res = wgetcwd();
if (res.empty()) {
return STATUS_BUILTIN_ERROR;
@@ -2001,7 +2009,7 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
line = reader_readline(nchars);
proc_pop_interactive();
if (line) {
if (0 < nchars && nchars < wcslen(line)) {
if (0 < nchars && (size_t)nchars < wcslen(line)) {
// Line may be longer than nchars if a keybinding used `commandline -i`
// note: we're deliberately throwing away the tail of the commandline.
// It shouldn't be unread because it was produced with `commandline -i`,
@@ -2402,6 +2410,7 @@ static int builtin_cd(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
/// Implementation of the builtin count command, used to count the number of arguments sent to it.
static int builtin_count(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
UNUSED(parser);
int argc;
argc = builtin_count_args(argv);
streams.out.append_format(L"%d\n", argc - 1);
@@ -2726,6 +2735,11 @@ static int builtin_break_continue(parser_t &parser, io_streams_t &streams, wchar
/// Implementation of the builtin breakpoint command, used to launch the interactive debugger.
static int builtin_breakpoint(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
if (argv[1] != NULL) {
streams.err.append_format(BUILTIN_ERR_ARG_COUNT1, argv[0], 0, builtin_count_args(argv));
return STATUS_BUILTIN_ERROR;
}
parser.push_block(new breakpoint_block_t());
reader_read(STDIN_FILENO, streams.io_chain ? *streams.io_chain : io_chain_t());
@@ -2839,14 +2853,14 @@ static bool set_hist_cmd(wchar_t *const cmd, hist_cmd_t *hist_cmd, hist_cmd_t su
}
#define CHECK_FOR_UNEXPECTED_HIST_ARGS(hist_cmd) \
if (history_search_type_defined || show_time_format) { \
if (history_search_type_defined || show_time_format || null_terminate) { \
streams.err.append_format(_(L"%ls: you cannot use any options with the %ls command\n"), \
cmd, hist_cmd_to_string(hist_cmd).c_str()); \
status = STATUS_BUILTIN_ERROR; \
break; \
} \
if (args.size() != 0) { \
streams.err.append_format(BUILTIN_ERR_ARG_COUNT, cmd, \
streams.err.append_format(BUILTIN_ERR_ARG_COUNT2, cmd, \
hist_cmd_to_string(hist_cmd).c_str(), 0, args.size()); \
status = STATUS_BUILTIN_ERROR; \
break; \
@@ -2861,10 +2875,12 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
long max_items = LONG_MAX;
bool history_search_type_defined = false;
const wchar_t *show_time_format = NULL;
bool case_sensitive = false;
bool null_terminate = false;
// TODO: Remove the long options that correspond to subcommands (e.g., '--delete') on or after
// 2017-10 (which will be a full year after these flags have been deprecated).
const wchar_t *short_options = L":mn:epcht";
const wchar_t *short_options = L":Cmn:epchtz";
const struct woption long_options[] = {{L"prefix", no_argument, NULL, 'p'},
{L"contains", no_argument, NULL, 'c'},
{L"help", no_argument, NULL, 'h'},
@@ -2872,6 +2888,8 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
{L"with-time", optional_argument, NULL, 't'},
{L"exact", no_argument, NULL, 'e'},
{L"max", required_argument, NULL, 'n'},
{L"null", no_argument, 0, 'z'},
{L"case-sensitive", no_argument, 0, 'C'},
{L"delete", no_argument, NULL, 1},
{L"search", no_argument, NULL, 2},
{L"save", no_argument, NULL, 3},
@@ -2918,6 +2936,10 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
}
break;
}
case 'C': {
case_sensitive = true;
break;
}
case 'p': {
search_type = HISTORY_SEARCH_TYPE_PREFIX;
history_search_type_defined = true;
@@ -2947,6 +2969,10 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
}
break;
}
case 'z': {
null_terminate = true;
break;
}
case 'h': {
builtin_print_help(parser, streams, cmd, streams.out);
return STATUS_BUILTIN_OK;
@@ -3000,20 +3026,27 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
int status = STATUS_BUILTIN_OK;
switch (hist_cmd) {
case HIST_SEARCH: {
if (!history->search(search_type, args, show_time_format, max_items, streams)) {
if (!history->search(search_type, args, show_time_format, max_items, case_sensitive,
null_terminate, streams)) {
status = STATUS_BUILTIN_ERROR;
}
break;
}
case HIST_DELETE: {
// TODO: Move this code to the history module and support the other search types. At
// this time we expect the non-exact deletions to be handled only by the history
// function's interactive delete feature.
// TODO: Move this code to the history module and support the other search types
// including case-insensitive matches. At this time we expect the non-exact deletions to
// be handled only by the history function's interactive delete feature.
if (search_type != HISTORY_SEARCH_TYPE_EXACT) {
streams.err.append_format(_(L"builtin history delete only supports --exact\n"));
status = STATUS_BUILTIN_ERROR;
break;
}
if (!case_sensitive) {
streams.err.append_format(
_(L"builtin history delete only supports --case-sensitive\n"));
status = STATUS_BUILTIN_ERROR;
break;
}
for (wcstring_list_t::const_iterator iter = args.begin(); iter != args.end(); ++iter) {
wcstring delete_string = *iter;
if (delete_string[0] == '"' && delete_string[delete_string.length() - 1] == '"') {
@@ -3094,10 +3127,22 @@ int builtin_parse(parser_t &parser, io_streams_t &streams, wchar_t **argv)
#endif
int builtin_true(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
UNUSED(parser);
UNUSED(streams);
if (argv[1] != NULL) {
streams.err.append_format(BUILTIN_ERR_ARG_COUNT1, argv[0], 0, builtin_count_args(argv));
return STATUS_BUILTIN_ERROR;
}
return STATUS_BUILTIN_OK;
}
int builtin_false(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
UNUSED(parser);
UNUSED(streams);
if (argv[1] != NULL) {
streams.err.append_format(BUILTIN_ERR_ARG_COUNT1, argv[0], 0, builtin_count_args(argv));
return STATUS_BUILTIN_ERROR;
}
return STATUS_BUILTIN_ERROR;
}

View File

@@ -53,7 +53,8 @@ enum { COMMAND_NOT_BUILTIN, BUILTIN_REGULAR, BUILTIN_FUNCTION };
#define BUILTIN_ERR_UNKNOWN _(L"%ls: Unknown option '%ls'\n")
/// Error message for unexpected args.
#define BUILTIN_ERR_ARG_COUNT _(L"%ls: %ls command expected %d args, got %d\n")
#define BUILTIN_ERR_ARG_COUNT1 _(L"%ls: expected %d args, got %d\n")
#define BUILTIN_ERR_ARG_COUNT2 _(L"%ls: %ls expected %d args, got %d\n")
/// Error message for invalid character in variable name.
#define BUILTIN_ERR_VARCHAR \

View File

@@ -695,6 +695,7 @@ int builtin_printf_state_t::print_formatted(const wchar_t *format, int argc, wch
/// The printf builtin.
int builtin_printf(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
UNUSED(parser);
builtin_printf_state_t state(streams);
wchar_t *format;

View File

@@ -26,7 +26,7 @@
class parser_t;
// Error message for invalid path operations.
#define BUILTIN_SET_PATH_ERROR L"%ls: Warning: path component %ls may not be valid in %ls.\n"
#define BUILTIN_SET_PATH_ERROR L"%ls: Warning: $%ls entry \"%ls\" is not valid (%s)\n"
// Hint for invalid path operation with a colon.
#define BUILTIN_SET_PATH_HINT L"%ls: Did you mean 'set %ls $%ls %ls'?\n"
@@ -72,24 +72,25 @@ static int my_env_set(const wchar_t *key, const wcstring_list_t &val, int scope,
continue;
}
bool show_perror = false;
int show_hint = 0;
bool error = false;
struct stat buff;
if (wstat(dir, &buff)) {
if (wstat(dir, &buff) == -1) {
error = true;
show_perror = true;
}
if (!(S_ISDIR(buff.st_mode))) {
else if (!S_ISDIR(buff.st_mode)) {
error = true;
errno = ENOTDIR;
}
else if (waccess(dir, X_OK) == -1) {
error = true;
}
if (!error) {
any_success = true;
} else {
streams.err.append_format(_(BUILTIN_SET_PATH_ERROR), L"set", dir.c_str(), key);
streams.err.append_format(_(BUILTIN_SET_PATH_ERROR), L"set", key, dir.c_str(),
strerror(errno));
const wchar_t *colon = wcschr(dir.c_str(), L':');
if (colon && *(colon + 1)) {
@@ -97,10 +98,6 @@ static int my_env_set(const wchar_t *key, const wcstring_list_t &val, int scope,
}
}
if (show_perror) {
builtin_wperror(L"set", streams);
}
if (show_hint) {
streams.err.append_format(_(BUILTIN_SET_PATH_HINT), L"set", key, key,
wcschr(dir.c_str(), L':') + 1);

View File

@@ -771,6 +771,7 @@ static bool unary_primary_evaluate(test_expressions::token_t token, const wcstri
///
/// Return status is the final shell status, i.e. 0 for true, 1 for false and 2 for error.
int builtin_test(parser_t &parser, io_streams_t &streams, wchar_t **argv) {
UNUSED(parser);
using namespace test_expressions;
// The first argument should be the name of the command ('test').

View File

@@ -118,7 +118,7 @@ show_stackframe(const wchar_t msg_level, int frame_count, int skip_levels) {
if (frame_count < 1) frame_count = 999;
debug_shared(msg_level, L"Backtrace:");
std::vector<wcstring> bt = demangled_backtrace(frame_count, skip_levels + 2);
for (int i = 0; i < bt.size(); i++) {
for (int i = 0; (size_t)i < bt.size(); i++) {
debug_shared(msg_level, bt[i]);
}
}
@@ -1340,6 +1340,7 @@ bool unescape_string(const wcstring &input, wcstring *output, unescape_flags_t e
void common_handle_winch(int signal) {
// Don't run ioctl() here, it's not safe to use in signals.
UNUSED(signal);
termsize_valid = false;
}

View File

@@ -52,8 +52,8 @@ typedef std::vector<wcstring> wcstring_list_t;
// Use Unicode "noncharacters" for internal characters as much as we can. This
// gives us 32 "characters" for internal use that we can guarantee should not
// appear in our input stream. See http://www.unicode.org/faq/private_use.html.
#define RESERVED_CHAR_BASE 0xFDD0u
#define RESERVED_CHAR_END 0xFDF0u
#define RESERVED_CHAR_BASE (wchar_t)0xFDD0
#define RESERVED_CHAR_END (wchar_t)0xFDF0
// Split the available noncharacter values into two ranges to ensure there are
// no conflicts among the places we use these special characters.
#define EXPAND_RESERVED_BASE RESERVED_CHAR_BASE
@@ -63,9 +63,9 @@ typedef std::vector<wcstring> wcstring_list_t;
// Make sure the ranges defined above don't exceed the range for noncharacters.
// This is to make sure we didn't do something stupid in subdividing the
// Unicode range for our needs.
#if WILDCARD_RESERVED_END > RESERVED_CHAR_END
#error
#endif
//#if WILDCARD_RESERVED_END > RESERVED_CHAR_END
//#error
//#endif
// These are in the Unicode private-use range. We really shouldn't use this
// range but have little choice in the matter given how our lexer/parser works.
@@ -79,9 +79,9 @@ typedef std::vector<wcstring> wcstring_list_t;
// Note: We don't use the highest 8 bit range (0xF800 - 0xF8FF) because we know
// of at least one use of a codepoint in that range: the Apple symbol (0xF8FF)
// on Mac OS X. See http://www.unicode.org/faq/private_use.html.
#define ENCODE_DIRECT_BASE 0xF600u
#define ENCODE_DIRECT_BASE (wchar_t)0xF600
#define ENCODE_DIRECT_END (ENCODE_DIRECT_BASE + 256)
#define INPUT_COMMON_BASE 0xF700u
#define INPUT_COMMON_BASE (wchar_t)0xF700
#define INPUT_COMMON_END (INPUT_COMMON_BASE + 64)
// Flags for unescape_string functions.
@@ -766,4 +766,13 @@ __attribute__((noinline)) void debug_thread_error(void);
/// specified base, return -1.
long convert_digit(wchar_t d, int base);
/// This is a macro that can be used to silence "unused parameter" warnings from the compiler for
/// functions which need to accept parameters they do not use because they need to be compatible
/// with an interface. It's similar to the Python idiom of doing `_ = expr` at the top of a
/// function in the same situation.
#define UNUSED(expr) \
do { \
(void)(expr); \
} while (0)
#endif

View File

@@ -1187,6 +1187,13 @@ bool completer_t::try_complete_variable(const wcstring &str) {
///
/// \return 0 if unable to complete, 1 otherwise
bool completer_t::try_complete_user(const wcstring &str) {
#ifndef HAVE_GETPWENT
// The getpwent() function does not exist on Android. A Linux user on Android isn't
// really a user - each installed app gets an UID assigned. Listing all UID:s is not
// possible without root access, and doing a ~USER type expansion does not make sense
// since every app is sandboxed and can't access eachother.
return false;
#else
const wchar_t *cmd = str.c_str();
const wchar_t *first_char = cmd;
int res = 0;
@@ -1233,6 +1240,7 @@ bool completer_t::try_complete_user(const wcstring &str) {
}
return res;
#endif
}
void complete(const wcstring &cmd_with_subcmds, std::vector<completion_t> *out_comps,

View File

@@ -191,7 +191,9 @@ static bool var_is_locale(const wcstring &key) {
/// Properly sets all locale information.
static void handle_locale(const wchar_t *env_var_name) {
debug(2, L"handle_locale() called in response to '%ls' changing", env_var_name);
const char *old_msg_locale = setlocale(LC_MESSAGES, NULL);
// We have to make a copy because the subsequent setlocale() call to change the locale will
// invalidate the pointer from the this setlocale() call.
char *old_msg_locale = strdup(setlocale(LC_MESSAGES, NULL));
const env_var_t val = env_get_string(env_var_name, ENV_EXPORT);
const std::string &value = wcs2string(val);
const std::string &name = wcs2string(env_var_name);
@@ -216,6 +218,7 @@ static void handle_locale(const wchar_t *env_var_name) {
_nl_msg_cat_cntr++;
}
#endif
free(old_msg_locale);
}
/// Check if the specified variable is a locale variable.
@@ -267,7 +270,7 @@ static void react_to_variable_change(const wcstring &key) {
/// Universal variable callback function. This function makes sure the proper events are triggered
/// when an event occurs.
static void universal_callback(fish_message_type_t type, const wchar_t *name, const wchar_t *val) {
static void universal_callback(fish_message_type_t type, const wchar_t *name) {
const wchar_t *str = NULL;
switch (type) {
@@ -1102,7 +1105,7 @@ void env_universal_barrier() {
// Post callbacks.
for (size_t i = 0; i < changes.size(); i++) {
const callback_data_t &data = changes.at(i);
universal_callback(data.type, data.key.c_str(), data.val.c_str());
universal_callback(data.type, data.key.c_str());
}
}
}

View File

@@ -826,7 +826,7 @@ var_table_t env_universal_t::read_message_internal(int fd) {
// Walk over it by lines. The contents of an unterminated line will be left in 'line' for
// the next iteration.
size_t line_start = 0;
ssize_t line_start = 0;
while (line_start < amt) {
// Run until we hit a newline.
size_t cursor = line_start;
@@ -1033,7 +1033,7 @@ class universal_notifier_shmem_poller_t : public universal_notifier_t {
}
// Set the size, if it's too small.
if (!errored && size < sizeof(universal_notifier_shmem_t)) {
if (!errored && size < (off_t)sizeof(universal_notifier_shmem_t)) {
if (ftruncate(fd, sizeof(universal_notifier_shmem_t)) < 0) {
int err = errno;
report_error(err, L"Unable to truncate shared memory object with path '%s'", path);
@@ -1120,7 +1120,7 @@ class universal_notifier_shmem_poller_t : public universal_notifier_t {
// If it's been less than five seconds since the last change, we poll quickly Otherwise we
// poll more slowly. Note that a poll is a very cheap shmem read. The bad part about making
// this high is the process scheduling/wakeups it produces.
unsigned long usec_per_sec = 1000000;
long long usec_per_sec = 1000000;
if (get_time() - last_change_time < 5LL * usec_per_sec) {
return usec_per_sec / 10; // 10 times a second
}
@@ -1299,6 +1299,7 @@ class universal_notifier_named_pipe_t : public universal_notifier_t {
// select() on our fd for a while, and sync periodically until the fd is no longer readable.
// However, if we are the one who posted the notification, we don't sync (until we clean
// up!)
UNUSED(fd);
bool should_sync = false;
if (readback_time_usec == 0) {
polling_due_to_readable_fd = true;
@@ -1494,4 +1495,7 @@ bool universal_notifier_t::poll() { return false; }
unsigned long universal_notifier_t::usec_delay_between_polls() const { return 0; }
bool universal_notifier_t::notification_fd_became_readable(int fd) { return false; }
bool universal_notifier_t::notification_fd_became_readable(int fd) {
UNUSED(fd);
return false;
}

View File

@@ -301,7 +301,7 @@ int event_get(const event_t &criterion, std::vector<event_t *> *out) {
bool event_is_signal_observed(int sig) {
// We are in a signal handler! Don't allocate memory, etc.
bool result = false;
if (sig >= 0 && sig < sizeof s_observed_signals / sizeof *s_observed_signals) {
if (sig >= 0 && (unsigned long)sig < sizeof(s_observed_signals) / sizeof(*s_observed_signals)) {
result = s_observed_signals[sig];
}
return result;

View File

@@ -159,6 +159,7 @@ char *get_interpreter(const char *command, char *interpreter, size_t buff_size)
/// specified in \c p. It never returns. Called in a forked child! Do not allocate memory, etc.
static void safe_launch_process(process_t *p, const char *actual_cmd, const char *const *cargv,
const char *const *cenvv) {
UNUSED(p);
int err;
// debug( 1, L"exec '%ls'", p->argv[0] );

View File

@@ -212,7 +212,7 @@ static int iswnumeric(const wchar_t *n) {
}
/// See if the process described by \c proc matches the commandline \c cmd.
static bool match_pid(const wcstring &cmd, const wchar_t *proc, int flags, size_t *offset) {
static bool match_pid(const wcstring &cmd, const wchar_t *proc, size_t *offset) {
// Test for a direct match. If the proc string is empty (e.g. the user tries to complete against
// %), then return an offset pointing at the base command. That ensures that you don't see a
// bunch of dumb paths when completing against all processes.
@@ -507,7 +507,7 @@ static int find_job(const struct find_job_data_t *info) {
if (j->command_is_empty()) continue;
size_t offset;
if (match_pid(j->command(), proc, flags, &offset)) {
if (match_pid(j->command(), proc, &offset)) {
if (flags & EXPAND_FOR_COMPLETIONS) {
append_completion(&completions, j->command_wcstr() + offset + wcslen(proc),
COMPLETE_JOB_DESC, 0);
@@ -527,7 +527,7 @@ static int find_job(const struct find_job_data_t *info) {
if (p->actual_cmd.empty()) continue;
size_t offset;
if (match_pid(p->actual_cmd, proc, flags, &offset)) {
if (match_pid(p->actual_cmd, proc, &offset)) {
if (flags & EXPAND_FOR_COMPLETIONS) {
append_completion(&completions,
wcstring(p->actual_cmd, offset + wcslen(proc)),
@@ -570,7 +570,7 @@ static void find_process(const wchar_t *proc, expand_flags_t flags,
process_iterator_t iterator;
while (iterator.next_process(&process_name, &process_pid)) {
size_t offset;
if (match_pid(process_name, proc, flags, &offset)) {
if (match_pid(process_name, proc, &offset)) {
if (flags & EXPAND_FOR_COMPLETIONS) {
append_completion(out, process_name.c_str() + offset + wcslen(proc),
COMPLETE_PROCESS_DESC, 0);
@@ -756,13 +756,12 @@ static int expand_variables(const wcstring &instr, std::vector<completion_t> *ou
for (long i = last_idx - 1; (i >= 0) && is_ok && !empty; i--) {
const wchar_t c = instr.at(i);
if ((c == VARIABLE_EXPAND) || (c == VARIABLE_EXPAND_SINGLE)) {
long start_pos = i + 1;
long stop_pos;
size_t start_pos = i + 1;
size_t stop_pos;
long var_len;
int is_single = (c == VARIABLE_EXPAND_SINGLE);
stop_pos = start_pos;
while (stop_pos < insize) {
const wchar_t nc = instr.at(stop_pos);
if (nc == VARIABLE_EXPAND_EMPTY) {
@@ -1382,6 +1381,7 @@ static expand_error_t expand_stage_home_and_pid(const wcstring &input,
static expand_error_t expand_stage_wildcards(const wcstring &input, std::vector<completion_t> *out,
expand_flags_t flags, parse_error_list_t *errors) {
UNUSED(errors);
expand_error_t result = EXPAND_OK;
wcstring path_to_expand = input;

View File

@@ -39,6 +39,7 @@
#include <signal.h> // IWYU pragma: keep
#include <wchar.h> // IWYU pragma: keep
#include "common.h" // IWYU pragma: keep
#include "fallback.h" // IWYU pragma: keep
#include "util.h" // IWYU pragma: keep
@@ -244,8 +245,15 @@ char *fish_bindtextdomain(const char *domainname, const char *dirname) {
char *fish_textdomain(const char *domainname) { return textdomain(domainname); }
#else
char *fish_gettext(const char *msgid) { return (char *)msgid; }
char *fish_bindtextdomain(const char *domainname, const char *dirname) { return NULL; }
char *fish_textdomain(const char *domainname) { return NULL; }
char *fish_bindtextdomain(const char *domainname, const char *dirname) {
UNUSED(domainname);
UNUSED(dirname);
return NULL;
}
char *fish_textdomain(const char *domainname) {
UNUSED(domainname);
return NULL;
}
#endif
#ifndef HAVE_KILLPG
@@ -255,10 +263,6 @@ int killpg(int pgr, int sig) {
}
#endif
#ifndef HAVE_NAN
double nan(char *tagp) { return 0.0 / 0.0; }
#endif
// Big hack to use our versions of wcswidth where we know them to be broken, which is
// EVERYWHERE (https://github.com/fish-shell/fish-shell/issues/2199)
#ifndef HAVE_BROKEN_WCWIDTH

View File

@@ -125,8 +125,4 @@ char *fish_textdomain(const char *domainname);
int killpg(int pgr, int sig);
#endif
#ifndef HAVE_NAN
double nan(char *tagp);
#endif
#endif

View File

@@ -84,7 +84,9 @@ static void dump_node(indent_t node_indent, const parse_node_t &node, const wcst
wcstring source_txt = L"";
if (node.source_start != SOURCE_OFFSET_INVALID && node.source_length != SOURCE_OFFSET_INVALID) {
int nextc_idx = node.source_start + node.source_length;
if (nextc_idx < source.size()) nextc = source[node.source_start + node.source_length];
if ((size_t)nextc_idx < source.size()) {
nextc = source[node.source_start + node.source_length];
}
if (node.source_start > 0) prevc = source[node.source_start - 1];
source_txt = source.substr(node.source_start, node.source_length);
}

View File

@@ -54,7 +54,7 @@ static bool should_exit(wchar_t wc) {
}
/// Return the name if the recent sequence of characters matches a known terminfo sequence.
static char *const sequence_name(wchar_t wc) {
static char *sequence_name(wchar_t wc) {
unsigned char c = wc < 0x80 ? wc : 0;
static char recent_chars[8] = {0};
@@ -157,7 +157,7 @@ static void add_char_to_bind_command(wchar_t wc, std::vector<wchar_t> &bind_char
static void output_bind_command(std::vector<wchar_t> &bind_chars) {
if (bind_chars.size()) {
fputs("bind ", stdout);
for (int i = 0; i < bind_chars.size(); i++) {
for (size_t i = 0; i < bind_chars.size(); i++) {
fputs(char_to_symbol(bind_chars[i], true), stdout);
}
fputs(" 'do something'\n", stdout);

View File

@@ -161,6 +161,11 @@ static int chdir_set_pwd(const char *path) {
if (!(e)) err(L"Test failed on line %lu: %s", __LINE__, #e); \
} while (0)
#define do_test_from(e, from_line) \
do { \
if (!(e)) err(L"Test failed on line %lu (from %lu): %s", __LINE__, from_line, #e); \
} while (0)
#define do_test1(e, msg) \
do { \
if (!(e)) err(L"Test failed on line %lu: %ls", __LINE__, (msg)); \
@@ -2165,8 +2170,7 @@ static void test_autosuggest_suggest_special() {
if (system("rm -Rf ~/test_autosuggest_suggest_special/")) err(L"rm failed");
}
static void perform_one_autosuggestion_should_ignore_test(const wcstring &command,
const wcstring &wd, long line) {
static void perform_one_autosuggestion_should_ignore_test(const wcstring &command, long line) {
completion_list_t comps;
complete(command, &comps, COMPLETION_REQUEST_AUTOSUGGESTION, env_vars_snapshot_t::current());
do_test(comps.empty());
@@ -2179,12 +2183,11 @@ static void perform_one_autosuggestion_should_ignore_test(const wcstring &comman
static void test_autosuggestion_ignores() {
say(L"Testing scenarios that should produce no autosuggestions");
const wcstring wd = L"/tmp/autosuggest_test/";
// Do not do file autosuggestions immediately after certain statement terminators - see #1631.
perform_one_autosuggestion_should_ignore_test(L"echo PIPE_TEST|", wd, __LINE__);
perform_one_autosuggestion_should_ignore_test(L"echo PIPE_TEST&", wd, __LINE__);
perform_one_autosuggestion_should_ignore_test(L"echo PIPE_TEST#comment", wd, __LINE__);
perform_one_autosuggestion_should_ignore_test(L"echo PIPE_TEST;", wd, __LINE__);
perform_one_autosuggestion_should_ignore_test(L"echo PIPE_TEST|", __LINE__);
perform_one_autosuggestion_should_ignore_test(L"echo PIPE_TEST&", __LINE__);
perform_one_autosuggestion_should_ignore_test(L"echo PIPE_TEST#comment", __LINE__);
perform_one_autosuggestion_should_ignore_test(L"echo PIPE_TEST;", __LINE__);
}
static void test_autosuggestion_combining() {
@@ -2202,18 +2205,20 @@ static void test_autosuggestion_combining() {
do_test(combine_command_and_autosuggestion(L"alpha", L"ALPHA") == L"alpha");
}
static void test_history_matches(history_search_t &search, size_t matches) {
static void test_history_matches(history_search_t &search, size_t matches, unsigned from_line) {
size_t i;
for (i = 0; i < matches; i++) {
do_test(search.go_backwards());
wcstring item = search.current_string();
}
do_test(!search.go_backwards());
// do_test_from(!search.go_backwards(), from_line);
bool result = search.go_backwards();
do_test_from(!result, from_line);
for (i = 1; i < matches; i++) {
do_test(search.go_forwards());
do_test_from(search.go_forwards(), from_line);
}
do_test(!search.go_forwards());
do_test_from(!search.go_forwards(), from_line);
}
static bool history_contains(history_t *history, const wcstring &txt) {
@@ -2519,28 +2524,64 @@ static wcstring random_string(void) {
}
void history_tests_t::test_history(void) {
history_search_t searcher;
say(L"Testing history");
history_t &history = history_t::history_with_name(L"test_history");
history.clear();
history.add(L"Gamma");
history.add(L"beta");
history.add(L"BetA");
history.add(L"Beta");
history.add(L"alpha");
history.add(L"AlphA");
history.add(L"Alpha");
history.add(L"alph");
history.add(L"ALPH");
history.add(L"ZZZ");
// All three items match "a".
history_search_t search1(history, L"a");
test_history_matches(search1, 3);
do_test(search1.current_string() == L"Alpha");
// Items matching "a", case-sensitive.
searcher = history_search_t(history, L"a");
test_history_matches(searcher, 6, __LINE__);
do_test(searcher.current_string() == L"alph");
// One item matches "et".
history_search_t search2(history, L"et");
test_history_matches(search2, 1);
do_test(search2.current_string() == L"Beta");
// Items matching "alpha", case-insensitive. Note that HISTORY_SEARCH_TYPE_CONTAINS but we have
// to explicitly specify it in order to be able to pass false for the case_sensitive parameter.
searcher = history_search_t(history, L"AlPhA", HISTORY_SEARCH_TYPE_CONTAINS, false);
test_history_matches(searcher, 3, __LINE__);
do_test(searcher.current_string() == L"Alpha");
// Test item removal.
// Items matching "et", case-sensitive.
searcher = history_search_t(history, L"et");
test_history_matches(searcher, 3, __LINE__);
do_test(searcher.current_string() == L"Beta");
// Items starting with "be", case-sensitive.
searcher = history_search_t(history, L"be", HISTORY_SEARCH_TYPE_PREFIX, true);
test_history_matches(searcher, 1, __LINE__);
do_test(searcher.current_string() == L"beta");
// Items starting with "be", case-insensitive.
searcher = history_search_t(history, L"be", HISTORY_SEARCH_TYPE_PREFIX, false);
test_history_matches(searcher, 3, __LINE__);
do_test(searcher.current_string() == L"Beta");
// Items exactly matchine "alph", case-sensitive.
searcher = history_search_t(history, L"alph", HISTORY_SEARCH_TYPE_EXACT, true);
test_history_matches(searcher, 1, __LINE__);
do_test(searcher.current_string() == L"alph");
// Items exactly matchine "alph", case-insensitive.
searcher = history_search_t(history, L"alph", HISTORY_SEARCH_TYPE_EXACT, false);
test_history_matches(searcher, 2, __LINE__);
do_test(searcher.current_string() == L"ALPH");
// Test item removal case-sensitive.
searcher = history_search_t(history, L"Alpha");
test_history_matches(searcher, 1, __LINE__);
history.remove(L"Alpha");
history_search_t search3(history, L"Alpha");
test_history_matches(search3, 0);
searcher = history_search_t(history, L"Alpha");
test_history_matches(searcher, 0, __LINE__);
// Test history escaping and unescaping, yaml, etc.
history_item_list_t before, after;
@@ -3844,6 +3885,7 @@ static void test_env_vars(void) {
/// Main test.
int main(int argc, char **argv) {
UNUSED(argc);
// Look for the file tests/test.fish. We expect to run in a directory containing that file.
// If we don't find it, walk up the directory hierarchy until we do, or error.
while (access("./tests/test.fish", F_OK) != 0) {

View File

@@ -158,6 +158,7 @@ function_info_t::function_info_t(const function_info_t &data, const wchar_t *fil
shadow_scope(data.shadow_scope) {}
void function_add(const function_data_t &data, const parser_t &parser, int definition_line_offset) {
UNUSED(parser);
ASSERT_IS_MAIN_THREAD();
CHECK(!data.name.empty(), );

View File

@@ -1186,6 +1186,7 @@ const highlighter_t::color_array_t &highlighter_t::highlight() {
void highlight_shell(const wcstring &buff, std::vector<highlight_spec_t> &color, size_t pos,
wcstring_list_t *error, const env_vars_snapshot_t &vars) {
UNUSED(error);
// 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();
@@ -1197,6 +1198,7 @@ void highlight_shell(const wcstring &buff, std::vector<highlight_spec_t> &color,
void highlight_shell_no_io(const wcstring &buff, std::vector<highlight_spec_t> &color, size_t pos,
wcstring_list_t *error, const env_vars_snapshot_t &vars) {
UNUSED(error);
// 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();
@@ -1291,6 +1293,8 @@ static void highlight_universal_internal(const wcstring &buffstr,
void highlight_universal(const wcstring &buff, std::vector<highlight_spec_t> &color, size_t pos,
wcstring_list_t *error, const env_vars_snapshot_t &vars) {
UNUSED(error);
UNUSED(vars);
assert(buff.size() == color.size());
std::fill(color.begin(), color.end(), 0);
highlight_universal_internal(buff, color, pos);

View File

@@ -1,4 +1,5 @@
// History functions, part of the user interface.
//
#include "config.h" // IWYU pragma: keep
#include <assert.h>
@@ -428,27 +429,52 @@ bool history_item_t::merge(const history_item_t &item) {
return result;
}
#if 0
history_item_t::history_item_t(const wcstring &str)
: contents(str), creation_timestamp(time(NULL)), identifier(0) {}
: contents(str), contents_lower(L""), creation_timestamp(time(NULL)), identifier(0) {
for (wcstring::const_iterator it = str.begin(); it != str.end(); ++it) {
contents_lower.push_back(towlower(*it));
}
}
#endif
history_item_t::history_item_t(const wcstring &str, time_t when, history_identifier_t ident)
: contents(str), creation_timestamp(when), identifier(ident) {}
: contents(str), contents_lower(L""), creation_timestamp(when), identifier(ident) {
for (wcstring::const_iterator it = str.begin(); it != str.end(); ++it) {
contents_lower.push_back(towlower(*it));
}
}
bool history_item_t::matches_search(const wcstring &term, enum history_search_type_t type) const {
switch (type) {
case HISTORY_SEARCH_TYPE_CONTAINS: {
bool history_item_t::matches_search(const wcstring &term, enum history_search_type_t type,
bool case_sensitive) const {
// We don't use a switch below because there are only three cases and if the strings are the
// same length we can use the faster HISTORY_SEARCH_TYPE_EXACT for the other two cases.
//
// Too, we consider equal strings to match a prefix search, so that autosuggest will allow
// suggesting what you've typed.
if (case_sensitive) {
if (type == HISTORY_SEARCH_TYPE_EXACT || term.size() == contents.size()) {
return term == contents;
} else if (type == HISTORY_SEARCH_TYPE_CONTAINS) {
return contents.find(term) != wcstring::npos;
}
case HISTORY_SEARCH_TYPE_PREFIX: {
// We consider equal strings to match a prefix search, so that autosuggest will allow
// suggesting what you've typed.
} else if (type == HISTORY_SEARCH_TYPE_PREFIX) {
return string_prefixes_string(term, contents);
}
case HISTORY_SEARCH_TYPE_EXACT: {
return term == contents;
} else {
wcstring lterm(L"");
for (wcstring::const_iterator it = term.begin(); it != term.end(); ++it) {
lterm.push_back(towlower(*it));
}
if (type == HISTORY_SEARCH_TYPE_EXACT || lterm.size() == contents.size()) {
return lterm == contents_lower;
} else if (type == HISTORY_SEARCH_TYPE_CONTAINS) {
return contents_lower.find(lterm) != wcstring::npos;
} else if (type == HISTORY_SEARCH_TYPE_PREFIX) {
return string_prefixes_string(lterm, contents_lower);
}
default: { DIE("unexpected history_search_type_t value"); }
}
DIE("unexpected history_search_type_t value");
}
/// Append our YAML history format to the provided vector at the given offset, updating the offset.
@@ -562,7 +588,7 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
// leading "- cmd: - cmd: - cmd:". Trim all but one leading "- cmd:".
const char *double_cmd = "- cmd: - cmd: ";
const size_t double_cmd_len = strlen(double_cmd);
while (a_newline - line_start > double_cmd_len &&
while ((size_t)(a_newline - line_start) > double_cmd_len &&
!memcmp(line_start, double_cmd, double_cmd_len)) {
// Skip over just one of the - cmd. In the end there will be just one left.
line_start += strlen("- cmd: ");
@@ -572,8 +598,10 @@ static size_t offset_of_next_item_fish_2_0(const char *begin, size_t mmap_length
// 123456". Ignore those.
const char *cmd_when = "- cmd: when:";
const size_t cmd_when_len = strlen(cmd_when);
if (a_newline - line_start >= cmd_when_len && !memcmp(line_start, cmd_when, cmd_when_len))
if ((size_t)(a_newline - line_start) >= cmd_when_len &&
!memcmp(line_start, cmd_when, cmd_when_len)) {
continue;
}
// At this point, we know line_start is at the beginning of an item. But maybe we want to
// skip this item because of timestamps. A 0 cutoff means we don't care; if we do care, then
@@ -763,16 +791,27 @@ void history_t::add(const wcstring &str, history_identifier_t ident, bool pendin
this->add(history_item_t(str, when, ident), pending);
}
void history_t::remove(const wcstring &str) {
// Add to our list of deleted items.
deleted_items.insert(str);
bool icompare_pred(wchar_t a, wchar_t b) { return std::tolower(a) == std::tolower(b); }
bool icompare(wcstring const &a, wcstring const &b) {
if (a.length() == b.length()) {
return std::equal(b.begin(), b.end(), a.begin(), icompare_pred);
} else {
return false;
}
}
// Remove matching history entries from our list of new items. This only supports literal,
// case-sensitive, matches.
void history_t::remove(const wcstring &str_to_remove) {
// Add to our list of deleted items.
deleted_items.insert(str_to_remove);
// Remove from our list of new items.
size_t idx = new_items.size();
while (idx--) {
if (new_items.at(idx).str() == str) {
bool matched = new_items.at(idx).str() == str_to_remove;
if (matched) {
new_items.erase(new_items.begin() + idx);
// If this index is before our first_unwritten_new_item_index, then subtract one from
// that index so it stays pointing at the same item. If it is equal to or larger, then
// we have not yet writen this item, so we don't have to adjust the index.
@@ -1001,7 +1040,7 @@ bool history_search_t::go_backwards() {
// Look for a term that matches and that we haven't seen before.
const wcstring &str = item.str();
if (item.matches_search(term, search_type) && !match_already_made(str) &&
if (item.matches_search(term, search_type, case_sensitive) && !match_already_made(str) &&
!should_skip_match(str)) {
prev_matches.push_back(prev_match_t(idx, item));
return true;
@@ -1397,7 +1436,7 @@ void history_t::save(void) {
// Formats a single history record, including a trailing newline. Returns true
// if bytes were written to the output stream and false otherwise.
static bool format_history_record(const history_item_t &item, const wchar_t *show_time_format,
io_streams_t &streams) {
bool null_terminate, io_streams_t &streams) {
if (show_time_format) {
const time_t seconds = item.timestamp();
struct tm timestamp;
@@ -1410,17 +1449,19 @@ static bool format_history_record(const history_item_t &item, const wchar_t *sho
streams.out.append(timestamp_string);
}
streams.out.append(item.str());
streams.out.append(L"\n");
streams.out.append(null_terminate ? L'\0' : L'\n');
return true;
}
bool history_t::search(history_search_type_t search_type, wcstring_list_t search_args,
const wchar_t *show_time_format, long max_items, io_streams_t &streams) {
const wchar_t *show_time_format, long max_items, bool case_sensitive,
bool null_terminate, io_streams_t &streams) {
// scoped_lock locker(lock);
if (search_args.empty()) {
// Start at one because zero is the current command.
for (int i = 1; !this->item_at_index(i).empty() && max_items; ++i, --max_items) {
if (!format_history_record(this->item_at_index(i), show_time_format, streams)) {
if (!format_history_record(this->item_at_index(i), show_time_format, null_terminate,
streams)) {
return false;
}
}
@@ -1434,9 +1475,11 @@ bool history_t::search(history_search_type_t search_type, wcstring_list_t search
streams.err.append_format(L"Searching for the empty string isn't allowed");
return false;
}
history_search_t searcher = history_search_t(*this, search_string, search_type);
history_search_t searcher =
history_search_t(*this, search_string, search_type, case_sensitive);
while (searcher.go_backwards()) {
if (!format_history_record(searcher.current_item(), show_time_format, streams)) {
if (!format_history_record(searcher.current_item(), show_time_format, null_terminate,
streams)) {
return false;
}
if (--max_items == 0) return true;
@@ -1659,8 +1702,8 @@ static int threaded_perform_file_detection(file_detection_context_t *ctx) {
return ctx->perform_file_detection(true /* test all */);
}
static void perform_file_detection_done(file_detection_context_t *ctx,
int success) { //!OCLINT(success is ignored)
static void perform_file_detection_done(file_detection_context_t *ctx, int success) {
UNUSED(success);
ASSERT_IS_MAIN_THREAD();
// Now that file detection is done, update the history item with the valid file paths.

View File

@@ -59,7 +59,8 @@ class history_item_t {
bool merge(const history_item_t &item);
// The actual contents of the entry.
wcstring contents;
wcstring contents; // value as entered by the user
wcstring contents_lower; // value normalized to all lowercase for case insensitive comparisons
// Original creation time for the entry.
time_t creation_timestamp;
@@ -71,15 +72,16 @@ class history_item_t {
path_list_t required_paths;
public:
explicit history_item_t(const wcstring &str);
explicit history_item_t(const wcstring &, time_t, history_identifier_t ident = 0);
explicit history_item_t(const wcstring &str, time_t when = 0, history_identifier_t ident = 0);
const wcstring &str() const { return contents; }
const wcstring &str_lower() const { return contents_lower; }
bool empty() const { return contents.empty(); }
// Whether our contents matches a search term.
bool matches_search(const wcstring &term, enum history_search_type_t type) const;
bool matches_search(const wcstring &term, enum history_search_type_t type,
bool case_sensitive) const;
time_t timestamp() const { return creation_timestamp; }
@@ -227,7 +229,8 @@ class history_t {
// Searches history.
bool search(history_search_type_t search_type, wcstring_list_t search_args,
const wchar_t *show_time_format, long max_items, io_streams_t &streams);
const wchar_t *show_time_format, long max_items, bool case_sensitive,
bool null_terminate, io_streams_t &streams);
// Enable / disable automatic saving. Main thread only!
void disable_automatic_saving();
@@ -262,8 +265,12 @@ class history_search_t {
// The history in which we are searching.
history_t *history;
// Our type.
// The search term.
wcstring term;
// Our search type.
enum history_search_type_t search_type;
bool case_sensitive;
// Our list of previous matches as index, value. The end is the current match.
typedef std::pair<size_t, history_item_t> prev_match_t;
@@ -272,9 +279,6 @@ class history_search_t {
// Returns yes if a given term is in prev_matches.
bool match_already_made(const wcstring &match) const;
// The search term.
wcstring term;
// Additional strings to skip (sorted).
wcstring_list_t external_skips;
@@ -310,11 +314,19 @@ class history_search_t {
// Constructor.
history_search_t(history_t &hist, const wcstring &str,
enum history_search_type_t type = HISTORY_SEARCH_TYPE_CONTAINS)
: history(&hist), search_type(type), term(str) {}
enum history_search_type_t type = HISTORY_SEARCH_TYPE_CONTAINS,
bool case_sensitive = true)
: history(&hist), term(str), search_type(type), case_sensitive(case_sensitive) {
if (!case_sensitive) {
term = wcstring();
for (wcstring::const_iterator it = str.begin(); it != str.end(); ++it) {
term.push_back(towlower(*it));
}
}
}
// Default constructor.
history_search_t() : history(), search_type(HISTORY_SEARCH_TYPE_CONTAINS), term() {}
history_search_t() : history(), term(), search_type(HISTORY_SEARCH_TYPE_CONTAINS), case_sensitive(true) {}
};
// Init history library. The history file won't actually be loaded until the first time a history

View File

@@ -124,7 +124,7 @@ static const wchar_t *const name_arr[] = {L"beginning-of-line",
wcstring describe_char(wint_t c) {
wint_t initial_cmd_char = R_BEGINNING_OF_LINE;
size_t name_count = sizeof name_arr / sizeof *name_arr;
long name_count = sizeof(name_arr) / sizeof(*name_arr);
if (c >= initial_cmd_char && c < initial_cmd_char + name_count) {
return format_string(L"%02x (%ls)", c, name_arr[c - initial_cmd_char]);
}
@@ -535,7 +535,7 @@ static void input_mapping_execute_matching_or_generic(bool allow_commands) {
const wcstring bind_mode = input_get_bind_mode();
for (int i = 0; i < mapping_list.size(); i++) {
for (size_t i = 0; i < mapping_list.size(); i++) {
const input_mapping_t &m = mapping_list.at(i);
// debug(0, L"trying mapping (%ls,%ls,%ls)\n", escape(m.seq.c_str(), ESCAPE_ALL).c_str(),

View File

@@ -116,6 +116,7 @@ static void *this_thread() { return (void *)(intptr_t)pthread_self(); }
/// The function that does thread work.
static void *iothread_worker(void *unused) {
UNUSED(unused);
scoped_lock locker(s_spawn_queue_lock);
struct SpawnRequest_t *req;
while ((req = dequeue_spawn_request()) != NULL) {

View File

@@ -93,7 +93,7 @@ class lru_cache_t {
lru_node_t mouth;
/// Overridable callback for when a node is evicted.
virtual void node_was_evicted(node_type_t *node) {}
virtual void node_was_evicted(node_type_t *node) { UNUSED(node); }
public:
/// Constructor
@@ -185,7 +185,6 @@ class lru_cache_t {
public:
explicit iterator(lru_node_t *val) : node(val) {}
void operator++() { node = lru_cache_t::get_previous(node); }
void operator++(int x) { node = lru_cache_t::get_previous(node); }
bool operator==(const iterator &other) { return node == other.node; }
bool operator!=(const iterator &other) { return !(*this == other); }
node_type_t *operator*() { return static_cast<node_type_t *>(node); }

View File

@@ -49,7 +49,7 @@ void output_set_writer(int (*writer)(char)) {
int (*output_get_writer())(char) { return out; }
/// Returns true if we think tparm can handle outputting a color index
static bool term_supports_color_natively(unsigned int c) { return max_colors >= (c + 1); }
static bool term_supports_color_natively(unsigned int c) { return (unsigned)max_colors >= c + 1; }
color_support_t output_get_color_support(void) { return color_support; }
@@ -71,6 +71,14 @@ static bool write_color_escape(char *todo, unsigned char idx, bool is_fg) {
// We are attempting to bypass the term here. Generate the ANSI escape sequence ourself.
char buff[16] = "";
if (idx < 16) {
// this allows the non-bright color to happen instead of no color working at all when
// a bright is attempted when only colors 0-7 are supported.
// TODO: enter bold mode in builtin_set_color in the same circumstance- doing that
// combined
// with what we do here, will make the brights actually work for virtual
// consoles/ancient emulators.
if (max_colors == 8 && idx > 8) idx -= 8;
snprintf(buff, sizeof buff, "\x1b[%dm", ((idx > 7) ? 82 : 30) + idx + !is_fg * 10);
} else {
snprintf(buff, sizeof buff, "\x1b[%d;5;%dm", is_fg ? 38 : 48, idx);

View File

@@ -50,8 +50,8 @@ static size_t divide_round_up(size_t numer, size_t denom) {
void pager_t::recalc_min_widths(comp_info_list_t *lst) const {
for (size_t i = 0; i < lst->size(); i++) {
comp_t *c = &lst->at(i);
c->min_width = mini(c->desc_width, maxi(0, available_term_width / 3 - 2)) +
mini(c->desc_width, maxi(0, available_term_width / 5 - 4)) + 4;
c->min_width = mini(c->desc_width, maxi((size_t)0, available_term_width / 3 - 2)) +
mini(c->desc_width, maxi((size_t)0, available_term_width / 5 - 4)) + 4;
}
}
@@ -84,14 +84,16 @@ static int print_max(const wcstring &str, highlight_spec_t color, int max, bool
/// Print the specified item using at the specified amount of space.
line_t pager_t::completion_print_item(const wcstring &prefix, const comp_t *c, size_t row,
size_t column, int width, bool secondary, bool selected,
size_t column, size_t width, bool secondary, bool selected,
page_rendering_t *rendering) const {
int comp_width = 0, desc_width = 0;
int written = 0;
UNUSED(column);
UNUSED(row);
UNUSED(rendering);
size_t comp_width = 0, desc_width = 0;
size_t written = 0;
line_t line_data;
if (c->pref_width <= width) {
if (c->pref_width <= (size_t)width) {
// The entry fits, we give it as much space as it wants.
comp_width = c->comp_width;
desc_width = c->desc_width;
@@ -255,8 +257,7 @@ static void join_completions(comp_info_list_t *comps) {
}
/// Generate a list of comp_t structures from a list of completions.
static comp_info_list_t process_completions_into_infos(const completion_list_t &lst,
const wcstring &prefix) {
static comp_info_list_t process_completions_into_infos(const completion_list_t &lst) {
const size_t lst_size = lst.size();
// Make the list of the correct size up-front.
@@ -341,7 +342,7 @@ void pager_t::refilter_completions() {
void pager_t::set_completions(const completion_list_t &raw_completions) {
// Get completion infos out of it.
unfiltered_completion_infos = process_completions_into_infos(raw_completions, prefix);
unfiltered_completion_infos = process_completions_into_infos(raw_completions);
// Maybe join them.
if (prefix == L"-") join_completions(&unfiltered_completion_infos);
@@ -379,12 +380,12 @@ bool pager_t::completion_try_print(size_t cols, const wcstring &prefix, const co
bool print = false;
// Compute the effective term width and term height, accounting for disclosure.
int term_width = this->available_term_width;
int term_height =
size_t term_width = this->available_term_width;
size_t term_height =
this->available_term_height - 1 -
(search_field_shown ? 1 : 0); // we always subtract 1 to make room for a comment row
if (!this->fully_disclosed) {
term_height = mini(term_height, PAGER_UNDISCLOSED_MAX_ROWS);
term_height = mini(term_height, (size_t)PAGER_UNDISCLOSED_MAX_ROWS);
}
size_t row_count = divide_round_up(lst.size(), cols);
@@ -404,15 +405,15 @@ bool pager_t::completion_try_print(size_t cols, const wcstring &prefix, const co
rendering->remaining_to_disclose = 0;
}
int pref_tot_width = 0;
int min_tot_width = 0;
size_t pref_tot_width = 0;
size_t min_tot_width = 0;
// Skip completions on tiny terminals.
if (term_width < PAGER_MIN_WIDTH) return true;
// Calculate how wide the list would be.
for (long col = 0; col < cols; col++) {
for (long row = 0; row < row_count; row++) {
for (size_t col = 0; col < cols; col++) {
for (size_t row = 0; row < row_count; row++) {
int pref, min;
const comp_t *c;
if (lst.size() <= col * row_count + row) continue;
@@ -526,7 +527,7 @@ page_rendering_t pager_t::render() const {
rendering.search_field_shown = this->search_field_shown;
rendering.search_field_line = this->search_field_line;
for (int cols = PAGER_MAX_COLS; cols > 0; cols--) {
for (size_t cols = PAGER_MAX_COLS; cols > 0; cols--) {
// Initially empty rendering.
rendering.screen_data.resize(0);
@@ -641,7 +642,7 @@ bool pager_t::select_next_completion_in_direction(selection_direction_t directio
// Cardinal directions. We have a completion index; we wish to compute its row and column.
size_t current_row = this->get_selected_row(rendering);
size_t current_col = this->get_selected_column(rendering);
size_t page_height = maxi(rendering.term_height - 1, 1);
size_t page_height = maxi(rendering.term_height - 1, (size_t)1);
switch (direction) {
case direction_page_north: {

View File

@@ -17,8 +17,8 @@
/// Represents rendering from the pager.
class page_rendering_t {
public:
int term_width;
int term_height;
size_t term_width;
size_t term_height;
size_t rows;
size_t cols;
size_t row_start;
@@ -47,8 +47,8 @@ page_rendering_t render_completions(const completion_list_t &raw_completions,
const wcstring &prefix);
class pager_t {
int available_term_width;
int available_term_height;
size_t available_term_width;
size_t available_term_height;
size_t selected_completion_idx;
size_t suggested_row_start;
@@ -73,13 +73,13 @@ class pager_t {
/// The representative completion.
completion_t representative;
/// On-screen width of the completion string.
int comp_width;
size_t comp_width;
/// On-screen width of the description information.
int desc_width;
size_t desc_width;
/// Preferred total width.
int pref_width;
size_t pref_width;
/// Minimum acceptable width.
int min_width;
size_t min_width;
comp_t()
: comp(),
@@ -114,7 +114,7 @@ class pager_t {
const wcstring &prefix, const comp_info_list_t &lst,
page_rendering_t *rendering) const;
line_t completion_print_item(const wcstring &prefix, const comp_t *c, size_t row, size_t column,
int width, bool secondary, bool selected,
size_t width, bool secondary, bool selected,
page_rendering_t *rendering) const;
public:

View File

@@ -1076,6 +1076,7 @@ parse_execution_result_t parse_execution_context_t::populate_block_process(
job_t *job, process_t *proc, const parse_node_t &statement_node) {
// We handle block statements by creating INTERNAL_BLOCK_NODE, that will bounce back to us when
// it's time to execute them.
UNUSED(job);
assert(statement_node.type == symbol_block_statement ||
statement_node.type == symbol_if_statement ||
statement_node.type == symbol_switch_statement);
@@ -1133,6 +1134,7 @@ parse_execution_result_t parse_execution_context_t::populate_job_process(
parse_execution_result_t parse_execution_context_t::populate_job_from_job_node(
job_t *j, const parse_node_t &job_node, const block_t *associated_block) {
UNUSED(associated_block);
assert(job_node.type == symbol_job);
// Tell the job what its command is.

View File

@@ -30,6 +30,9 @@ using namespace parse_productions;
extern const production_t sym##_only; \
static const production_t *resolve_##sym( \
const parse_token_t &token1, const parse_token_t &token2, parse_node_tag_t *out_tag) { \
UNUSED(token1); \
UNUSED(token2); \
UNUSED(out_tag); \
return &sym##_only; \
} \
const production_t sym##_only
@@ -41,6 +44,8 @@ using namespace parse_productions;
/// A job_list is a list of jobs, separated by semicolons or newlines.
RESOLVE(job_list) {
UNUSED(token2);
UNUSED(out_tag);
P list_end = {};
P normal = {symbol_job, symbol_job_list};
P empty_line = {parse_token_type_end, symbol_job_list};
@@ -80,6 +85,8 @@ RESOLVE(job_list) {
RESOLVE_ONLY(job) = {symbol_statement, symbol_job_continuation, symbol_optional_background};
RESOLVE(job_continuation) {
UNUSED(token2);
UNUSED(out_tag);
P empty = {};
P piped = {parse_token_type_pipe, symbol_statement, symbol_job_continuation};
switch (token1.type) {
@@ -94,6 +101,7 @@ RESOLVE(job_continuation) {
// A statement is a normal command, or an if / while / and etc.
RESOLVE(statement) {
UNUSED(out_tag);
P boolean = {symbol_boolean_statement};
P block = {symbol_block_statement};
P ifs = {symbol_if_statement};
@@ -173,6 +181,8 @@ RESOLVE_ONLY(if_clause) = {KEYWORD(parse_keyword_if), symbol_job, parse_token_ty
symbol_andor_job_list, symbol_job_list};
RESOLVE(else_clause) {
UNUSED(token2);
UNUSED(out_tag);
P empty = {};
P else_cont = {KEYWORD(parse_keyword_else), symbol_else_continuation};
switch (token1.keyword) {
@@ -184,6 +194,8 @@ RESOLVE(else_clause) {
}
RESOLVE(else_continuation) {
UNUSED(token2);
UNUSED(out_tag);
P elseif = {symbol_if_clause, symbol_else_clause};
P elseonly = {parse_token_type_end, symbol_job_list};
@@ -200,6 +212,8 @@ RESOLVE_ONLY(switch_statement) = {
symbol_case_item_list, symbol_end_command, symbol_arguments_or_redirections_list};
RESOLVE(case_item_list) {
UNUSED(token2);
UNUSED(out_tag);
P empty = {};
P case_item = {symbol_case_item, symbol_case_item_list};
P blank_line = {parse_token_type_end, symbol_case_item_list};
@@ -215,6 +229,7 @@ RESOLVE_ONLY(case_item) = {KEYWORD(parse_keyword_case), symbol_argument_list, pa
symbol_job_list};
RESOLVE(andor_job_list) {
UNUSED(out_tag);
P list_end = {};
P andor_job = {symbol_job, symbol_andor_job_list};
P empty_line = {parse_token_type_end, symbol_andor_job_list};
@@ -233,6 +248,8 @@ RESOLVE(andor_job_list) {
}
RESOLVE(argument_list) {
UNUSED(token2);
UNUSED(out_tag);
P empty = {};
P arg = {symbol_argument, symbol_argument_list};
switch (token1.type) {
@@ -244,6 +261,8 @@ RESOLVE(argument_list) {
}
RESOLVE(freestanding_argument_list) {
UNUSED(token2);
UNUSED(out_tag);
P empty = {};
P arg = {symbol_argument, symbol_freestanding_argument_list};
P semicolon = {parse_token_type_end, symbol_freestanding_argument_list};
@@ -263,6 +282,8 @@ RESOLVE_ONLY(block_statement) = {symbol_block_header, symbol_job_list, symbol_en
symbol_arguments_or_redirections_list};
RESOLVE(block_header) {
UNUSED(token2);
UNUSED(out_tag);
P forh = {symbol_for_header};
P whileh = {symbol_while_header};
P funch = {symbol_function_header};
@@ -295,6 +316,7 @@ RESOLVE_ONLY(function_header) = {KEYWORD(parse_keyword_function), symbol_argumen
// A boolean statement is AND or OR or NOT.
RESOLVE(boolean_statement) {
UNUSED(token2);
P ands = {KEYWORD(parse_keyword_and), symbol_statement};
P ors = {KEYWORD(parse_keyword_or), symbol_statement};
P nots = {KEYWORD(parse_keyword_not), symbol_statement};
@@ -352,6 +374,8 @@ RESOLVE(decorated_statement) {
RESOLVE_ONLY(plain_statement) = {parse_token_type_string, symbol_arguments_or_redirections_list};
RESOLVE(arguments_or_redirections_list) {
UNUSED(token2);
UNUSED(out_tag);
P empty = {};
P value = {symbol_argument_or_redirection, symbol_arguments_or_redirections_list};
switch (token1.type) {
@@ -364,6 +388,8 @@ RESOLVE(arguments_or_redirections_list) {
}
RESOLVE(argument_or_redirection) {
UNUSED(token2);
UNUSED(out_tag);
P arg = {symbol_argument};
P redir = {symbol_redirection};
switch (token1.type) {
@@ -381,6 +407,7 @@ RESOLVE_ONLY(argument) = {parse_token_type_string};
RESOLVE_ONLY(redirection) = {parse_token_type_redirection, parse_token_type_string};
RESOLVE(optional_background) {
UNUSED(token2);
P empty = {};
P background = {parse_token_type_background};
switch (token1.type) {

View File

@@ -67,16 +67,11 @@ size_t parse_util_get_offset_from_line(const wcstring &str, int line) {
size_t i;
int count = 0;
if (line < 0) {
return (size_t)-1;
}
if (line < 0) return (size_t)-1;
if (line == 0) return 0;
for (i = 0;; i++) {
if (!buff[i]) {
return -1;
}
if (!buff[i]) return (size_t)-1;
if (buff[i] == L'\n') {
count++;
@@ -91,25 +86,18 @@ size_t parse_util_get_offset(const wcstring &str, int line, long line_offset) {
const wchar_t *buff = str.c_str();
size_t off = parse_util_get_offset_from_line(buff, line);
size_t off2 = parse_util_get_offset_from_line(buff, line + 1);
long line_offset2 = line_offset;
if (off == (size_t)(-1)) {
return -1;
if (off == (size_t)-1) return (size_t)-1;
if (off2 == (size_t)-1) off2 = wcslen(buff) + 1;
if (line_offset < 0) line_offset = 0;
if ((size_t)line_offset >= off2 - off - 1) {
line_offset = off2 - off - 1;
}
if (off2 == (size_t)(-1)) {
off2 = wcslen(buff) + 1;
}
if (line_offset2 < 0) {
line_offset2 = 0;
}
if (line_offset2 >= off2 - off - 1) {
line_offset2 = off2 - off - 1;
}
return off + line_offset2;
return off + line_offset;
}
static int parse_util_locate_brackets_of_type(const wchar_t *in, wchar_t **begin, wchar_t **end,
@@ -305,7 +293,7 @@ static void job_or_process_extent(const wchar_t *buff, size_t cursor_pos, const
return;
}
assert(cursor_pos >= (begin - buff));
assert(cursor_pos >= (size_t)(begin - buff));
const size_t pos = cursor_pos - (begin - buff);
if (a) *a = begin;
@@ -369,7 +357,7 @@ void parse_util_token_extent(const wchar_t *buff, size_t cursor_pos, const wchar
}
// pos is equivalent to cursor_pos within the range of the command substitution {begin, end}.
long offset_within_cmdsubst = cursor_pos - (cmdsubst_begin - buff);
size_t offset_within_cmdsubst = cursor_pos - (cmdsubst_begin - buff);
a = cmdsubst_begin + offset_within_cmdsubst;
b = a;

View File

@@ -285,6 +285,7 @@ pid_t execute_fork(bool wait_for_threads_to_die) {
bool fork_actions_make_spawn_properties(posix_spawnattr_t *attr,
posix_spawn_file_actions_t *actions, job_t *j, process_t *p,
const io_chain_t &io_chain) {
UNUSED(p);
// Initialize the output.
if (posix_spawnattr_init(attr) != 0) {
return false;

View File

@@ -254,12 +254,12 @@ int job_signal(job_t *j, int signal) {
int res = 0;
if (j->pgid != my_pid) {
res = killpg(j->pgid, SIGHUP);
res = killpg(j->pgid, signal);
} else {
for (process_t *p = j->first_process; p; p = p->next) {
if (!p->completed) {
if (p->pid) {
if (kill(p->pid, SIGHUP)) {
if (kill(p->pid, signal)) {
res = -1;
break;
}
@@ -272,7 +272,7 @@ int job_signal(job_t *j, int signal) {
}
/// Store the status of the process pid that was returned by waitpid.
static void mark_process_status(const job_t *j, process_t *p, int status) {
static void mark_process_status(process_t *p, int status) {
// debug( 0, L"Process %ls %ls", p->argv[0], WIFSTOPPED (status)?L"stopped":(WIFEXITED( status
// )?L"exited":(WIFSIGNALED( status )?L"signaled to exit":L"BLARGH")) );
p->status = status;
@@ -291,6 +291,7 @@ static void mark_process_status(const job_t *j, process_t *p, int status) {
void job_mark_process_as_failed(const job_t *job, process_t *p) {
// The given process failed to even lift off (e.g. posix_spawn failed) and so doesn't have a
// valid pid. Mark it as dead.
UNUSED(job);
for (process_t *cursor = p; cursor != NULL; cursor = cursor->next) {
cursor->completed = 1;
}
@@ -310,7 +311,7 @@ static void handle_child_status(pid_t pid, int status) {
process_t *prev = 0;
for (p = j->first_process; p; p = p->next) {
if (pid == p->pid) {
mark_process_status(j, p, status);
mark_process_status(p, status);
if (p->completed && prev != 0) {
if (!prev->completed && prev->pid) {
kill(prev->pid, SIGPIPE);
@@ -455,7 +456,10 @@ static int process_mark_finished_children(bool wants_await) {
}
/// This is called from a signal handler. The signal is always SIGCHLD.
void job_handle_signal(int signal, siginfo_t *info, void *con) {
void job_handle_signal(int signal, siginfo_t *info, void *context) {
UNUSED(signal);
UNUSED(info);
UNUSED(context);
// This is the only place that this generation count is modified. It's OK if it overflows.
s_sigchld_generation_count += 1;
}

View File

@@ -468,7 +468,7 @@ static void reader_kill(editable_line_t *el, size_t begin_idx, size_t length, in
}
// This is called from a signal handler!
void reader_handle_int(int sig) {
void reader_handle_sigint() {
if (!is_interactive_read) {
parser_t::skip_all_blocks();
}
@@ -846,7 +846,10 @@ void reader_repaint_if_needed() {
}
}
static void reader_repaint_if_needed_one_arg(void *unused) { reader_repaint_if_needed(); }
static void reader_repaint_if_needed_one_arg(void *unused) {
UNUSED(unused);
reader_repaint_if_needed();
}
void reader_react_to_color_change() {
if (!data) return;
@@ -2003,7 +2006,13 @@ parser_test_error_bits_t reader_shell_test(const wchar_t *b) {
/// Test if the given string contains error. Since this is the error detection for general purpose,
/// there are no invalid strings, so this function always returns false.
static parser_test_error_bits_t default_test(const wchar_t *b) { return 0; }
///
/// TODO: Possibly remove this. It is called from only only one place: reader_push().Since it always
/// returns a static result it's not clear why it's needed.
static parser_test_error_bits_t default_test(const wchar_t *b) {
UNUSED(b);
return 0;
}
void reader_push(const wchar_t *name) {
reader_data_t *n = new reader_data_t();
@@ -2149,6 +2158,7 @@ static void highlight_search(void) {
}
static void highlight_complete(background_highlight_context_t *ctx, int result) {
UNUSED(result); // ignored because of the indirect invocation via iothread_perform()
ASSERT_IS_MAIN_THREAD();
if (ctx->string_to_highlight == data->command_line.text) {
// The data hasn't changed, so swap in our colors. The colors may not have changed, so do
@@ -2743,7 +2753,7 @@ const wchar_t *reader_readline(int nchars) {
if (data->search_mode) {
data->search_mode = NO_SEARCH;
if (data->token_history_pos == -1) {
if (data->token_history_pos == (size_t)-1) {
// history_reset();
data->history_search.go_to_end();
reader_set_buffer(data->search_buff, data->search_buff.size());

View File

@@ -192,7 +192,7 @@ void reader_set_exit_on_interrupt(bool flag);
bool shell_is_exiting();
/// The readers interrupt signal handler. Cancels all currently running blocks.
void reader_handle_int(int signal);
void reader_handle_sigint();
/// This function returns true if fish is exiting by force, i.e. because stdin died.
int reader_exit_forced();

View File

@@ -205,7 +205,8 @@ size_t escape_code_length(const wchar_t *code) {
bool found = false;
if (cur_term != NULL) {
// Detect these terminfo color escapes with parameter value 0..16, all of which don't move
// Detect these terminfo color escapes with parameter value up to max_colors-1, all of which
// don't move
// the cursor.
char *const esc[] = {
set_a_foreground, set_a_background, set_foreground, set_background,
@@ -214,7 +215,7 @@ size_t escape_code_length(const wchar_t *code) {
for (size_t p = 0; p < sizeof esc / sizeof *esc && !found; p++) {
if (!esc[p]) continue;
for (size_t k = 0; k < 8; k++) {
for (short k = 0; k < max_colors; k++) {
size_t len = try_sequence(tparm(esc[p], k), code);
if (len) {
resulting_length = len;
@@ -388,13 +389,12 @@ static void s_desired_append_char(screen_t *s, wchar_t b, int c, int indent, siz
int line_no = s->desired.cursor.y;
if (b == L'\n') {
int i;
// Current line is definitely hard wrapped.
s->desired.create_line(s->desired.line_count());
s->desired.line(s->desired.cursor.y).is_soft_wrapped = false;
s->desired.cursor.y++;
s->desired.cursor.x = 0;
for (i = 0; i < prompt_width + indent * INDENT_STEP; i++) {
for (size_t i = 0; i < prompt_width + indent * INDENT_STEP; i++) {
s_desired_append_char(s, L' ', 0, indent, prompt_width);
}
} else if (b == L'\r') {
@@ -529,6 +529,7 @@ static void s_move(screen_t *s, data_buffer_t *b, int new_x, int new_y) {
/// Set the pen color for the terminal.
static void s_set_color(screen_t *s, data_buffer_t *b, highlight_spec_t c) {
UNUSED(s);
scoped_buffer_t scoped_buffer(b);
unsigned int uc = (unsigned int)c;
@@ -732,7 +733,7 @@ static void s_update(screen_t *scr, const wchar_t *left_prompt, const wchar_t *r
// avoid repeatedly outputting it.
const size_t shared_prefix = line_shared_prefix(o_line, s_line);
if (shared_prefix > 0) {
int prefix_width = fish_wcswidth(&o_line.text.at(0), shared_prefix);
size_t prefix_width = fish_wcswidth(&o_line.text.at(0), shared_prefix);
if (prefix_width > skip_remaining) skip_remaining = prefix_width;
}
@@ -754,7 +755,7 @@ static void s_update(screen_t *scr, const wchar_t *left_prompt, const wchar_t *r
// Skip over skip_remaining width worth of characters.
size_t j = 0;
for (; j < o_line.size(); j++) {
int width = fish_wcwidth_min_0(o_line.char_at(j));
size_t width = fish_wcwidth_min_0(o_line.char_at(j));
if (skip_remaining < width) break;
skip_remaining -= width;
current_width += width;
@@ -772,7 +773,8 @@ static void s_update(screen_t *scr, const wchar_t *left_prompt, const wchar_t *r
// the screen after we output into the last column, it can erase the last character due
// to the sticky right cursor. If we clear the screen too early, we can defeat soft
// wrapping.
if (j + 1 == screen_width && should_clear_screen_this_line && !has_cleared_screen) {
if (j + 1 == (size_t)screen_width && should_clear_screen_this_line &&
!has_cleared_screen) {
s_move(scr, &output, current_width, (int)i);
s_write_mbs(&output, clr_eos);
has_cleared_screen = true;
@@ -893,6 +895,7 @@ static screen_layout_t compute_layout(screen_t *s, size_t screen_width,
const wcstring &left_prompt_str,
const wcstring &right_prompt_str, const wcstring &commandline,
const wcstring &autosuggestion_str, const int *indent) {
UNUSED(s);
screen_layout_t result = {};
// Start by ensuring that the prompts themselves can fit.

View File

@@ -192,6 +192,8 @@ const wchar_t *signal_get_desc(int sig) {
/// Standard signal handler.
static void default_handler(int signal, siginfo_t *info, void *context) {
UNUSED(info);
UNUSED(context);
if (event_is_signal_observed(signal)) {
event_fire_signal(signal);
}
@@ -200,6 +202,8 @@ static void default_handler(int signal, siginfo_t *info, void *context) {
#ifdef SIGWINCH
/// Respond to a winch signal by checking the terminal size.
static void handle_winch(int sig, siginfo_t *info, void *context) {
UNUSED(info);
UNUSED(context);
common_handle_winch(sig);
default_handler(sig, 0, 0);
}
@@ -208,6 +212,8 @@ static void handle_winch(int sig, siginfo_t *info, void *context) {
/// Respond to a hup signal by exiting, unless it is caught by a shellscript function, in which case
/// we do nothing.
static void handle_hup(int sig, siginfo_t *info, void *context) {
UNUSED(info);
UNUSED(context);
if (event_is_signal_observed(SIGHUP)) {
default_handler(sig, 0, 0);
} else {
@@ -217,6 +223,9 @@ static void handle_hup(int sig, siginfo_t *info, void *context) {
/// Handle sigterm. The only thing we do is restore the front process ID, then die.
static void handle_term(int sig, siginfo_t *info, void *context) {
UNUSED(sig);
UNUSED(info);
UNUSED(context);
restore_term_foreground_process_group();
signal(SIGTERM, SIG_DFL);
raise(SIGTERM);
@@ -225,7 +234,7 @@ static void handle_term(int sig, siginfo_t *info, void *context) {
/// Interactive mode ^C handler. Respond to int signal by setting interrupted-flag and stopping all
/// loops and conditionals.
static void handle_int(int sig, siginfo_t *info, void *context) {
reader_handle_int(sig);
reader_handle_sigint();
default_handler(sig, info, context);
}

View File

@@ -31,7 +31,7 @@
// We can tweak the following typedef to allow us to simulate Windows-style 16 bit wchar's on Unix.
typedef wchar_t utf8_wchar_t;
#define UTF8_WCHAR_MAX ((size_t)std::numeric_limits<utf8_wchar_t>::max())
#define UTF8_WCHAR_MAX (wchar_t) std::numeric_limits<utf8_wchar_t>::max()
typedef std::basic_string<utf8_wchar_t> utf8_wstring_t;
@@ -197,7 +197,7 @@ static size_t utf8_to_wchar_internal(const char *in, size_t insize, utf8_wstring
}
// Does the sequence header tell us truth about length?
if (lim - p <= n - 1) {
if ((size_t)(lim - p) <= n - 1) {
if ((flags & UTF8_IGNORE_ERROR) == 0) return 0;
n = 1;
continue; // skip
@@ -238,7 +238,7 @@ static size_t utf8_to_wchar_internal(const char *in, size_t insize, utf8_wstring
if (skip) {
total--;
} else if (out_val > UTF8_WCHAR_MAX) {
} else if (out_val > (uint32_t)UTF8_WCHAR_MAX) {
// wchar_t is UCS-2, but the UTF-8 specified an astral character.
return 0;
} else {
@@ -304,8 +304,7 @@ static size_t wchar_to_utf8_internal(const utf8_wchar_t *in, size_t insize, char
total += n;
if (out == NULL) continue;
if (lim - p <= n - 1) return 0; // no space left
if (size_t(lim - p) <= n - 1) return 0; // no space left
// Extract the wchar_t as big-endian. If wchar_t is UCS-16, the first two bytes will be 0.
unsigned char oc[4];

View File

@@ -348,7 +348,7 @@ wchar_t *wrealpath(const wcstring &pathname, wchar_t *resolved_path) {
if (narrow_res) {
real_path.append(narrow_res);
} else {
ssize_t pathsep_idx = narrow_path.rfind('/');
size_t pathsep_idx = narrow_path.rfind('/');
if (pathsep_idx == 0) {
// If the only pathsep is the first character then it's an absolute path with a
// single path component and thus doesn't need conversion.
@@ -548,7 +548,7 @@ file_id_t file_id_t::file_id_from_stat(const struct stat *buf) {
result.change_seconds = buf->st_ctime;
result.mod_seconds = buf->st_mtime;
#if STAT_HAVE_NSEC
#ifdef HAVE_STRUCT_STAT_ST_CTIME_NSEC
result.change_nanoseconds = buf->st_ctime_nsec;
result.mod_nanoseconds = buf->st_mtime_nsec;
#elif defined(__APPLE__)

View File

@@ -2,15 +2,15 @@ history: Invalid combination of options,
you cannot do both 'search' and 'merge' in the same invocation
history: you cannot use any options with the clear command
history: you cannot use any options with the merge command
history: save command expected 0 args, got 1
history: save expected 0 args, got 1
history: you cannot use any options with the save command
history: you cannot use any options with the clear command
history: merge command expected 0 args, got 1
history: clear command expected 0 args, got 2
history: merge expected 0 args, got 1
history: clear expected 0 args, got 2
history: you cannot use any options with the clear command
history: you cannot use any options with the merge command
history: save command expected 0 args, got 1
history: save expected 0 args, got 1
history: you cannot use any options with the clear command
history: you cannot use any options with the merge command
@@ -18,7 +18,7 @@ history: Invalid combination of options,
you cannot do both 'search' and 'merge' in the same invocation
history: you cannot use any options with the save command
history: you cannot use any options with the clear command
history: merge command expected 0 args, got 1
history: clear command expected 0 args, got 2
history: merge expected 0 args, got 1
history: clear expected 0 args, got 2
history: you cannot use any options with the save command
history: you cannot use any options with the merge command

View File

@@ -112,8 +112,10 @@ expect_prompt -re {history search --exact 'echo hell'\r\n} {
# ==========
# Delete a single command we recently ran.
send "history delete 'echo hello'\r"
expect_prompt -re {history delete 'echo hello'\r\n} {
send "history delete -e -C 'echo hello'\r"
expect -re {history delete -e -C 'echo hello'\r\n}
send "echo count hello (history search -e -C 'echo hello' | wc -l | string trim)\r"
expect -re {\r\ncount hello 0\r\n} {
puts "history function explicit exact delete 'echo hello' succeeded"
} unmatched {
puts stderr "history function explicit exact delete 'echo hello' failed"
@@ -130,24 +132,20 @@ expect -re {\[2\] echo hello again\r\n\r\n}
expect -re {Enter nothing to cancel.*\r\nEnter "all" to delete all the matching entries\.\r\n}
expect -re {Delete which entries\? >}
send "1\r"
expect_prompt -re {Deleting history entry 1: "echo hello AGAIN"\r\n} {
puts "history function explicit prefix delete 'echo hello' succeeded"
} unmatched {
puts stderr "history function explicit prefix delete 'echo hello' failed"
}
expect -re {Deleting history entry 1: "echo hello AGAIN"\r\n}
# Verify that the deleted history entry is gone and the other one that matched
# the prefix search above is still there.
send "history search --exact 'echo hello again'\r"
expect_prompt -re {\r\necho hello again\r\n} {
send "echo count AGAIN (history search -e -C 'echo hello AGAIN' | wc -l | string trim)\r"
expect -re {\r\ncount AGAIN 0\r\n} {
puts "history function explicit prefix delete 'echo hello AGAIN' succeeded"
} unmatched {
puts stderr "history function explicit prefix delete 'echo hello AGAIN' failed"
}
send "echo count again (history search -e -C 'echo hello again' | wc -l | string trim)\r"
expect -re {\r\ncount again 1\r\n} {
puts "history function explicit exact search 'echo hello again' succeeded"
} unmatched {
puts stderr "history function explicit exact search 'echo hello again' failed"
}
send "history search --exact 'echo hello AGAIN'\r"
expect_prompt -re {\r\necho hello AGAIN\r\n} {
puts stderr "history function explicit exact search 'echo hello AGAIN' found the entry"
} unmatched {
puts "history function explicit exact search 'echo hello AGAIN' failed to find the entry"
}

View File

@@ -7,6 +7,5 @@ history function explicit exact search 'echo goodbye' succeeded
history function explicit exact search 'echo hello' succeeded
history function explicit exact search 'echo hell' succeeded
history function explicit exact delete 'echo hello' succeeded
history function explicit prefix delete 'echo hello' succeeded
history function explicit prefix delete 'echo hello AGAIN' succeeded
history function explicit exact search 'echo hello again' succeeded
history function explicit exact search 'echo hello AGAIN' failed to find the entry