From 3044697baa8e098a31f8049194d7cf1890363cb2 Mon Sep 17 00:00:00 2001
From: ridiculousfish
Date: Sat, 5 Mar 2016 19:02:50 -0800
Subject: [PATCH 001/363] Prefer the first, not last, of any env var duplicates
If envp contains duplicate environment variables, use the
first value, not the last value. Fixes #2784.
---
src/env.cpp | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/env.cpp b/src/env.cpp
index e6deec52a..28ea51b05 100644
--- a/src/env.cpp
+++ b/src/env.cpp
@@ -449,12 +449,16 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
is to insert valid data
*/
- /*
- Import environment variables
- */
- for (char **p = (environ ? environ : __environ); p && *p; p++)
+ /* Import environment variables. Walk backwards so that the first one out of any duplicates wins (#2784) */
+ const char * const * envp = (environ ? environ : __environ);
+ size_t i = 0;
+ while (envp && envp[i])
{
- const wcstring key_and_val = str2wcstring(*p); //like foo=bar
+ i++;
+ }
+ while (i--)
+ {
+ const wcstring key_and_val = str2wcstring(envp[i]); //like foo=bar
size_t eql = key_and_val.find(L'=');
if (eql == wcstring::npos)
{
From a37d4d809e067e54dfaec74888bd668f1a1727d1 Mon Sep 17 00:00:00 2001
From: ridiculousfish
Date: Sat, 5 Mar 2016 19:07:00 -0800
Subject: [PATCH 002/363] Save a few string allocations when importing
environment variables
---
src/env.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/env.cpp b/src/env.cpp
index 28ea51b05..c24280bcc 100644
--- a/src/env.cpp
+++ b/src/env.cpp
@@ -450,6 +450,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
*/
/* Import environment variables. Walk backwards so that the first one out of any duplicates wins (#2784) */
+ wcstring key, val;
const char * const * envp = (environ ? environ : __environ);
size_t i = 0;
while (envp && envp[i])
@@ -468,9 +469,9 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
}
else
{
- wcstring key = key_and_val.substr(0, eql);
+ key.assign(key_and_val, 0, eql);
if (is_read_only(key) || is_electric(key)) continue;
- wcstring val = key_and_val.substr(eql + 1);
+ val.assign(key_and_val, eql + 1, wcstring::npos);
if (variable_is_colon_delimited_array(key))
{
std::replace(val.begin(), val.end(), L':', ARRAY_SEP);
From 6bee85fefa968a632287d5830be6023b90b88068 Mon Sep 17 00:00:00 2001
From: ridiculousfish
Date: Sat, 5 Mar 2016 21:50:05 -0800
Subject: [PATCH 003/363] expand_string should not return any results on error
Fixes #2796
---
src/expand.cpp | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/expand.cpp b/src/expand.cpp
index 34e861f64..c2b4258c8 100644
--- a/src/expand.cpp
+++ b/src/expand.cpp
@@ -1908,13 +1908,15 @@ expand_error_t expand_string(const wcstring &input, std::vector *o
output_storage.clear();
}
- /* Hack to un-expand tildes (see #647) */
- if (!(flags & EXPAND_SKIP_HOME_DIRECTORIES))
+ if (total_result != EXPAND_ERROR)
{
- unexpand_tildes(input, &completions);
+ /* Hack to un-expand tildes (see #647) */
+ if (!(flags & EXPAND_SKIP_HOME_DIRECTORIES))
+ {
+ unexpand_tildes(input, &completions);
+ }
+ out_completions->insert(out_completions->end(), completions.begin(), completions.end());
}
-
- out_completions->insert(out_completions->end(), completions.begin(), completions.end());
return total_result;
}
From ed4b78918a944fe3b3a1e05ac553e89d5f1fa411 Mon Sep 17 00:00:00 2001
From: David Adam
Date: Sun, 6 Mar 2016 19:24:02 +0800
Subject: [PATCH 004/363] fish.spec: dependency on net-tools/hostname depending
on platform
Closes #2190.
[ci skip]
---
fish.spec.in | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/fish.spec.in b/fish.spec.in
index fda42790b..04006037d 100644
--- a/fish.spec.in
+++ b/fish.spec.in
@@ -14,10 +14,16 @@ BuildRequires: ncurses-devel gettext gcc-c++ autoconf
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Requires: bc
-Requires: python
+Requires: python
Requires: which
Requires: man
+%if 0%{?rhel_version} >= 700 || 0%{?centos_version} >= 700 || 0%{?fedora}
+Requires: hostname
+%else
+Requires: net-tools
+%endif
+
%description
fish is a shell geared towards interactive use. Its features are
From b4b52b82340985595949238966b68daa710c99b2 Mon Sep 17 00:00:00 2001
From: David Adam
Date: Sun, 6 Mar 2016 19:29:32 +0800
Subject: [PATCH 005/363] Don't set locale to en_US.UTF-8 unconditionally.
This is an unwise assumption, both for en_US and UTF-8; the fallback C
locale should be used instead.
---
etc/config.fish | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/etc/config.fish b/etc/config.fish
index 0683f40e6..f4126d360 100644
--- a/etc/config.fish
+++ b/etc/config.fish
@@ -8,15 +8,6 @@
if status --is-login
- #
- # Set some value for LANG if nothing was set before, and this is a
- # login shell.
- #
-
- if not set -q LANG >/dev/null
- set -gx LANG en_US.UTF-8
- end
-
# Check for i18n information in
# /etc/sysconfig/i18n
From f4c14b69a23e8a25c016b6ba65ef2f54b4833e6b Mon Sep 17 00:00:00 2001
From: David Adam
Date: Sun, 6 Mar 2016 21:29:09 +0800
Subject: [PATCH 006/363] Update dpkg completions to complete commonly used
options
Closes #2798.
---
share/completions/dpkg.fish | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/share/completions/dpkg.fish b/share/completions/dpkg.fish
index c199bdada..d60b6dbad 100644
--- a/share/completions/dpkg.fish
+++ b/share/completions/dpkg.fish
@@ -1,6 +1,19 @@
complete -c dpkg -s i -l install -d 'Install .deb package' -xa '(__fish_complete_suffix .deb)'
-complete -c dpkg -s r -l remove -d 'Remove package' -xa '(__fish_print_packages)'
-complete -c dpkg -s P -l purge -d 'Purge package' -xa '(__fish_print_packages)'
+complete -c dpkg -l unpack -d 'Unpack .deb package' -xa '(__fish_complete_suffix .deb)'
+complete -c dpkg -l configure -d 'Configure package' -xa '(dpkg-query -W -f \'${Package}\n\')'
+complete -c dpkg -s r -l remove -d 'Remove package' -xa '(dpkg-query -W -f \'${Package}\n\')'
+complete -c dpkg -s P -l purge -d 'Purge package' -xa '(dpkg-query -W -f \'${Package}\n\')'
+complete -c dpkg -s V -l verify -d 'Verify contents of package' -xa '(dpkg-query -W -f \'${Package}\n\')'
complete -c dpkg -l force-all -d 'Continue on all problems'
+# dpkg-deb options
+complete -c dpkg -s b -l build -d 'Build package from directory' -xa '(__fish_complete_directories (commandline -ct))'
+complete -c dpkg -s c -l contents -d 'List contents of .deb' -xa '(__fish_complete_suffix .deb)'
+complete -c dpkg -s I -l info -d 'Show .deb information' -xa '(__fish_complete_suffix .deb)'
+
+# dpkg-query options
+complete -c dpkg -s l -l list -d 'List packages matching pattern' -xa '(dpkg-query -W -f \'${Package}\n\')'
+complete -c dpkg -s L -l listfiles -d 'List contents of packages' -xa '(dpkg-query -W -f \'${Package}\n\')'
+complete -c dpkg -s s -l status -d 'Print status of package' -xa '(dpkg-query -W -f \'${Package}\n\')'
+complete -c dpkg -s S -l search -d 'Search for packages containing file'
From 5e09411340b347caf2f81dc65fc9d3a1fefac261 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Sun, 6 Mar 2016 15:23:30 +0100
Subject: [PATCH 007/363] Document more bind functions
Fixes #2534 as backward-kill-path-component is now documented.
---
doc_src/bind.txt | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/doc_src/bind.txt b/doc_src/bind.txt
index c56c5c9a7..813026c3b 100644
--- a/doc_src/bind.txt
+++ b/doc_src/bind.txt
@@ -53,6 +53,8 @@ The following parameters are available:
The following special input functions are available:
+- `accept-autosuggestion`, accept the current autosuggestion completely
+
- `backward-char`, moves one character to the left
- `backward-bigword`, move one whitespace-delimited word to the left
@@ -63,6 +65,8 @@ The following special input functions are available:
- `backward-kill-line`, move everything from the beginning of the line to the cursor to the killring
+- `backward-kill-path-component`, move one path component to the left of the cursor (everything from the last "/" or whitespace exclusive) to the killring
+
- `backward-kill-word`, move the word to the left of the cursor to the killring
- `backward-word`, move one word to the left
@@ -75,6 +79,8 @@ The following special input functions are available:
- `complete`, guess the remainder of the current token
+- `complete-and-search`, invoke the searchable pager on completion options
+
- `delete-char`, delete one character to the right of the cursor
- `delete-line`, delete the entire line
@@ -107,6 +113,12 @@ The following special input functions are available:
- `kill-word`, move the next word to the killring
+- `suppress-autosuggestion`, remove the current autosuggestion
+
+- `transpose-chars`, transpose two characters to the left of the cursor
+
+- `transpose-words`, transpose two words to the left of the cursor
+
- `upcase-word`, make the current word uppercase
- `yank`, insert the latest entry of the killring into the buffer
From 6a16bdb808b02977cc99f84b4adae420f99019d2 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Thu, 3 Mar 2016 15:36:17 -0800
Subject: [PATCH 008/363] assume getopt/getopt_long is available
There is no longer a good reason to detect whether or not getopt_long()
is available. All UNIX implementations we're likely to run on have it. And
if we ever find one that doesn't the right thing to do is not fallback to
getopt() but to include the getopt_long() source in our package like we
do with the pcre2 library. Since it's licensed under LGPL we can legally
do so if it becomes necessary.
This partially addresses issue #2790.
---
configure.ac | 37 -----------------------------------
src/fallback.cpp | 14 --------------
src/fallback.h | 47 ---------------------------------------------
src/fish.cpp | 26 ++++++++-----------------
src/fish_indent.cpp | 45 ++++++++++++++++++-------------------------
src/fish_tests.cpp | 8 --------
6 files changed, 27 insertions(+), 150 deletions(-)
diff --git a/configure.ac b/configure.ac
index fe8b3a73c..af4fc5aff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -752,43 +752,6 @@ else
AC_MSG_RESULT(no)
fi
-# Check if getopt_long exists and works
-AC_MSG_CHECKING([if getopt_long exists and works])
-AC_TRY_LINK(
- [
- #if HAVE_GETOPT_H
- #include
- #endif
- ],
- [
- static struct option
- long_options[] =
- {
- 0, 0, 0, 0
- }
- ;
- int opt = getopt_long( 0,
- 0,
- 0,
- long_options,
- 0 );
-
- ],
- have_working_getopt_long=yes,
- have_working_getopt_long=no
-)
-if test "$have_working_getopt_long" = yes; then
- AC_MSG_RESULT(yes)
- AC_DEFINE(
- [HAVE_WORKING_GETOPT_LONG],
- [1],
- [Define to 1 if getopt_long exists and works.]
- )
-else
- AC_MSG_RESULT(no)
-fi
-
-
# Check for Solaris curses tputs having fixed length parameter list.
AC_MSG_CHECKING([if we are using non varargs tparm.])
AC_COMPILE_IFELSE(
diff --git a/src/fallback.cpp b/src/fallback.cpp
index 6b4b8b0a9..7c5f84d23 100644
--- a/src/fallback.cpp
+++ b/src/fallback.cpp
@@ -1207,20 +1207,6 @@ int killpg(int pgr, int sig)
}
#endif
-#ifndef HAVE_WORKING_GETOPT_LONG
-
-int getopt_long(int argc,
- char * const argv[],
- const char *optstring,
- const struct option *longopts,
- int *longindex)
-{
- return getopt(argc, argv, optstring);
-}
-
-
-#endif
-
#ifndef HAVE_BACKTRACE
int backtrace(void **buffer, int size)
{
diff --git a/src/fallback.h b/src/fallback.h
index 7d3afa13b..e30444497 100644
--- a/src/fallback.h
+++ b/src/fallback.h
@@ -413,53 +413,6 @@ extern int _nl_msg_cat_cntr;
int killpg(int pgr, int sig);
#endif
-
-#ifndef HAVE_WORKING_GETOPT_LONG
-
-/**
- Struct describing a long getopt option
- */
-struct option
-{
- /**
- Name of option
- */
- const char *name;
- /**
- Flag
- */
- int has_arg;
- /**
- Flag
- */
- int *flag;
- /**
- Return value
- */
- int val;
-}
-;
-
-#ifndef no_argument
-#define no_argument 0
-#endif
-
-#ifndef required_argument
-#define required_argument 1
-#endif
-
-#ifndef optional_argument
-#define optional_argument 2
-#endif
-
-int getopt_long(int argc,
- char * const argv[],
- const char *optstring,
- const struct option *longopts,
- int *longindex);
-
-#endif
-
#ifndef HAVE_SYSCONF
#define _SC_ARG_MAX 1
diff --git a/src/fish.cpp b/src/fish.cpp
index 916102321..048c9cbe3 100644
--- a/src/fish.cpp
+++ b/src/fish.cpp
@@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#include "config.h"
#include
+#include
#include
#include
#include
@@ -39,15 +40,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#include // IWYU pragma: keep - suggests internal header
#include
#include
-
-#ifdef HAVE_GETOPT_H
-#include
-#endif
-
#include
#include "fallback.h" // IWYU pragma: keep
-
#include "common.h"
#include "reader.h"
#include "builtin.h"
@@ -72,11 +67,6 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#define PATH_MAX 1024
#endif
-/**
- The string describing the single-character options accepted by the main fish binary
-*/
-#define GETOPT_STRING "+hilnvc:p:d:"
-
/* If we are doing profiling, the filename to output to */
static const char *s_profiling_output_filename = NULL;
@@ -370,7 +360,8 @@ static int read_init(const struct config_paths_t &paths)
*/
static int fish_parse_opt(int argc, char **argv, std::vector *cmds)
{
- const struct option long_options[] =
+ const char *short_opts = "+hilnvc:p:d:";
+ const struct option long_opts[] =
{
{ "command", required_argument, NULL, 'c' },
{ "debug-level", required_argument, NULL, 'd' },
@@ -383,17 +374,15 @@ static int fish_parse_opt(int argc, char **argv, std::vector *cmds)
{ NULL, 0, NULL, 0 }
};
- while (1)
+ int opt;
+ while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1)
{
- int opt = getopt_long(argc, argv, GETOPT_STRING, long_options, NULL);
- if (opt == -1)
- break;
-
switch (opt)
{
case 0:
{
- break;
+ fwprintf(stderr, _(L"getopt_long() unexpectedly returned zero\n"));
+ exit_without_destructors(127);
}
case 'c':
@@ -462,6 +451,7 @@ static int fish_parse_opt(int argc, char **argv, std::vector *cmds)
default:
{
+ // We assume getopt_long() has already emitted a diagnostic msg.
exit_without_destructors(1);
}
diff --git a/src/fish_indent.cpp b/src/fish_indent.cpp
index 60ed23343..037d9b773 100644
--- a/src/fish_indent.cpp
+++ b/src/fish_indent.cpp
@@ -21,13 +21,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#include "config.h"
+#include
#include
#include
#include
#include
-#ifdef HAVE_GETOPT_H
-#include
-#endif
#include
#include
#include
@@ -297,40 +295,34 @@ int main(int argc, char *argv[])
output_type_ansi,
output_type_html
} output_type = output_type_plain_text;
-
- /* Whether to indent (true) or just reformat to one job per line (false) */
bool do_indent = true;
- while (1)
+ const char *short_opts = "+hvi";
+ const struct option long_opts[] =
{
- const struct option long_options[] =
- {
- { "no-indent", no_argument, 0, 'i' },
- { "help", no_argument, 0, 'h' },
- { "version", no_argument, 0, 'v' },
- { "html", no_argument, 0, 1 },
- { "ansi", no_argument, 0, 2 },
- { 0, 0, 0, 0 }
- };
-
- int opt_index = 0;
- int opt = getopt_long(argc, argv, "hvi", long_options, &opt_index);
- if (opt == -1)
- break;
+ { "no-indent", no_argument, NULL, 'i' },
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { "html", no_argument, NULL, 1 },
+ { "ansi", no_argument, NULL, 2 },
+ { NULL, 0, NULL, 0 }
+ };
+ int opt;
+ while ((opt = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1)
+ {
switch (opt)
{
case 0:
{
- break;
+ fwprintf(stderr, _(L"getopt_long() unexpectedly returned zero\n"));
+ exit_without_destructors(127);
}
case 'h':
{
print_help("fish_indent", 1);
- exit(0);
- assert(0 && "Unreachable code reached");
- break;
+ exit_without_destructors(0);
}
case 'v':
@@ -359,9 +351,10 @@ int main(int argc, char *argv[])
break;
}
- case '?':
+ default:
{
- exit(1);
+ // We assume getopt_long() has already emitted a diagnostic msg.
+ exit_without_destructors(1);
}
}
}
diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp
index bcfff0324..dfc346092 100644
--- a/src/fish_tests.cpp
+++ b/src/fish_tests.cpp
@@ -4,7 +4,6 @@
#include "config.h"
-
#include
#include
#include
@@ -24,20 +23,13 @@
#include
#include
#include
-
-#ifdef HAVE_GETOPT_H
-#include
-#endif
-
#include
-
#include
#include
#include
#include "fallback.h"
#include "util.h"
-
#include "common.h"
#include "proc.h"
#include "reader.h"
From 6288f89bf95273cbce8437cfd6466cf8fc80850b Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Sun, 6 Mar 2016 15:28:54 +0100
Subject: [PATCH 009/363] Move code in etc/config.fish to share/config.fish
instead add a bit of information on how fish's configuration works for
the admin to etc/config.fish.
This means that fish is fully functional without /etc, which might be nice for "stateless" systems.
---
etc/config.fish | 42 +++++++++++++-----------------------------
share/config.fish | 29 +++++++++++++++++++++++++++++
2 files changed, 42 insertions(+), 29 deletions(-)
diff --git a/etc/config.fish b/etc/config.fish
index f4126d360..9be6f0728 100644
--- a/etc/config.fish
+++ b/etc/config.fish
@@ -1,30 +1,14 @@
-#
-# Init file for fish
-#
-
-#
-# Some things should only be done for login terminals
-#
-
-if status --is-login
-
- # Check for i18n information in
- # /etc/sysconfig/i18n
-
- if test -f /etc/sysconfig/i18n
- eval (cat /etc/sysconfig/i18n |sed -ne 's/^\([a-zA-Z]*\)=\(.*\)$/set -gx \1 \2;/p')
- end
-
- #
- # Put linux consoles in unicode mode.
- #
-
- if test "$TERM" = linux
- if expr "$LANG" : ".*\.[Uu][Tt][Ff].*" >/dev/null
- if which unicode_start >/dev/null
- unicode_start
- end
- end
- end
-end
+# Put system-wide fish configuration entries here
+# or in .fish files in conf.d/
+# Files in conf.d can be overridden by the user
+# by files with the same name in $XDG_CONFIG_HOME/fish/conf.d
+# This file is run by all fish instances.
+# To include configuration only for login shells, use
+# if status --is-login
+# ...
+# end
+# To include configuration only for interactive shells, use
+# if status --is-interactiv
+# ...
+# end
diff --git a/share/config.fish b/share/config.fish
index b7a461c3e..9ed3250a7 100644
--- a/share/config.fish
+++ b/share/config.fish
@@ -176,3 +176,32 @@ if not set -q __fish_init_2_3_0
set fish_user_abbreviations $fab
set -U __fish_init_2_3_0
end
+
+#
+# Some things should only be done for login terminals
+# This used to be in etc/config.fish - keep it here to keep the semantics
+#
+
+if status --is-login
+
+ # Check for i18n information in
+ # /etc/sysconfig/i18n
+
+ if test -f /etc/sysconfig/i18n
+ string match -r '^[a-zA-Z]*=.*' < /etc/sysconfig/i18n | while read -l line
+ set -gx (string split '=' -m 1 -- $line | string replace -ra '"([^"]+)"' '$1' | string replace -ra "'([^']+)'" '$1')
+ end
+ end
+
+ #
+ # Put linux consoles in unicode mode.
+ #
+
+ if test "$TERM" = linux
+ if string match -qir '\.UTF' -- $LANG
+ if command -s unicode_start >/dev/null
+ unicode_start
+ end
+ end
+ end
+end
From 540bdfcb026dfadf8d6fc8bde91cddc886b2c677 Mon Sep 17 00:00:00 2001
From: lordlycastle
Date: Thu, 10 Mar 2016 15:35:39 +0000
Subject: [PATCH 010/363] date and uniq completions for OS X.
---
share/completions/date.fish | 33 +++++++++++++++++++++-----------
share/completions/uniq.fish | 38 ++++++++++++++++++++++---------------
2 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/share/completions/date.fish b/share/completions/date.fish
index 1c93f2352..b7725f199 100644
--- a/share/completions/date.fish
+++ b/share/completions/date.fish
@@ -1,11 +1,22 @@
-complete -c date -s d -l date --description "Display date described by string" -x
-complete -c date -s f -l file --description "Display date for each line in file" -r
-complete -c date -s I -l iso-8601 --description "Output in ISO 8601 format" -x -a "date hours minutes seconds"
-complete -c date -s s -l set --description "Set time" -x
-complete -c date -s R -l rfc-2822 --description "Output RFC-2822 compliant date string"
-complete -c date -s r -l reference --description "Display the last modification time of file" -r
-complete -c date -s u -l utc --description "Print or set Coordinated Universal Time"
-complete -c date -l universal --description "Print or set Coordinated Universal Time"
-complete -c date -s h -l help --description "Display help and exit"
-complete -c date -s v -l version --description "Display version and exit"
-
+if date --version > /dev/null ^ /dev/null
+ complete -c date -s d -l date --description "Display date described by string" -x
+ complete -c date -s f -l file --description "Display date for each line in file" -r
+ complete -c date -s I -l iso-8601 --description "Output in ISO 8601 format" -x -a "date hours minutes seconds"
+ complete -c date -s s -l set --description "Set time" -x
+ complete -c date -s R -l rfc-2822 --description "Output RFC-2822 compliant date string"
+ complete -c date -s r -l reference --description "Display the last modification time of file" -r
+ complete -c date -s u -l utc --description "Print or set Coordinated Universal Time"
+ complete -c date -l universal --description "Print or set Coordinated Universal Time"
+ complete -c date -s h -l help --description "Display help and exit"
+ complete -c date -s v -l version --description "Display version and exit"
+else # OS X
+ complete -c date -s d -d 'Set the kernel\'s value for daylight saving time' -x
+ complete -c date -s f -d 'Use format string to parse the date provided rather than default format'
+ complete -c date -s j -d 'Do no try to set the date'
+ complete -c date -s n -d 'Set the time for current machine only in the local group'
+ complete -c date -s r -d 'Print date and time represented by SEC since Epoch' -x
+ complete -c date -s t -d 'Set system\'s value for MINUTES west of GMT'
+ complete -c date -s u -d 'Display or set the date int UTC time'
+ complete -c date -s v -d 'Adjust the time component backward(-)/forward(+) according to VAL' -x
+end
+
diff --git a/share/completions/uniq.fish b/share/completions/uniq.fish
index 0027d71fc..1e35c9c59 100644
--- a/share/completions/uniq.fish
+++ b/share/completions/uniq.fish
@@ -1,15 +1,23 @@
-complete -c uniq -s c -l count --description "Print number of occurences"
-complete -c uniq -s d -l repeated --description "Only print duplicates"
-complete -c uniq -s D -l all-repeated --description "Remove non-duplicate lines" -f -x -a "
- none\t'Remove none-duplicate lines'
- prepend\t'Remove non-duplicate lines and print an empty line before each non-duplicate'
- separate\t'Remove non-duplicate lines and print an empty line between each non-duplicate'
-"
-complete -c uniq -s f -l skip-fields --description "Avoid comparing first N fields" -r
-complete -c uniq -s i -l ignore-case --description "Case insensitive"
-complete -c uniq -s s -l skip-chars --description "Avoid comparing first N characters" -r
-complete -c uniq -s u -l unique --description "Only print unique lines"
-complete -c uniq -s w -l check-chars --description "Compare only specified number of characters" -r
-complete -c uniq -l help --description "Display help and exit"
-complete -c uniq -l version --description "Display version and exit"
-
+if uniq --version > /dev/null ^ /dev/null
+ complete -c uniq -s c -l count --description "Print number of occurences"
+ complete -c uniq -s d -l repeated --description "Only print duplicates"
+ complete -c uniq -s D -l all-repeated --description "Remove non-duplicate lines" -f -x -a "
+ none\t'Remove none-duplicate lines'
+ prepend\t'Remove non-duplicate lines and print an empty line before each non-duplicate'
+ separate\t'Remove non-duplicate lines and print an empty line between each non-duplicate'
+ "
+ complete -c uniq -s f -l skip-fields --description "Avoid comparing first N fields" -r
+ complete -c uniq -s i -l ignore-case --description "Case insensitive"
+ complete -c uniq -s s -l skip-chars --description "Avoid comparing first N characters" -r
+ complete -c uniq -s u -l unique --description "Only print unique lines"
+ complete -c uniq -s w -l check-chars --description "Compare only specified number of characters" -r
+ complete -c uniq -l help --description "Display help and exit"
+ complete -c uniq -l version --description "Display version and exit"
+else # OS X
+ complete -c uniq -s c -d 'Precede each output line with count of it\'s occurrence'
+ complete -c uniq -s d -d 'Only print duplicates'
+ complete -c uniq -s f -d 'Avoid comparing first N fields' -x
+ complete -c uniq -s s -d 'Avoid comparing fist N characters' -x
+ complete -c uniq -s u -d 'Only print unique lines'
+ complete -c uniq -s i -d 'Case insensitive comparision'
+end
From 46b9f263ac780ae6a921fc24611c75bbec92ebca Mon Sep 17 00:00:00 2001
From: Jeff Kowalski
Date: Sat, 12 Mar 2016 11:21:52 -0800
Subject: [PATCH 011/363] Handle return values from fchown
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The function fchown is annotated with warn_unused_result. As
formerly used in the code, it would emit a compiler warning
```warning: ignoring return value of ‘fchown’, declared with
attribute warn_unused_result [-Wunused-result]```
This commit notes the return value and emits appropriate error/logging
messages if the call fails, creating more traceable results and
satisfying the compiler.
---
src/env_universal_common.cpp | 9 +++++----
src/history.cpp | 5 ++++-
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp
index bee25a1ea..5cd9edb14 100644
--- a/src/env_universal_common.cpp
+++ b/src/env_universal_common.cpp
@@ -859,22 +859,23 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
success = this->write_to_fd(private_fd, private_file_path);
if (! success) UNIVERSAL_LOG("write_to_fd() failed");
}
-
+
if (success)
{
/* Ensure we maintain ownership and permissions (#2176) */
struct stat sbuf;
if (wstat(vars_path, &sbuf) >= 0)
{
- fchown(private_fd, sbuf.st_uid, sbuf.st_gid);
+ if (0 > fchown(private_fd, sbuf.st_uid, sbuf.st_gid))
+ UNIVERSAL_LOG("fchown() failed");
fchmod(private_fd, sbuf.st_mode);
}
-
+
/* Linux by default stores the mtime with low precision, low enough that updates that occur in quick succession may
result in the same mtime (even the nanoseconds field). So manually set the mtime of the new file to a high-precision
clock. Note that this is only necessary because Linux aggressively reuses inodes, causing the ABA problem; on other
platforms we tend to notice the file has changed due to a different inode (or file size!)
-
+
It's probably worth finding a simpler solution to this. The tests ran into this, but it's unlikely to affect users.
*/
#if HAVE_CLOCK_GETTIME && HAVE_FUTIMENS
diff --git a/src/history.cpp b/src/history.cpp
index 1bada96d3..022524c35 100644
--- a/src/history.cpp
+++ b/src/history.cpp
@@ -1453,7 +1453,10 @@ bool history_t::save_internal_via_rewrite()
if (wstat(new_name, &sbuf) >= 0)
{
/* Success */
- fchown(out_fd, sbuf.st_uid, sbuf.st_gid);
+ if (0 > fchown(out_fd, sbuf.st_uid, sbuf.st_gid))
+ {
+ debug(2, L"Error when changing ownership of history file");
+ }
fchmod(out_fd, sbuf.st_mode);
}
From a7012648fe64fe5e501a7439660684f93afcd60d Mon Sep 17 00:00:00 2001
From: Jeff Kowalski
Date: Sat, 12 Mar 2016 12:26:01 -0800
Subject: [PATCH 012/363] Improve error handling around fchown
Address the feedback from the prior commit:
- Change the sense of return value testing to match more common
comparison idiom
- Test result of fchmod as well as fchown
- Change sense of return value testing around wrename as well
- Include errno where possible in error message
---
src/env_universal_common.cpp | 5 +++--
src/history.cpp | 13 ++++++++-----
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp
index 5cd9edb14..a0b4ebfdc 100644
--- a/src/env_universal_common.cpp
+++ b/src/env_universal_common.cpp
@@ -866,9 +866,10 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
struct stat sbuf;
if (wstat(vars_path, &sbuf) >= 0)
{
- if (0 > fchown(private_fd, sbuf.st_uid, sbuf.st_gid))
+ if (fchown(private_fd, sbuf.st_uid, sbuf.st_gid) == -1)
UNIVERSAL_LOG("fchown() failed");
- fchmod(private_fd, sbuf.st_mode);
+ if (fchmod(private_fd, sbuf.st_mode) == -1)
+ UNIVERSAL_LOG("fchmod() failed");
}
/* Linux by default stores the mtime with low precision, low enough that updates that occur in quick succession may
diff --git a/src/history.cpp b/src/history.cpp
index 022524c35..75e426387 100644
--- a/src/history.cpp
+++ b/src/history.cpp
@@ -1453,16 +1453,19 @@ bool history_t::save_internal_via_rewrite()
if (wstat(new_name, &sbuf) >= 0)
{
/* Success */
- if (0 > fchown(out_fd, sbuf.st_uid, sbuf.st_gid))
+ if (fchown(out_fd, sbuf.st_uid, sbuf.st_gid) == -1)
{
- debug(2, L"Error when changing ownership of history file");
+ debug(2, L"Error %d when changing ownership of history file", errno);
+ }
+ if (fchmod(out_fd, sbuf.st_mode) == -1)
+ {
+ debug(2, L"Error %d when changing mode of history file", errno);
}
- fchmod(out_fd, sbuf.st_mode);
}
- if (0 > wrename(tmp_name, new_name))
+ if (wrename(tmp_name, new_name) == -1)
{
- debug(2, L"Error when renaming history file");
+ debug(2, L"Error %d when renaming history file", errno);
}
}
close(out_fd);
From f20e8420a8eb58c4e27509f624d7756d8078937d Mon Sep 17 00:00:00 2001
From: Andreas Nordal
Date: Sun, 13 Mar 2016 20:18:37 +0100
Subject: [PATCH 013/363] parse_execution.cpp: Remove line continuations
My IDE (Kdevelop 4.7.3) didn't tackle them.
---
src/parse_execution.cpp | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/src/parse_execution.cpp b/src/parse_execution.cpp
index 608857604..c54942878 100644
--- a/src/parse_execution.cpp
+++ b/src/parse_execution.cpp
@@ -1367,13 +1367,11 @@ parse_execution_result_t parse_execution_context_t::run_1_job(const parse_node_t
job_set_flag(j, JOB_FOREGROUND, ! tree.job_should_be_backgrounded(job_node));
- job_set_flag(j, JOB_TERMINAL, job_get_flag(j, JOB_CONTROL) \
- && (!is_subshell && !is_event));
+ job_set_flag(j, JOB_TERMINAL,
+ job_get_flag(j, JOB_CONTROL) && !is_subshell && !is_event);
- job_set_flag(j, JOB_SKIP_NOTIFICATION, is_subshell \
- || is_block \
- || is_event \
- || (!get_is_interactive()));
+ job_set_flag(j, JOB_SKIP_NOTIFICATION,
+ is_subshell || is_block || is_event || !get_is_interactive());
/* Tell the current block what its job is. This has to happen before we populate it (#1394) */
parser->current_block()->job = j;
From 19c13c72f69cd35449add4c07cf9dd6ff7ff0810 Mon Sep 17 00:00:00 2001
From: David Adam
Date: Fri, 18 Mar 2016 11:45:48 +0800
Subject: [PATCH 014/363] env_universal_common: use uid_t in geteuid checks
The u_int typedef fails to compile on all platforms (e.g. Windows). It
is part of the code imported from tmux.
Update it to the SUS-standard uid_t.
Closes #2821.
---
src/env_universal_common.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp
index a0b4ebfdc..71fb1667d 100644
--- a/src/env_universal_common.cpp
+++ b/src/env_universal_common.cpp
@@ -129,7 +129,7 @@ static int check_runtime_path(const char * path)
*/
struct stat statpath;
- u_int uid = geteuid();
+ uid_t uid = geteuid();
if (mkdir(path, S_IRWXU) != 0 && errno != EEXIST)
return errno;
From 03460a3928e7545ebef736b1c0be94e79734c725 Mon Sep 17 00:00:00 2001
From: David Adam
Date: Fri, 18 Mar 2016 11:45:48 +0800
Subject: [PATCH 015/363] env_universal_common: use uid_t in geteuid checks
The u_int typedef fails to compile on all platforms (e.g. Windows). It
is part of the code imported from tmux.
Update it to the SUS-standard uid_t.
Closes #2821.
---
src/env_universal_common.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp
index a0b4ebfdc..71fb1667d 100644
--- a/src/env_universal_common.cpp
+++ b/src/env_universal_common.cpp
@@ -129,7 +129,7 @@ static int check_runtime_path(const char * path)
*/
struct stat statpath;
- u_int uid = geteuid();
+ uid_t uid = geteuid();
if (mkdir(path, S_IRWXU) != 0 && errno != EEXIST)
return errno;
From 9f0417b587ac6cec7343e287c12886adc459e01c Mon Sep 17 00:00:00 2001
From: Owen Richardson
Date: Fri, 13 Nov 2015 06:06:35 +0000
Subject: [PATCH 016/363] make alt-L output respect multi-line prompts
Fixes #718
---
.../functions/__fish_list_current_token.fish | 42 ++++++++++---------
1 file changed, 23 insertions(+), 19 deletions(-)
diff --git a/share/functions/__fish_list_current_token.fish b/share/functions/__fish_list_current_token.fish
index a88978cc3..0a0f2dab1 100644
--- a/share/functions/__fish_list_current_token.fish
+++ b/share/functions/__fish_list_current_token.fish
@@ -1,22 +1,26 @@
-
-#
-# This function is bound to Alt-L, it is used to list the contents of
-# the directory under the cursor
-#
+# This function is typically bound to Alt-L, it is used to list the contents
+# of the directory under the cursor.
function __fish_list_current_token -d "List contents of token under the cursor if it is a directory, otherwise list the contents of the current directory"
- set val (eval echo (commandline -t))
- printf "\n"
- if test -d $val
- ls $val
- else
- set dir (dirname $val)
- if test $dir != . -a -d $dir
- ls $dir
- else
- ls
- end
- end
- commandline -f repaint
-end
+ set val (eval echo (commandline -t))
+ printf "\n"
+ if test -d $val
+ ls $val
+ else
+ set dir (dirname $val)
+ if test $dir != . -a -d $dir
+ ls $dir
+ else
+ ls
+ end
+ end
+ set -l line_count (count (fish_prompt))
+ if test $line_count -gt 1
+ for x in (seq 2 $line_count)
+ printf "\n"
+ end
+ end
+
+ commandline -f repaint
+end
From de0349399c5fcf0aa624e6607c17fd47fd5301bf Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Sun, 20 Mar 2016 12:17:00 +0100
Subject: [PATCH 017/363] robbyrussell prompt: Check for git/hg existence
Fixes #2826
---
share/tools/web_config/sample_prompts/robbyrussell.fish | 2 ++
1 file changed, 2 insertions(+)
diff --git a/share/tools/web_config/sample_prompts/robbyrussell.fish b/share/tools/web_config/sample_prompts/robbyrussell.fish
index 1c7fa748b..0a895ba4b 100644
--- a/share/tools/web_config/sample_prompts/robbyrussell.fish
+++ b/share/tools/web_config/sample_prompts/robbyrussell.fish
@@ -14,6 +14,7 @@ function fish_prompt
end
function _is_git_repo
+ type -q git; or return 1
git status -s >/dev/null ^/dev/null
end
@@ -26,6 +27,7 @@ function fish_prompt
end
function _is_hg_repo
+ type -q hg; or return 1
hg summary >/dev/null ^/dev/null
end
From dedc7f6f03cbdea41a851779af83db19893c5558 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Sun, 20 Mar 2016 12:20:39 +0100
Subject: [PATCH 018/363] Fix acpi check in nim prompt
---
share/tools/web_config/sample_prompts/nim.fish | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/share/tools/web_config/sample_prompts/nim.fish b/share/tools/web_config/sample_prompts/nim.fish
index 87837bf86..347af1d4d 100644
--- a/share/tools/web_config/sample_prompts/nim.fish
+++ b/share/tools/web_config/sample_prompts/nim.fish
@@ -47,16 +47,7 @@ function fish_prompt
set_color -o green
echo -n ]
- # Check if acpi exists
- if not set -q __fish_nim_prompt_has_acpi
- if type acpi > /dev/null
- set -g __fish_nim_prompt_has_acpi ''
- else
- set -g __fish_nim_prompt_has_acpi '' # empty string
- end
- end
-
- if test "$__fish_nim_prompt_has_acpi"
+ if type -q acpi
if [ (acpi -a 2> /dev/null | grep off) ]
echo -n '─['
set_color -o red
From 1828def8668dc95326a0f084e9c8370742656bc8 Mon Sep 17 00:00:00 2001
From: Cody Frazer
Date: Sun, 20 Mar 2016 10:10:51 -0500
Subject: [PATCH 019/363] Add `--no-index` option completion for `git diff`
---
share/completions/git.fish | 1 +
1 file changed, 1 insertion(+)
diff --git a/share/completions/git.fish b/share/completions/git.fish
index 5130ec34f..8ffdb071c 100644
--- a/share/completions/git.fish
+++ b/share/completions/git.fish
@@ -323,6 +323,7 @@ complete -f -c git -n '__fish_git_using_command commit' -a '(__fish_git_modified
complete -c git -n '__fish_git_needs_command' -a diff -d 'Show changes between commits, commit and working tree, etc'
complete -c git -n '__fish_git_using_command diff' -a '(__fish_git_ranges)' -d 'Branch'
complete -c git -n '__fish_git_using_command diff' -l cached -d 'Show diff of changes in the index'
+complete -c git -n '__fish_git_using_command diff' -l no-index -d 'Compare two paths on the filesystem'
# TODO options
### difftool
From fb0921249f4584e68699e336be249a655b9c8ede Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Sun, 20 Mar 2016 12:00:34 -0700
Subject: [PATCH 020/363] add \r equivalent binding
Add a binding that was overlooked by commit
d65c63322ef52443b372c3c49dbd3584596fed6b.
Fixes #2834
---
share/functions/fish_default_key_bindings.fish | 1 +
1 file changed, 1 insertion(+)
diff --git a/share/functions/fish_default_key_bindings.fish b/share/functions/fish_default_key_bindings.fish
index cac095d3d..8d86c7eec 100644
--- a/share/functions/fish_default_key_bindings.fish
+++ b/share/functions/fish_default_key_bindings.fish
@@ -16,6 +16,7 @@ function fish_default_key_bindings -d "Default (Emacs-like) key bindings for fis
bind $argv \t complete
bind $argv \e\n "commandline -i \n"
+ bind $argv \e\r "commandline -i \n"
bind $argv \e\[A up-or-search
bind $argv \e\[B down-or-search
From c2f1df1d4af0c7e633528cb4c8caa79ef04b0b5a Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Thu, 10 Mar 2016 18:17:39 -0800
Subject: [PATCH 021/363] fix handling of non-ASCII chars in C locale
The relevant standards allow the mbtowc/mbrtowc functions to reject
non-ASCII characters (i.e., chars with the high bit set) when the locale
is C or POSIX. The BSD libraries (e.g., on OS X) don't do this but
the GNU libraries (e.g., on Linux) do. Like most programs we need the
C/POSIX locales to allow arbitrary bytes. So explicitly check if we're
in a single-byte locale (which would also include ISO-8859 variants)
and simply pass-thru the chars without encoding or decoding.
Fixes #2802.
---
src/builtin.cpp | 47 ++++++++++++++--------------
src/common.cpp | 71 +++++++++++++++++++++++++++++-------------
src/env.cpp | 7 ++---
src/fallback.cpp | 72 ++++++++++++++++++++++---------------------
src/fallback.h | 20 ++----------
src/history.cpp | 19 +++++++-----
src/input_common.cpp | 11 ++++---
src/output.cpp | 58 +++++++++++++++++-----------------
src/wutil.cpp | 29 +++++++----------
src/wutil.h | 6 ++--
tests/c-locale.err | 0
tests/c-locale.in | 35 +++++++++++++++++++++
tests/c-locale.out | 4 +++
tests/c-locale.status | 1 +
14 files changed, 215 insertions(+), 165 deletions(-)
create mode 100644 tests/c-locale.err
create mode 100644 tests/c-locale.in
create mode 100644 tests/c-locale.out
create mode 100644 tests/c-locale.status
diff --git a/src/builtin.cpp b/src/builtin.cpp
index 4597b18e8..f4de72c73 100644
--- a/src/builtin.cpp
+++ b/src/builtin.cpp
@@ -1907,18 +1907,18 @@ static int builtin_echo(parser_t &parser, io_streams_t &streams, wchar_t **argv)
return STATUS_BUILTIN_OK;
}
-/** The pwd builtin. We don't respect -P to resolve symbolic links because we try to always resolve them. */
+// 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)
{
- wchar_t dir_path[4096];
- wchar_t *res = wgetcwd(dir_path, 4096);
- if (res == NULL)
+ wcstring res = wgetcwd();
+ if (res.empty())
{
return STATUS_BUILTIN_ERROR;
}
else
{
- streams.out.append(dir_path);
+ streams.out.append(res);
streams.out.push_back(L'\n');
return STATUS_BUILTIN_OK;
}
@@ -2699,9 +2699,8 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
while (1)
{
- int finished=0;
-
- wchar_t res=0;
+ int finished = 0;
+ wchar_t res = 0;
mbstate_t state = {};
while (!finished)
@@ -2713,24 +2712,26 @@ static int builtin_read(parser_t &parser, io_streams_t &streams, wchar_t **argv)
break;
}
- size_t sz = mbrtowc(&res, &b, 1, &state);
-
- switch (sz)
+ if (MB_CUR_MAX == 1) // single-byte locale
{
- case (size_t)(-1):
- memset(&state, '\0', sizeof(state));
- break;
+ res = (unsigned char)b;
+ finished = 1;
+ }
+ else {
+ size_t sz = mbrtowc(&res, &b, 1, &state);
+ switch (sz)
+ {
+ case (size_t)-1:
+ memset(&state, 0, sizeof(state));
+ break;
- case (size_t)(-2):
- break;
- case 0:
- finished = 1;
- break;
-
- default:
- finished=1;
- break;
+ case (size_t)-2:
+ break;
+ default:
+ finished = 1;
+ break;
+ }
}
}
diff --git a/src/common.cpp b/src/common.cpp
index 2aa76cc5c..a796baca1 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -103,8 +103,7 @@ int fgetws2(wcstring *s, FILE *f)
{
errno=0;
- c = getwc(f);
-
+ c = fgetwc(f);
if (errno == EILSEQ || errno == EINTR)
{
continue;
@@ -148,8 +147,19 @@ static wcstring str2wcs_internal(const char *in, const size_t in_len)
wcstring result;
result.reserve(in_len);
- mbstate_t state = {};
size_t in_pos = 0;
+
+ if (MB_CUR_MAX == 1) // single-byte locale, all values are legal
+ {
+ while (in_pos < in_len)
+ {
+ result.push_back((unsigned char)in[in_pos]);
+ in_pos++;
+ }
+ return result;
+ }
+
+ mbstate_t state = {};
while (in_pos < in_len)
{
wchar_t wc = 0;
@@ -165,12 +175,12 @@ static wcstring str2wcs_internal(const char *in, const size_t in_len)
{
use_encode_direct = true;
}
- else if (ret == (size_t)(-2))
+ else if (ret == (size_t)-2)
{
/* Incomplete sequence */
use_encode_direct = true;
}
- else if (ret == (size_t)(-1))
+ else if (ret == (size_t)-1)
{
/* Invalid data */
use_encode_direct = true;
@@ -266,9 +276,7 @@ std::string wcs2string(const wcstring &input)
std::string result;
result.reserve(input.size());
- mbstate_t state;
- memset(&state, 0, sizeof(state));
-
+ mbstate_t state = {};
char converted[MB_LEN_MAX + 1];
for (size_t i=0; i < input.size(); i++)
@@ -276,12 +284,22 @@ std::string wcs2string(const wcstring &input)
wchar_t wc = input[i];
if (wc == INTERNAL_SEPARATOR)
{
+ // Do nothing.
}
- else if ((wc >= ENCODE_DIRECT_BASE) &&
- (wc < ENCODE_DIRECT_BASE+256))
+ else if (wc >= ENCODE_DIRECT_BASE && wc < ENCODE_DIRECT_BASE + 256)
{
result.push_back(wc - ENCODE_DIRECT_BASE);
}
+ else if (MB_CUR_MAX == 1) // single-byte locale (C/POSIX/ISO-8859)
+ {
+ // If `wc` contains a wide character we emit a question-mark.
+ if (wc & ~0xFF)
+ {
+ wc = '?';
+ }
+ converted[0] = wc;
+ result.append(converted, 1);
+ }
else
{
memset(converted, 0, sizeof converted);
@@ -311,38 +329,47 @@ std::string wcs2string(const wcstring &input)
*/
static char *wcs2str_internal(const wchar_t *in, char *out)
{
- size_t res=0;
- size_t in_pos=0;
- size_t out_pos = 0;
- mbstate_t state;
-
CHECK(in, 0);
CHECK(out, 0);
- memset(&state, 0, sizeof(state));
+ size_t in_pos = 0;
+ size_t out_pos = 0;
+ mbstate_t state = {};
while (in[in_pos])
{
if (in[in_pos] == INTERNAL_SEPARATOR)
{
+ // Do nothing.
}
- else if ((in[in_pos] >= ENCODE_DIRECT_BASE) &&
- (in[in_pos] < ENCODE_DIRECT_BASE+256))
+ else if (in[in_pos] >= ENCODE_DIRECT_BASE &&
+ in[in_pos] < ENCODE_DIRECT_BASE + 256)
{
out[out_pos++] = in[in_pos]- ENCODE_DIRECT_BASE;
}
+ else if (MB_CUR_MAX == 1) // single-byte locale (C/POSIX/ISO-8859)
+ {
+ // If `wc` contains a wide character we emit a question-mark.
+ if (in[in_pos] & ~0xFF)
+ {
+ out[out_pos++] = '?';
+ }
+ else
+ {
+ out[out_pos++] = (unsigned char)in[in_pos];
+ }
+ }
else
{
- res = wcrtomb(&out[out_pos], in[in_pos], &state);
-
- if (res == (size_t)(-1))
+ size_t len = wcrtomb(&out[out_pos], in[in_pos], &state);
+ if (len == (size_t)-1)
{
debug(1, L"Wide character %d has no narrow representation", in[in_pos]);
memset(&state, 0, sizeof(state));
}
else
{
- out_pos += res;
+ out_pos += len;
}
}
in_pos++;
diff --git a/src/env.cpp b/src/env.cpp
index c24280bcc..56c9deb07 100644
--- a/src/env.cpp
+++ b/src/env.cpp
@@ -377,14 +377,13 @@ static void setup_path()
int env_set_pwd()
{
- wchar_t dir_path[4096];
- wchar_t *res = wgetcwd(dir_path, 4096);
- if (!res)
+ wcstring res = wgetcwd();
+ if (res.empty())
{
debug(0, _(L"Could not determine current working directory. Is your locale set correctly?"));
return 0;
}
- env_set(L"PWD", dir_path, ENV_EXPORT | ENV_GLOBAL);
+ env_set(L"PWD", res.c_str(), ENV_EXPORT | ENV_GLOBAL);
return 1;
}
diff --git a/src/fallback.cpp b/src/fallback.cpp
index 7c5f84d23..ed29f5de9 100644
--- a/src/fallback.cpp
+++ b/src/fallback.cpp
@@ -606,7 +606,7 @@ static FILE *fw_data;
static void fw_writer(wchar_t c)
{
- putwc(c, fw_data);
+ fputwc(c, fw_data);
}
/*
@@ -648,33 +648,30 @@ int wprintf(const wchar_t *filter, ...)
#endif
#ifndef HAVE_FGETWC
-
wint_t fgetwc(FILE *stream)
{
- wchar_t res=0;
- mbstate_t state;
- memset(&state, '\0', sizeof(state));
+ wchar_t res;
+ mbstate_t state = {};
while (1)
{
int b = fgetc(stream);
- char bb;
-
- int sz;
-
if (b == EOF)
+ {
return WEOF;
+ }
- bb=b;
-
- sz = mbrtowc(&res, &bb, 1, &state);
+ if (MB_CUR_MAX == 1) // single-byte locale, all values are legal
+ {
+ return b;
+ }
+ char bb = b;
+ size_t sz = mbrtowc(&res, &bb, 1, &state);
switch (sz)
{
case -1:
- memset(&state, '\0', sizeof(state));
return WEOF;
-
case -2:
break;
case 0:
@@ -683,35 +680,40 @@ wint_t fgetwc(FILE *stream)
return res;
}
}
-
}
-
-
-wint_t getwc(FILE *stream)
-{
- return fgetwc(stream);
-}
-
-
#endif
#ifndef HAVE_FPUTWC
-
wint_t fputwc(wchar_t wc, FILE *stream)
{
- int res;
- char s[MB_CUR_MAX+1];
- memset(s, 0, MB_CUR_MAX+1);
- wctomb(s, wc);
- res = fputs(s, stream);
- return res==EOF?WEOF:wc;
-}
+ int res = 0;
+ mbstate_t state = {};
+ char s[MB_CUR_MAX + 1] = {};
-wint_t putwc(wchar_t wc, FILE *stream)
-{
- return fputwc(wc, stream);
-}
+ if (MB_CUR_MAX == 1) // single-byte locale (C/POSIX/ISO-8859)
+ {
+ // If `wc` contains a wide character we emit a question-mark.
+ if (wc & ~0xFF)
+ {
+ wc = '?';
+ }
+ s[0] = (char)wc;
+ res = fputs(s, stream);
+ }
+ else
+ {
+ size_t len = wcrtomb(s, wc, &state);
+ if (len == (size_t)-1)
+ {
+ debug(1, L"Wide character %d has no narrow representation", wc);
+ }
+ else {
+ res = fputs(s, stream);
+ }
+ }
+ return res == EOF ? WEOF : wc;
+}
#endif
#ifndef HAVE_WCSTOK
diff --git a/src/fallback.h b/src/fallback.h
index e30444497..f3252c149 100644
--- a/src/fallback.h
+++ b/src/fallback.h
@@ -158,29 +158,13 @@ int vswprintf(wchar_t *out, size_t n, const wchar_t *filter, va_list va);
#endif
#ifndef HAVE_FGETWC
-/**
- Fallback implementation of fgetwc
-*/
+// Fallback implementation of fgetwc.
wint_t fgetwc(FILE *stream);
-
-/**
- Fallback implementation of getwc
-*/
-wint_t getwc(FILE *stream);
-
#endif
#ifndef HAVE_FPUTWC
-
-/**
- Fallback implementation of fputwc
-*/
+// Fallback implementation of fputwc.
wint_t fputwc(wchar_t wc, FILE *stream);
-/**
- Fallback implementation of putwc
-*/
-wint_t putwc(wchar_t wc, FILE *stream);
-
#endif
#ifndef HAVE_WCSTOK
diff --git a/src/history.cpp b/src/history.cpp
index 75e426387..a37d2b776 100644
--- a/src/history.cpp
+++ b/src/history.cpp
@@ -926,10 +926,9 @@ history_item_t history_t::decode_item_fish_1_x(const char *begin, size_t length)
{
const char *end = begin + length;
- const char *pos=begin;
-
- bool was_backslash = 0;
+ const char *pos = begin;
wcstring out;
+ bool was_backslash = false;
bool first_char = true;
bool timestamp_mode = false;
time_t timestamp = 0;
@@ -937,12 +936,18 @@ history_item_t history_t::decode_item_fish_1_x(const char *begin, size_t length)
while (1)
{
wchar_t c;
- mbstate_t state;
size_t res;
+ mbstate_t state = {};
- memset(&state, 0, sizeof(state));
-
- res = mbrtowc(&c, pos, end-pos, &state);
+ if (MB_CUR_MAX == 1) // single-byte locale
+ {
+ c = (unsigned char)*pos;
+ res = 1;
+ }
+ else
+ {
+ res = mbrtowc(&c, pos, end - pos, &state);
+ }
if (res == (size_t)-1)
{
diff --git a/src/input_common.cpp b/src/input_common.cpp
index ebe95fced..7c018c2d1 100644
--- a/src/input_common.cpp
+++ b/src/input_common.cpp
@@ -263,16 +263,17 @@ wchar_t input_common_readch(int timed)
while (1)
{
wint_t b = readb();
- char bb;
- size_t sz;
+ if (MB_CUR_MAX == 1) // single-byte locale, all values are legal
+ {
+ return (unsigned char)b;
+ }
if ((b >= R_NULL) && (b < R_NULL + 1000))
return b;
- bb=b;
-
- sz = mbrtowc(&res, &bb, 1, &state);
+ char bb = b;
+ size_t sz = mbrtowc(&res, &bb, 1, &state);
switch (sz)
{
diff --git a/src/output.cpp b/src/output.cpp
index 1707f4fb7..dbd97eb4b 100644
--- a/src/output.cpp
+++ b/src/output.cpp
@@ -386,32 +386,35 @@ int writeb(tputs_arg_t b)
int writech(wint_t ch)
{
- mbstate_t state;
- size_t i;
char buff[MB_LEN_MAX+1];
- size_t bytes;
+ size_t len;
- if ((ch >= ENCODE_DIRECT_BASE) &&
- (ch < ENCODE_DIRECT_BASE+256))
+ if (ch >= ENCODE_DIRECT_BASE && ch < ENCODE_DIRECT_BASE + 256)
{
buff[0] = ch - ENCODE_DIRECT_BASE;
- bytes=1;
+ len = 1;
+ }
+ else if (MB_CUR_MAX == 1) // single-byte locale (C/POSIX/ISO-8859)
+ {
+ // If `wc` contains a wide character we emit a question-mark.
+ if (ch & ~0xFF)
+ {
+ ch = '?';
+ }
+ buff[0] = ch;
+ len = 1;
}
else
{
- memset(&state, 0, sizeof(state));
- bytes= wcrtomb(buff, ch, &state);
-
- switch (bytes)
+ mbstate_t state = {};
+ len = wcrtomb(buff, ch, &state);
+ if (len == (size_t)-1)
{
- case (size_t)(-1):
- {
- return 1;
- }
+ return 1;
}
}
- for (i=0; i
Date: Sun, 20 Mar 2016 04:02:42 +0100
Subject: [PATCH 022/363] fix w, e (with a trick to cope with big-words)
---
share/functions/fish_vi_key_bindings.fish | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish
index 5debe6166..10551832f 100644
--- a/share/functions/fish_vi_key_bindings.fish
+++ b/share/functions/fish_vi_key_bindings.fish
@@ -79,10 +79,10 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind B backward-bigword
bind ge backward-word
bind gE backward-bigword
- bind w forward-word
- bind W forward-bigword
- bind e forward-word
- bind E forward-bigword
+ bind w forward-word forward-char
+ bind W forward-bigword forward-char
+ bind e forward-char forward-word backward-char
+ bind E forward-bigword backward-char
bind x delete-char
bind X backward-delete-char
From 168a156e5896fcaaf82a1b36587cde948f1765be Mon Sep 17 00:00:00 2001
From: Federico Ferri
Date: Sun, 20 Mar 2016 02:08:23 +0100
Subject: [PATCH 023/363] implement swap-selection-start-stop function
The swap-selection-start-stop function goes to the other end of the highlighted text, the equivalent of `o' for vim visual mode.
Add binding to the swap-selection-start-stop function, `o' when in visual
mode.
Document swap-selection-start-stop, begin-selection, end-selection, kill-selection.
---
doc_src/bind.txt | 8 ++++++++
share/functions/fish_vi_key_bindings.fish | 1 +
src/input.cpp | 2 ++
src/input_common.h | 1 +
src/reader.cpp | 11 +++++++++++
5 files changed, 23 insertions(+)
diff --git a/doc_src/bind.txt b/doc_src/bind.txt
index 813026c3b..9b1f34a09 100644
--- a/doc_src/bind.txt
+++ b/doc_src/bind.txt
@@ -75,6 +75,8 @@ The following special input functions are available:
- `beginning-of-line`, move to the beginning of the line
+- `begin-selection`, start selecting text
+
- `capitalize-word`, make the current word begin with a capital letter
- `complete`, guess the remainder of the current token
@@ -93,6 +95,8 @@ The following special input functions are available:
- `end-of-line`, move to the end of the line
+- `end-selection`, end selecting text
+
- `explain`, print a description of possible problems with the current command
- `forward-bigword`, move one whitespace-delimited word to the right
@@ -109,12 +113,16 @@ The following special input functions are available:
- `kill-line`, move everything from the cursor to the end of the line to the killring
+- `kill-selection`, move the selected text to the killring
+
- `kill-whole-line`, move the line to the killring
- `kill-word`, move the next word to the killring
- `suppress-autosuggestion`, remove the current autosuggestion
+- `swap-selection-start-stop`, go to the other end of the highlighted text without changing the selection
+
- `transpose-chars`, transpose two characters to the left of the cursor
- `transpose-words`, transpose two words to the left of the cursor
diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish
index 10551832f..de0f8bd6e 100644
--- a/share/functions/fish_vi_key_bindings.fish
+++ b/share/functions/fish_vi_key_bindings.fish
@@ -200,6 +200,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -M visual W forward-bigword
bind -M visual e forward-word
bind -M visual E forward-bigword
+ bind -M visual o swap-selection-start-stop force-repaint
for key in $eol_keys
bind -M visual $key end-of-line
diff --git a/src/input.cpp b/src/input.cpp
index c3e26815b..b4277724b 100644
--- a/src/input.cpp
+++ b/src/input.cpp
@@ -132,6 +132,7 @@ static const wchar_t * const name_arr[] =
L"suppress-autosuggestion",
L"accept-autosuggestion",
L"begin-selection",
+ L"swap-selection-start-stop",
L"end-selection",
L"kill-selection",
L"forward-jump",
@@ -242,6 +243,7 @@ static const wchar_t code_arr[] =
R_SUPPRESS_AUTOSUGGESTION,
R_ACCEPT_AUTOSUGGESTION,
R_BEGIN_SELECTION,
+ R_SWAP_SELECTION_START_STOP,
R_END_SELECTION,
R_KILL_SELECTION,
R_FORWARD_JUMP,
diff --git a/src/input_common.h b/src/input_common.h
index e605d18b7..8f4cdd52a 100644
--- a/src/input_common.h
+++ b/src/input_common.h
@@ -68,6 +68,7 @@ enum
R_SUPPRESS_AUTOSUGGESTION,
R_ACCEPT_AUTOSUGGESTION,
R_BEGIN_SELECTION,
+ R_SWAP_SELECTION_START_STOP,
R_END_SELECTION,
R_KILL_SELECTION,
R_FORWARD_JUMP,
diff --git a/src/reader.cpp b/src/reader.cpp
index a7e8ec7e5..50c8c93d4 100644
--- a/src/reader.cpp
+++ b/src/reader.cpp
@@ -4026,6 +4026,17 @@ const wchar_t *reader_readline(int nchars)
break;
}
+ case R_SWAP_SELECTION_START_STOP:
+ {
+ if (!data->sel_active) break;
+ size_t tmp = data->sel_begin_pos;
+ data->sel_begin_pos = data->command_line.position;
+ data->sel_start_pos = data->command_line.position;
+ editable_line_t *el = data->active_edit_line();
+ update_buff_pos(el, tmp);
+ break;
+ }
+
case R_END_SELECTION:
{
data->sel_active = false;
From 2e0205a7462c812559952c069f21aec58515785a Mon Sep 17 00:00:00 2001
From: Nyanpasu
Date: Tue, 22 Mar 2016 06:52:11 +0800
Subject: [PATCH 024/363] Add missing "Universal Variables" to tutorial.hdr
---
doc_src/tutorial.hdr | 1 +
1 file changed, 1 insertion(+)
diff --git a/doc_src/tutorial.hdr b/doc_src/tutorial.hdr
index 8877b0b4f..cb8427d4b 100644
--- a/doc_src/tutorial.hdr
+++ b/doc_src/tutorial.hdr
@@ -27,6 +27,7 @@
- $PATH
- Startup
- Autoloading Functions
+- Universal Variables
- Ready for more?
\htmlonly[block]
From a81bd697a8237ada71a24ebbf58fcf1b127e8f34 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Tue, 22 Mar 2016 11:09:36 +0100
Subject: [PATCH 025/363] Make reading ssh files case-insensitive
Fixes #2843
---
share/functions/__fish_print_hostnames.fish | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/share/functions/__fish_print_hostnames.fish b/share/functions/__fish_print_hostnames.fish
index 492954a49..385157768 100644
--- a/share/functions/__fish_print_hostnames.fish
+++ b/share/functions/__fish_print_hostnames.fish
@@ -26,9 +26,9 @@ function __fish_print_hostnames -d "Print a list of known hostnames"
if test -r $file
# Print hosts from system wide ssh configuration file
# Note the non-capturing group to avoid printing "name"
- string match -r '\s*Host(?:name)? \w.*' < $file | string replace -r '^\s*Host(?:name)?\s*(\S+)' '$1'
- set known_hosts $known_hosts (string match -r '^\s*UserKnownHostsFile|^\s*GlobalKnownHostsFile' <$file \
- | string replace -r '.*KnownHostsFile\s*' '')
+ string match -ri '\s*Host(?:name)? \w.*' < $file | string replace -ri '^\s*Host(?:name)?\s*(\S+)' '$1'
+ set known_hosts $known_hosts (string match -ri '^\s*UserKnownHostsFile|^\s*GlobalKnownHostsFile' <$file \
+ | string replace -ri '.*KnownHostsFile\s*' '')
end
end
for file in $known_hosts
From 2a4a539d8696bcd61bac5d558795c2eaa3f78c70 Mon Sep 17 00:00:00 2001
From: Andreas Nordal
Date: Tue, 15 Mar 2016 22:03:27 +0100
Subject: [PATCH 026/363] Fix memory leak, error message when failing to open
input file
The early return skipped all cleanup.
This problem is a case for the classic "goto fail" paradigm, but this
change instead makes a few adjustments to take advantage of a previously
unused level of indentation to conditionally execute the success path.
The error message now prints the filename instead of "open",
which should be more idiomatic.
Tip:
This patch makes sense if viewed with `git show --ignore-space-change`.
---
src/fish.cpp | 28 ++++++++++++----------------
1 file changed, 12 insertions(+), 16 deletions(-)
diff --git a/src/fish.cpp b/src/fish.cpp
index 048c9cbe3..bb898be5f 100644
--- a/src/fish.cpp
+++ b/src/fish.cpp
@@ -550,34 +550,30 @@ int main(int argc, char **argv)
}
reader_exit(0, 0);
}
+ else if (my_optind == argc)
+ {
+ // Interactive mode
+ check_running_fishd();
+ res = reader_read(STDIN_FILENO, empty_ios);
+ }
else
{
- if (my_optind == argc)
+ char *file = *(argv+(my_optind++));
+ int fd = open(file, O_RDONLY);
+ if (fd == -1)
{
- // Interactive mode
- check_running_fishd();
- res = reader_read(STDIN_FILENO, empty_ios);
+ perror(file);
}
else
{
- char **ptr;
- char *file = *(argv+(my_optind++));
- int i;
- int fd;
-
-
- if ((fd = open(file, O_RDONLY)) == -1)
- {
- wperror(L"open");
- return 1;
- }
-
// OK to not do this atomically since we cannot have gone multithreaded yet
set_cloexec(fd);
if (*(argv+my_optind))
{
wcstring sb;
+ char **ptr;
+ int i;
for (i=1,ptr = argv+my_optind; *ptr; i++, ptr++)
{
if (i != 1)
From de1258e09b3cd4605995297d400ff134fd68b226 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Wed, 23 Mar 2016 11:42:17 -0700
Subject: [PATCH 027/363] `fish --version` should write to stdout
When explicitly asking for the fish version string the information
should go to stdout rather than stderr. Also, there is no reason to use
exit_without_destructors() rather than exit() in that code path. We
actually want the side-effects of exit() such as flushing stdout and
there aren't any threads or other things that could cause a normal exit
to fail when that function is run.
---
src/fish.cpp | 13 +++++++------
1 file changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/fish.cpp b/src/fish.cpp
index bb898be5f..17cd1f16a 100644
--- a/src/fish.cpp
+++ b/src/fish.cpp
@@ -382,7 +382,7 @@ static int fish_parse_opt(int argc, char **argv, std::vector *cmds)
case 0:
{
fwprintf(stderr, _(L"getopt_long() unexpectedly returned zero\n"));
- exit_without_destructors(127);
+ exit(127);
}
case 'c':
@@ -405,8 +405,9 @@ static int fish_parse_opt(int argc, char **argv, std::vector *cmds)
}
else
{
- debug(0, _(L"Invalid value '%s' for debug level switch"), optarg);
- exit_without_destructors(1);
+ fwprintf(stderr, _(L"Invalid value '%s' for debug level switch"),
+ optarg);
+ exit(1);
}
break;
}
@@ -444,15 +445,15 @@ static int fish_parse_opt(int argc, char **argv, std::vector *cmds)
case 'v':
{
- fwprintf(stderr, _(L"%s, version %s\n"), PACKAGE_NAME,
+ fwprintf(stdout, _(L"%s, version %s\n"), PACKAGE_NAME,
get_fish_version());
- exit_without_destructors(0);
+ exit(0);
}
default:
{
// We assume getopt_long() has already emitted a diagnostic msg.
- exit_without_destructors(1);
+ exit(1);
}
}
From 9d2b53450ac038bcef7c62191770e9b85b6017f9 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Mon, 21 Mar 2016 16:51:39 -0700
Subject: [PATCH 028/363] limit size of cd history to 25 directories
The existing implementation grows the $dirprev array without bounds. Besides
causing what would appear to be a memory leak it also makes the nextd and
prevd commands more expensive than they need to be. It also makes it harder to
create a useful "menu" cd command.
In addition to implementing a reasonable limit on the size of the $dirprev
array I've reformatted the code using fish_indent.
Update the documentation to include mentions of the $dirprev and $dirnext
variables as well as the limit on how much directory history is kept.
Fixes 2836
---
doc_src/cd.txt | 2 +-
doc_src/dirh.txt | 2 ++
doc_src/nextd.txt | 1 +
doc_src/prevd.txt | 1 +
share/functions/cd.fish | 57 ++++++++++++++++++++++-------------------
5 files changed, 36 insertions(+), 27 deletions(-)
diff --git a/doc_src/cd.txt b/doc_src/cd.txt
index 3153c383d..a2cb95885 100644
--- a/doc_src/cd.txt
+++ b/doc_src/cd.txt
@@ -14,7 +14,7 @@ If `DIRECTORY` is a relative path, the paths found in the `CDPATH` environment v
Note that the shell will attempt to change directory without requiring `cd` if the name of a directory is provided (starting with `.`, `/` or `~`, or ending with `/`).
-Fish also ships a wrapper function around `cd` that understands `cd -` as changing to the previous directory. See `prevd`.
+Fish also ships a wrapper function around the builtin `cd` that understands `cd -` as changing to the previous directory. See also `prevd`. This wrapper function maintains a history of the 25 most recently visited directories in the `$dirprev` and `$dirnext` global variables.
\subsection cd-example Examples
diff --git a/doc_src/dirh.txt b/doc_src/dirh.txt
index d25b9c2ad..77e03e185 100644
--- a/doc_src/dirh.txt
+++ b/doc_src/dirh.txt
@@ -10,3 +10,5 @@ dirh
`dirh` prints the current directory history. The current position in the history is highlighted using the color defined in the `fish_color_history_current` environment variable.
`dirh` does not accept any parameters.
+
+Note that the `cd` command limits directory history to the 25 most recently visited directories. The history is stored in the `$dirprev` and `$dirnext` variables.
diff --git a/doc_src/nextd.txt b/doc_src/nextd.txt
index 8d7c90350..e02598a9b 100644
--- a/doc_src/nextd.txt
+++ b/doc_src/nextd.txt
@@ -11,6 +11,7 @@ nextd [ -l | --list ] [POS]
If the `-l` or `--list` flag is specified, the current directory history is also displayed.
+Note that the `cd` command limits directory history to the 25 most recently visited directories. The history is stored in the `$dirprev` and `$dirnext` variables which this command manipulates.
\subsection nextd-example Example
diff --git a/doc_src/prevd.txt b/doc_src/prevd.txt
index cd0c99ac4..f1e9e6cb3 100644
--- a/doc_src/prevd.txt
+++ b/doc_src/prevd.txt
@@ -11,6 +11,7 @@ prevd [ -l | --list ] [POS]
If the `-l` or `--list` flag is specified, the current history is also displayed.
+Note that the `cd` command limits directory history to the 25 most recently visited directories. The history is stored in the `$dirprev` and `$dirnext` variables which this command manipulates.
\subsection prevd-example Example
diff --git a/share/functions/cd.fish b/share/functions/cd.fish
index 8faa469d7..a1b6b2ac9 100644
--- a/share/functions/cd.fish
+++ b/share/functions/cd.fish
@@ -1,36 +1,41 @@
#
-# The following functions add support for a directory history
+# Wrap the builtin cd command to maintain directory history.
#
-
function cd --description "Change directory"
+ set -l MAX_DIR_HIST 25
- # Skip history in subshells
- if status --is-command-substitution
- builtin cd $argv
- return $status
- end
+ if test (count $argv) -gt 1
+ printf "%s\n" (_ "Too many args for cd command")
+ return 1
+ end
- # Avoid set completions
- set -l previous $PWD
+ # Skip history in subshells.
+ if status --is-command-substitution
+ builtin cd $argv
+ return $status
+ end
- if test $argv[1] = - ^/dev/null
- if test "$__fish_cd_direction" = next ^/dev/null
- nextd
- else
- prevd
- end
- return $status
- end
+ # Avoid set completions
+ set -l previous $PWD
- builtin cd $argv[1]
- set -l cd_status $status
+ if test "$argv" = "-"
+ if test "$__fish_cd_direction" = "next"
+ nextd
+ else
+ prevd
+ end
+ return $status
+ end
- if test $cd_status = 0 -a "$PWD" != "$previous"
- set -g dirprev $dirprev $previous
- set -e dirnext
- set -g __fish_cd_direction prev
- end
+ builtin cd $argv
+ set -l cd_status $status
- return $cd_status
+ if test $cd_status -eq 0 -a "$PWD" != "$previous"
+ set -q dirprev[$MAX_DIR_HIST]; and set -e dirprev[1]
+ set -g dirprev $dirprev $previous
+ set -e dirnext
+ set -g __fish_cd_direction prev
+ end
+
+ return $cd_status
end
-
From 516695ff21acb9160f403947840363dba5632f13 Mon Sep 17 00:00:00 2001
From: Bogdan Sinitsyn
Date: Fri, 18 Mar 2016 15:43:59 +0300
Subject: [PATCH 029/363] add yaourt completions
---
share/completions/yaourt.fish | 190 +++++++++++++++++++++++++++++++++-
1 file changed, 189 insertions(+), 1 deletion(-)
diff --git a/share/completions/yaourt.fish b/share/completions/yaourt.fish
index 9e19cca46..91a2401cd 100644
--- a/share/completions/yaourt.fish
+++ b/share/completions/yaourt.fish
@@ -1 +1,189 @@
-complete -c yaourt -w pacman
+# Completions for yaourt
+
+set -l progname yaourt
+complete -e -c $progname
+complete -c $progname -f
+
+set -l listinstalled "(pacman -Q | string replace ' ' \t)"
+# This might be an issue if another package manager is also installed (e.g. for containers)
+set -l listall "(__fish_print_packages)"
+set -l listrepos "(__fish_print_pacman_repos)"
+set -l listgroups "(pacman -Sg)\t'Package Group'"
+
+set -l hasopt '__fish_contains_opt -s B backup -s C -s G getpkgbuild -s P pkgbuild -s D database -s Q query -s R remove -s S sync -s U upgrade -s F files stats'
+set -l noopt "not $hasopt"
+
+set -l backup '__fish_contains_opt -s B backup'
+set -l clean '__fish_contains_opt -s C'
+set -l getpkgbuild '__fish_contains_opt -s G getpkgbuild'
+set -l pkgbuild '__fish_contains_opt -s P pkgbuild'
+set -l database '__fish_contains_opt -s D database'
+set -l query '__fish_contains_opt -s Q query'
+set -l remove '__fish_contains_opt -s R remove'
+set -l sync '__fish_contains_opt -s S sync'
+set -l upgrade '__fish_contains_opt -s U upgrade'
+set -l files '__fish_contains_opt -s F files'
+
+# HACK: We only need these three to coerce fish to stop file completion and complete options
+complete -c $progname -n $noopt -a "-D" -d "Modify the package database"
+complete -c $progname -n $noopt -a "-Q" -d "Query the package database"
+complete -c $progname -n $noopt -a "-C" -d "Manage .pac* files"
+# Primary operations
+complete -c $progname -s D -f -l database -n $noopt -d 'Modify the package database'
+complete -c $progname -s Q -f -l query -n $noopt -d 'Query the package database'
+complete -c $progname -s R -f -l remove -n $noopt -d 'Remove packages from the system'
+complete -c $progname -s S -f -l sync -n $noopt -d 'Synchronize packages'
+complete -c $progname -s T -f -l deptest -n $noopt -d 'Check dependencies'
+complete -c $progname -s U -f -l upgrade -n $noopt -d 'Upgrade or add a local package'
+complete -c $progname -s F -f -l files -n $noopt -d 'Query the files database'
+complete -c $progname -s V -f -l version -d 'Display version and exit'
+complete -c $progname -s h -f -l help -d 'Display help'
+# $progname operations
+complete -c $progname -n $noopt -s B -l backup -d "Backup or restore alpm local database"
+complete -c $progname -n $noopt -s C -f -d "Manage .pac* files"
+complete -c $progname -n $noopt -s G -f -l getpkgbuild -d "Get PKGBUILD from ABS or AUR"
+complete -c $progname -n $noopt -s P -l pkgbuild -d "Build package from PKGBUILD found in a local directory"
+complete -c $progname -n $noopt -f -l stats -d "Show some statistics about your packages"
+
+# General options
+# Only offer these once a command has been given so they get prominent display
+complete -c $progname -n $noopt -s b -l dbpath -d 'Alternative database location' -xa '(__fish_complete_directories)'
+complete -c $progname -n $hasopt -s r -l root -d 'Alternative installation root'
+complete -c $progname -n $hasopt -s v -l verbose -d 'Output more status messages'
+complete -c $progname -n $hasopt -l arch -d 'Alternate architecture' -f
+complete -c $progname -n $hasopt -l cachedir -d 'Alternative package cache location'
+complete -c $progname -n $hasopt -l config -d 'Alternate config file'
+complete -c $progname -n $hasopt -l debug -d 'Display debug messages' -f
+complete -c $progname -n $hasopt -l gpgdir -d 'GPG directory to verify signatures'
+complete -c $progname -n $hasopt -l hookdir -d 'Hook file directory'
+complete -c $progname -n $hasopt -l logfile -d 'Specify alternative log file'
+complete -c $progname -n $hasopt -l noconfirm -d 'Bypass any question' -f
+# General options (yaourt only)
+complete -c $progname -n $hasopt -l color -d 'Force color'
+complete -c $progname -n $hasopt -l force -d 'Force installation or updates'
+complete -c $progname -n $hasopt -l insecure -d 'Allow to perform "insecure" SSL connections'
+complete -c $progname -n $hasopt -l nocolor -d 'Disable color'
+complete -c $progname -n $hasopt -l confirm -d 'Always ask for confirmation'
+complete -c $progname -n $hasopt -l pager -d 'Use $PAGER to show search results'
+complete -c $progname -n $hasopt -l export -x -a '(__fish_complete_directories)' -d 'Export built packages and their sources to DIR'
+complete -c $progname -n $hasopt -l tmp -x -a '(__fish_complete_directories)' -d 'Use DIR as temporary folder'
+
+# Transaction options (sync, remove, upgrade)
+for condition in sync remove upgrade
+ complete -c $progname -n $$condition -s d -l nodeps -d 'Skip [all] dependency checks' -f
+ complete -c $progname -n $$condition -l dbonly -d 'Modify database entry only' -f
+ complete -c $progname -n $$condition -l noprogressbar -d 'Do not display progress bar' -f
+ complete -c $progname -n $$condition -l noscriptlet -d 'Do not execute install script' -f
+ complete -c $progname -n $$condition -s p -l print -d 'Dry run, only print targets' -f
+ complete -c $progname -n $$condition -l print-format -x -d 'Specify printf-like format' -f
+end
+
+# Database and upgrade options (database, sync, upgrade)
+for condition in database sync upgrade
+ complete -c $progname -n $$condition -l asdeps -d 'Mark PACKAGE as dependency' -f
+ complete -c $progname -n $$condition -l asexplicit -d 'Mark PACKAGE as explicitly installed' -f
+end
+
+# Upgrade options (sync, upgrade)
+for condition in sync upgrade
+ complete -c $progname -n $$condition -l force -d 'Bypass file conflict checks' -f
+ complete -c $progname -n $$condition -l ignore -d 'Ignore upgrade of PACKAGE' -xa "$listinstalled" -f
+ complete -c $progname -n $$condition -l ignoregroup -d 'Ignore upgrade of GROUP' -xa "$listgroups" -f
+ complete -c $progname -n $$condition -l needed -d 'Do not reinstall up-to-date targets' -f
+ complete -c $progname -n $$condition -l recursive -d 'Recursively reinstall all dependencies' -f
+end
+
+# Query and sync options
+for condition in query sync
+ complete -c $progname -n $$condition -s g -l groups -d 'Display all packages in GROUP' -xa "$listgroups" -f
+ complete -c $progname -n $$condition -s i -l info -d 'Display information on PACKAGE' -f
+ complete -c $progname -n $$condition -s q -l quiet -d 'Show less information' -f
+ complete -c $progname -n $$condition -s s -l search -r -d 'Search packages for regexp' -f
+ # Yaourt only
+ complete -c $progname -n $$condition -l conflicts -d 'Show packages that conflict with one of the targets'
+ complete -c $progname -n $$condition -l depends -d 'Show packages that depend on one of the targets'
+ complete -c $progname -n $$condition -l provides -d 'Show packages that provide one of the targets'
+ complete -c $progname -n $$condition -l replaces -d 'Show packages that replace one of the targets'
+ complete -c $progname -n $$condition -l nameonly -d 'Query the package names only'
+end
+
+# Query options
+complete -c $progname -n $query -s c -l changelog -d 'View the change log of PACKAGE' -f
+complete -c $progname -n $query -s d -l deps -d 'List only non-explicit packages (dependencies)' -f
+complete -c $progname -n $query -s e -l explicit -d 'List only explicitly installed packages' -f
+complete -c $progname -n $query -s k -l check -d 'Check if all files owned by PACKAGE are present' -f
+complete -c $progname -n $query -s l -l list -d 'List all files owned by PACKAGE' -f
+complete -c $progname -n $query -s m -l foreign -d 'List all packages not in the database' -f
+complete -c $progname -n $query -s o -l owns -r -d 'Search for the package that owns FILE' -xa '' -f
+complete -c $progname -n $query -s p -l file -d 'Apply the query to a package file, not package' -xa '' -f
+complete -c $progname -n $query -s t -l unrequired -d 'List only unrequired packages' -f
+complete -c $progname -n $query -s u -l upgrades -d 'List only out-of-date packages' -f
+complete -c $progname -n "$query" -d 'Installed package' -xa $listinstalled -f
+# Yaourt only query options
+# Backup file is always saved as pacman-$date.tar.bz2
+complete -c $progname -n $query -r -l backupfile -a '(__fish_complete_suffix tar.bz2)' -d 'Query FILE instead of alpm/aur'
+complete -c $progname -n $query -l date -d 'List queries result sorted by installation date'
+
+# Remove options
+complete -c $progname -n $remove -s c -l cascade -d 'Also remove packages depending on PACKAGE' -f
+complete -c $progname -n $remove -s n -l nosave -d 'Ignore file backup designations' -f
+complete -c $progname -n $remove -s s -l recursive -d 'Also remove dependencies of PACKAGE' -f
+complete -c $progname -n $remove -s u -l unneeded -d 'Only remove targets not required by PACKAGE' -f
+complete -c $progname -n "$remove" -d 'Installed package' -xa $listinstalled -f
+
+# Sync options
+complete -c $progname -n $sync -s c -l clean -d 'Remove [all] packages from cache'
+complete -c $progname -n $sync -s l -l list -xa "$listrepos" -d 'List all packages in REPOSITORY'
+complete -c $progname -n "$sync; and not __fish_contains_opt -s u sysupgrade" -s u -l sysupgrade -d 'Upgrade all packages that are out of date'
+complete -c $progname -n "$sync; and __fish_contains_opt -s u sysupgrade" -s u -l sysupgrade -d 'Also downgrade packages'
+complete -c $progname -n $sync -s w -l downloadonly -d 'Only download the target packages'
+complete -c $progname -n $sync -s y -l refresh -d 'Download fresh copy of the package list'
+complete -c $progname -n "$sync" -xa "$listall $listgroups"
+# Additional sync options
+complete -c $progname -n $sync -s a -l aur -d 'Also search in AUR database'
+complete -c $progname -n $sync -s A -l ignorearch -d 'Pass -A or --ignorearch option to makepkg'
+complete -c $progname -n $sync -l aur-url -x -d 'Specify a custom AUR url'
+set -l has_build_opt '__fish_contains_opt -s b build'
+complete -c $progname -n "$sync; and not $has_build_opt" -s b -l build -d 'Build from sources(AUR or ABS)'
+complete -c $progname -n "$sync; and $has_build_opt" -s b -l build -d 'Also build all dependencies'
+complete -c $progname -n $sync -l devel -d 'Search an update for devel packages'
+complete -c $progname -n $sync -l maintainer -d 'Search packages by maintainer instead of name (AUR only)'
+complete -c $progname -n $sync -l m-arg -d 'Pass additional options to makepkg'
+
+# Database options
+set -l has_db_opt '__fish_contains_opt asdeps asexplicit'
+complete -c $progname -n "$database; and not $has_db_opt" -xa --asdeps -d 'Mark PACKAGE as dependency'
+complete -c $progname -n "$database; and not $has_db_opt" -xa --asexplicit -d 'Mark PACKAGE as explicitly installed'
+complete -c $progname -n "$database; and not $has_db_opt" -s k -l check -d 'Check database validity'
+complete -c $progname -n "$has_db_opt; and $database" -xa "$listinstalled"
+
+# File options - since pacman 5
+set -l has_file_opt '__fish_contains_opt list search -s l -s s'
+complete -c $progname -n "$files; and not $has_file_opt" -xa --list -d 'List files owned by given packages'
+complete -c $progname -n "$files; and not $has_file_opt" -xa -l -d 'List files owned by given packages'
+complete -c $progname -n "$files; and not $has_file_opt" -xa --search -d 'Search packages for matching files'
+complete -c $progname -n "$files; and not $has_file_opt" -xa -s -d 'Search packages for matching files'
+complete -c $progname -n "$files" -s y -l refresh -d 'Refresh the files database' -f
+complete -c $progname -n "$files" -s l -l list -d 'List files owned by given packages' -xa $listall
+complete -c $progname -n "$files" -s s -l search -d 'Search packages for matching files'
+complete -c $progname -n "$files" -s o -l owns -d 'Search for packages that include the given files'
+complete -c $progname -n "$files" -s q -l quiet -d 'Show less information' -f
+complete -c $progname -n "$files" -l machinereadable -d 'Show in machine readable format' -f
+
+# Upgrade options
+# Theoretically, pacman reads packages in all formats that libarchive supports
+# In practice, it's going to be tar.xz or tar.gz
+# Using "pkg.tar.*" here would change __fish_complete_suffix's descriptions to "unknown"
+complete -c $progname -n "$upgrade" -xa '(__fish_complete_suffix pkg.tar.xz)' -d 'Package file'
+complete -c $progname -n "$upgrade" -xa '(__fish_complete_suffix pkg.tar.gz)' -d 'Package file'
+
+## Yaourt only stuff
+# Clean options
+set -l has_clean_opt '__fish_contains_opt clean'
+complete -c $progname -n "$clean; and not $has_clean_opt" -xa --clean -d 'Clean all these files'
+
+# pkgbuild options
+complete -c $progname -n $pkgbuild -s i -l install -d 'Also install the package'
+
+# getpkgbuild options
+complete -c $progname -n $getpkgbuild -xa "$listall"
From ad97a122c9093610ed0807553e6592a658e5a7a7 Mon Sep 17 00:00:00 2001
From: CharlonTank
Date: Thu, 24 Mar 2016 18:31:26 -0700
Subject: [PATCH 030/363] Update README.md
Add a command that instantly add the fish path to /etc/shells
---
README.md | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/README.md b/README.md
index bfbd790ef..fc549ef61 100644
--- a/README.md
+++ b/README.md
@@ -106,6 +106,10 @@ If you wish to use fish as your default shell, use the following command:
chsh will prompt you for your password, and change your default shell. Substitute "/usr/local/bin/fish" with whatever path to fish is in your /etc/shells file.
+Use the following command if you didn't already add your fish path to /etc/shells.
+
+ echo /usr/local/bin/fish | sudo tee -a /etc/shells
+
To switch your default shell back, you can run:
chsh -s /bin/bash
From 7accadc33f817a3e17c14c989a3b83f0d6737665 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Sat, 26 Mar 2016 19:16:17 +0100
Subject: [PATCH 031/363] Only read .fish files in the snippets directories
This would allow us to add a README and allows users to easily disable
something temporarily.
---
doc_src/index.hdr.in | 2 +-
share/config.fish | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index ed497a992..ff2d5ab36 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -1088,7 +1088,7 @@ function on_exit --on-process %self
end
\endfish
-Right after reading /usr/share/fish/config.fish and before reading /etc/fish/config.fish, fish will also read files in ~/.config/fish/conf.d/, /etc/fish/conf.d and /usr/share/fish/vendor_conf.d (the exact values depend on $XDG_CONFIG_HOME, $__fish_sysconfdir and $__fish_datadir). If there are files with the same name in two or all of these, fish will only attempt to read the first (skipping all files with that name if it is unreadable). ~/.config takes precedence over /etc/ which takes precedence over /usr. The path to the latter can also be gotten via `pkg-config` as "confdir", and is meant for third-party applications to integrate with fish.
+Right after reading /usr/share/fish/config.fish and before reading /etc/fish/config.fish, fish will also read files ending in ".fish" in ~/.config/fish/conf.d/, /etc/fish/conf.d and /usr/share/fish/vendor_conf.d (the exact values depend on $XDG_CONFIG_HOME, $__fish_sysconfdir and $__fish_datadir). If there are files with the same name in two or all of these, fish will only attempt to read the first (skipping all files with that name if it is unreadable). ~/.config takes precedence over /etc/ which takes precedence over /usr. The path to the latter can also be gotten via `pkg-config` as "confdir", and is meant for third-party applications to integrate with fish.
\section other Other features
diff --git a/share/config.fish b/share/config.fish
index 9ed3250a7..fe45f70d7 100644
--- a/share/config.fish
+++ b/share/config.fish
@@ -157,7 +157,7 @@ end
# As last part of initialization, source the conf directories
# Implement precedence (User > Admin > Vendors > Fish) by basically doing "basename"
set -l sourcelist
-for file in $configdir/fish/conf.d/* $__fish_sysconfdir/conf.d/* $__fish_datadir/vendor_conf.d/*
+for file in $configdir/fish/conf.d/*.fish $__fish_sysconfdir/conf.d/*.fish $__fish_datadir/vendor_conf.d/*.fish
set -l basename (string replace -r '^.*/' '' -- $file)
contains -- $basename $sourcelist; and continue
set sourcelist $sourcelist $basename
From 6495bd470d40b2b489e6fe350e2da08be64d4bec Mon Sep 17 00:00:00 2001
From: Andreas Nordal
Date: Fri, 18 Mar 2016 23:14:16 +0100
Subject: [PATCH 032/363] Fix memory leaks at exit found in tests
This fixes all memory leaks found by compiling with
clang++ -g -fsanitize=address and running the tests.
Method:
Ensure that memory is freed by the destructor of its respective container,
either by storing objects directly instead of by pointer, or implementing
the required destructor.
---
src/complete.cpp | 92 ++++++++++++++++------------------------------
src/fish_tests.cpp | 4 +-
src/history.cpp | 54 ++++++++++++++++++++++-----
src/history.h | 13 +++----
src/wutil.cpp | 16 ++++----
5 files changed, 95 insertions(+), 84 deletions(-)
diff --git a/src/complete.cpp b/src/complete.cpp
index 5e77af256..8af2c822f 100644
--- a/src/complete.cpp
+++ b/src/complete.cpp
@@ -186,7 +186,6 @@ public:
/** Adds or removes an option. */
void add_option(const complete_entry_opt_t &opt);
bool remove_option(const wcstring &option, complete_option_type_t type);
- void remove_all_options();
completion_entry_t(const wcstring &c, bool type, bool author) :
cmd(c),
@@ -201,20 +200,20 @@ public:
struct completion_entry_set_comparer
{
/** Comparison for std::set */
- bool operator()(completion_entry_t *p1, completion_entry_t *p2) const
+ bool operator()(const completion_entry_t &p1, const completion_entry_t &p2) const
{
/* Paths always come last for no particular reason */
- if (p1->cmd_is_path != p2->cmd_is_path)
+ if (p1.cmd_is_path != p2.cmd_is_path)
{
- return p1->cmd_is_path < p2->cmd_is_path;
+ return p1.cmd_is_path < p2.cmd_is_path;
}
else
{
- return p1->cmd < p2->cmd;
+ return p1.cmd < p2.cmd;
}
}
};
-typedef std::set completion_entry_set_t;
+typedef std::set completion_entry_set_t;
static completion_entry_set_t completion_set;
// Comparison function to sort completions by their order field
@@ -520,46 +519,28 @@ bool completer_t::condition_test(const wcstring &condition)
}
-/** Search for an exactly matching completion entry. Must be called while locked. */
-static completion_entry_t *complete_find_exact_entry(const wcstring &cmd, const bool cmd_is_path)
-{
- ASSERT_IS_LOCKED(completion_lock);
- completion_entry_t *result = NULL;
- completion_entry_t tmp_entry(cmd, cmd_is_path, false);
- completion_entry_set_t::iterator iter = completion_set.find(&tmp_entry);
- if (iter != completion_set.end())
- {
- result = *iter;
- }
- return result;
-}
-
/** Locate the specified entry. Create it if it doesn't exist. Must be called while locked. */
-static completion_entry_t *complete_get_exact_entry(const wcstring &cmd, bool cmd_is_path)
+static completion_entry_t &complete_get_exact_entry(const wcstring &cmd, bool cmd_is_path)
{
ASSERT_IS_LOCKED(completion_lock);
- completion_entry_t *c;
- c = complete_find_exact_entry(cmd, cmd_is_path);
+ std::pair ins =
+ completion_set.insert(completion_entry_t(cmd, cmd_is_path, false));
- if (c == NULL)
- {
- c = new completion_entry_t(cmd, cmd_is_path, false);
- completion_set.insert(c);
- }
-
- return c;
+ // NOTE SET_ELEMENTS_ARE_IMMUTABLE: Exposing mutable access here is only
+ // okay as long as callers do not change any field that matters to ordering
+ // - affecting order without telling std::set invalidates its internal state
+ return const_cast(*ins.first);
}
void complete_set_authoritative(const wchar_t *cmd, bool cmd_is_path, bool authoritative)
{
- completion_entry_t *c;
-
CHECK(cmd,);
scoped_lock lock(completion_lock);
- c = complete_get_exact_entry(cmd, cmd_is_path);
- c->authoritative = authoritative;
+
+ completion_entry_t &c = complete_get_exact_entry(cmd, cmd_is_path);
+ c.authoritative = authoritative;
}
@@ -580,8 +561,7 @@ void complete_add(const wchar_t *cmd,
/* Lock the lock that allows us to edit the completion entry list */
scoped_lock lock(completion_lock);
- completion_entry_t *c;
- c = complete_get_exact_entry(cmd, cmd_is_path);
+ completion_entry_t &c = complete_get_exact_entry(cmd, cmd_is_path);
/* Create our new option */
complete_entry_opt_t opt;
@@ -594,7 +574,7 @@ void complete_add(const wchar_t *cmd,
if (desc) opt.desc = desc;
opt.flags = flags;
- c->add_option(opt);
+ c.add_option(opt);
}
/**
@@ -621,28 +601,23 @@ bool completion_entry_t::remove_option(const wcstring &option, complete_option_t
return this->options.empty();
}
-void completion_entry_t::remove_all_options()
-{
- ASSERT_IS_LOCKED(completion_lock);
- this->options.clear();
-}
-
void complete_remove(const wcstring &cmd, bool cmd_is_path, const wcstring &option, complete_option_type_t type)
{
scoped_lock lock(completion_lock);
completion_entry_t tmp_entry(cmd, cmd_is_path, false);
- completion_entry_set_t::iterator iter = completion_set.find(&tmp_entry);
+ completion_entry_set_t::iterator iter = completion_set.find(tmp_entry);
if (iter != completion_set.end())
{
- completion_entry_t *entry = *iter;
- bool delete_it = entry->remove_option(option, type);
+ // const_cast: See SET_ELEMENTS_ARE_IMMUTABLE
+ completion_entry_t &entry = const_cast(*iter);
+
+ bool delete_it = entry.remove_option(option, type);
if (delete_it)
{
/* Delete this entry */
completion_set.erase(iter);
- delete entry;
}
}
}
@@ -652,14 +627,7 @@ void complete_remove_all(const wcstring &cmd, bool cmd_is_path)
scoped_lock lock(completion_lock);
completion_entry_t tmp_entry(cmd, cmd_is_path, false);
- completion_entry_set_t::iterator iter = completion_set.find(&tmp_entry);
- if (iter != completion_set.end())
- {
- completion_entry_t *entry = *iter;
- entry->remove_all_options();
- completion_set.erase(iter);
- delete entry;
- }
+ completion_set.erase(tmp_entry);
}
@@ -1187,12 +1155,12 @@ bool completer_t::complete_param(const wcstring &scmd_orig, const wcstring &spop
scoped_lock lock(completion_lock);
for (completion_entry_set_t::const_iterator iter = completion_set.begin(); iter != completion_set.end(); ++iter)
{
- const completion_entry_t *i = *iter;
- const wcstring &match = i->cmd_is_path ? path : cmd;
- if (wildcard_match(match, i->cmd))
+ const completion_entry_t &i = *iter;
+ const wcstring &match = i.cmd_is_path ? path : cmd;
+ if (wildcard_match(match, i.cmd))
{
/* Copy all of their options into our list */
- all_options.push_back(i->get_options()); //Oof, this is a lot of copying
+ all_options.push_back(i.get_options()); //Oof, this is a lot of copying
}
}
}
@@ -1909,7 +1877,11 @@ wcstring complete_print()
scoped_lock locker(completion_lock);
// Get a list of all completions in a vector, then sort it by order
- std::vector all_completions(completion_set.begin(), completion_set.end());
+ std::vector all_completions;
+ for (completion_entry_set_t::const_iterator i = completion_set.begin(); i != completion_set.end(); ++i)
+ {
+ all_completions.push_back(&*i);
+ }
sort(all_completions.begin(), all_completions.end(), compare_completions_by_order);
for (std::vector::const_iterator iter = all_completions.begin(); iter != all_completions.end(); ++iter)
diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp
index dfc346092..5bacab80e 100644
--- a/src/fish_tests.cpp
+++ b/src/fish_tests.cpp
@@ -2645,9 +2645,11 @@ static void test_universal()
if (system("mkdir -p /tmp/fish_uvars_test/")) err(L"mkdir failed");
const int threads = 16;
+ static int ctx[threads];
for (int i=0; i < threads; i++)
{
- iothread_perform(test_universal_helper, new int(i));
+ ctx[i] = i;
+ iothread_perform(test_universal_helper, &ctx[i]);
}
iothread_drain_all();
diff --git a/src/history.cpp b/src/history.cpp
index a37d2b776..ff99db9a0 100644
--- a/src/history.cpp
+++ b/src/history.cpp
@@ -56,6 +56,9 @@ Our history format is intended to be valid YAML. Here it is:
/** Default buffer size for flushing to the history file */
#define HISTORY_OUTPUT_BUFFER_SIZE (4096 * 4)
+namespace
+{
+
/* Helper class for certain output. This is basically a string that allows us to ensure we only flush at record boundaries, and avoids the copying of ostringstream. Have you ever tried to implement your own streambuf? Total insanity. */
class history_output_buffer_t
{
@@ -168,7 +171,7 @@ public:
explicit history_lru_node_t(const history_item_t &item) :
lru_node_t(item.str()),
timestamp(item.timestamp()),
- required_paths(item.required_paths)
+ required_paths(item.get_required_paths())
{}
};
@@ -207,9 +210,31 @@ public:
}
};
-static pthread_mutex_t hist_lock = PTHREAD_MUTEX_INITIALIZER;
+class history_collection_t
+{
+ pthread_mutex_t m_lock;
+ std::map m_histories;
-static std::map histories;
+public:
+ history_collection_t()
+ {
+ VOMIT_ON_FAILURE_NO_ERRNO(pthread_mutex_init(&m_lock, NULL));
+ }
+ ~history_collection_t()
+ {
+ for (std::map::const_iterator i = m_histories.begin(); i != m_histories.end(); ++i)
+ {
+ delete i->second;
+ }
+ pthread_mutex_destroy(&m_lock);
+ }
+ history_t& alloc(const wcstring &name);
+ void save();
+};
+
+} //anonymous namespace
+
+static history_collection_t histories;
static wcstring history_filename(const wcstring &name, const wcstring &suffix);
@@ -524,16 +549,21 @@ static size_t offset_of_next_item(const char *begin, size_t mmap_length, history
return result;
}
-history_t & history_t::history_with_name(const wcstring &name)
+history_t & history_collection_t::alloc(const wcstring &name)
{
/* Note that histories are currently never deleted, so we can return a reference to them without using something like shared_ptr */
- scoped_lock locker(hist_lock);
- history_t *& current = histories[name];
+ scoped_lock locker(m_lock);
+ history_t *& current = m_histories[name];
if (current == NULL)
current = new history_t(name);
return *current;
}
+history_t & history_t::history_with_name(const wcstring &name)
+{
+ return histories.alloc(name);
+}
+
history_t::history_t(const wcstring &pname) :
name(pname),
first_unwritten_new_item_index(0),
@@ -1809,15 +1839,21 @@ void history_init()
}
-void history_destroy()
+void history_collection_t::save()
{
/* Save all histories */
- for (std::map::iterator iter = histories.begin(); iter != histories.end(); ++iter)
+ for (std::map::iterator iter = m_histories.begin(); iter != m_histories.end(); ++iter)
{
- iter->second->save();
+ history_t *hist = iter->second;
+ hist->save();
}
}
+void history_destroy()
+{
+ histories.save();
+}
+
void history_sanity_check()
{
diff --git a/src/history.h b/src/history.h
index f99950aa0..58291f22a 100644
--- a/src/history.h
+++ b/src/history.h
@@ -43,7 +43,6 @@ typedef uint32_t history_identifier_t;
class history_item_t
{
friend class history_t;
- friend class history_lru_node_t;
friend class history_tests_t;
private:
@@ -115,15 +114,9 @@ class history_t
history_t(const history_t&);
history_t &operator=(const history_t&);
- /** Private creator */
- explicit history_t(const wcstring &pname);
-
/** Privately add an item. If pending, the item will not be returned by history searches until a call to resolve_pending. */
void add(const history_item_t &item, bool pending = false);
- /** Destructor */
- ~history_t();
-
/** Lock for thread safety */
pthread_mutex_t lock;
@@ -208,6 +201,12 @@ class history_t
static history_item_t decode_item(const char *base, size_t len, history_file_type_t type);
public:
+ /** Constructor */
+ explicit history_t(const wcstring &);
+
+ /** Destructor */
+ ~history_t();
+
/** Returns history with the given name, creating it if necessary */
static history_t & history_with_name(const wcstring &name);
diff --git a/src/wutil.cpp b/src/wutil.cpp
index 2ff358bc8..62602c2cf 100644
--- a/src/wutil.cpp
+++ b/src/wutil.cpp
@@ -44,8 +44,8 @@ const file_id_t kInvalidFileID = {(dev_t)-1LL, (ino_t)-1LL, (uint64_t)-1LL, -1,
/* Lock to protect wgettext */
static pthread_mutex_t wgettext_lock;
-/* Maps string keys to (immortal) pointers to string values. */
-typedef std::map wgettext_map_t;
+/* Map used as cache by wgettext. */
+typedef std::map wgettext_map_t;
static wgettext_map_t wgettext_map;
bool wreaddir_resolving(DIR *dir, const std::wstring &dir_path, std::wstring &out_name, bool *out_is_dir)
@@ -488,16 +488,18 @@ const wchar_t *wgettext(const wchar_t *in)
wcstring key = in;
scoped_lock lock(wgettext_lock);
- // Reference to pointer to string
- const wchar_t *& val = wgettext_map[key];
- if (val == NULL)
+ wcstring &val = wgettext_map[key];
+ if (val.empty())
{
cstring mbs_in = wcs2string(key);
char *out = fish_gettext(mbs_in.c_str());
- val = wcsdup(format_string(L"%s", out).c_str()); //note that this writes into the map!
+ val = format_string(L"%s", out).c_str();
}
errno = err;
- return val; //looks dangerous but is safe, since the string is stored in the map
+
+ // The returned string is stored in the map
+ // TODO: If we want to shrink the map, this would be a problem
+ return val.c_str();
}
int wmkdir(const wcstring &name, int mode)
From bb5608e920043070498a16bec30fb4d3cebfd0db Mon Sep 17 00:00:00 2001
From: ridiculousfish
Date: Sun, 27 Mar 2016 18:01:19 -0700
Subject: [PATCH 033/363] Remove an unnecessary c_str()
---
src/wutil.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/wutil.cpp b/src/wutil.cpp
index 62602c2cf..a4494470d 100644
--- a/src/wutil.cpp
+++ b/src/wutil.cpp
@@ -493,7 +493,7 @@ const wchar_t *wgettext(const wchar_t *in)
{
cstring mbs_in = wcs2string(key);
char *out = fish_gettext(mbs_in.c_str());
- val = format_string(L"%s", out).c_str();
+ val = format_string(L"%s", out);
}
errno = err;
From 6663c73eb0f1eedf5290bf07398d6dbe30eaaf73 Mon Sep 17 00:00:00 2001
From: Josef Gajdusek
Date: Sun, 27 Mar 2016 23:00:19 +0200
Subject: [PATCH 034/363] Fix typos: ingnore->ignore
---
share/completions/modprobe.fish | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/share/completions/modprobe.fish b/share/completions/modprobe.fish
index 540fa5a24..14133ad55 100644
--- a/share/completions/modprobe.fish
+++ b/share/completions/modprobe.fish
@@ -7,8 +7,8 @@ complete -c modprobe -s v -l verbose --description "Print messages about what th
complete -c modprobe -s C -l config --description "Configuration file" -r
complete -c modprobe -s c -l showconfig --description "Dump configuration file"
complete -c modprobe -s n -l dry-run --description "Do not actually insert/remove module"
-complete -c modprobe -s i -l ingnore-install --description "Ignore install and remove commands in configuration file"
-complete -c modprobe -l ingnore-remove --description "Ignore install and remove commands in configuration file"
+complete -c modprobe -s i -l ignore-install --description "Ignore install and remove commands in configuration file"
+complete -c modprobe -l ignore-remove --description "Ignore install and remove commands in configuration file"
complete -c modprobe -s q -l quiet --description "Ignore bogus module names"
complete -c modprobe -s r -l remove --description "Remove modules"
complete -c modprobe -s V -l version --description "Display version and exit"
From 0eb3fd6b3f25e6fd0f22ed4327b2aa1b019cde18 Mon Sep 17 00:00:00 2001
From: Josef Gajdusek
Date: Mon, 28 Mar 2016 00:39:15 +0200
Subject: [PATCH 035/363] Make modprobe completion more precise
Only match loaded modules when -r is specified.
Also adds /lib/modules/(uname -r)/misc to the search path.
This directory is used by Gentoo for package-provided modules
(such as the app-emulation/virtualbox-modules)
---
share/completions/modprobe.fish | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/share/completions/modprobe.fish b/share/completions/modprobe.fish
index 14133ad55..8075d4373 100644
--- a/share/completions/modprobe.fish
+++ b/share/completions/modprobe.fish
@@ -2,7 +2,8 @@
# Completions for the modprobe command
#
-complete -c modprobe --no-files -d Module -a "(find /lib/modules/(uname -r)/kernel -type f | sed -e 's/\/.*\/\([^\/.]*\).*/\1/')"
+complete -c modprobe -n "__fish_contains_opt -s r remove" --no-files -d Module -a "(lsmod | cut -d' ' -f1)"
+complete -c modprobe -n "not __fish_contains_opt -s r remove" --no-files -d Module -a "(find /lib/modules/(uname -r)/{kernel,misc} -type f 2>/dev/null | sed -e 's/\/.*\/\([^\/.]*\).*/\1/')"
complete -c modprobe -s v -l verbose --description "Print messages about what the program is doing"
complete -c modprobe -s C -l config --description "Configuration file" -r
complete -c modprobe -s c -l showconfig --description "Dump configuration file"
From 2eb518f59c2401185ab58ba2639fb8907e68e6d0 Mon Sep 17 00:00:00 2001
From: David Adam
Date: Mon, 28 Mar 2016 20:56:56 +0800
Subject: [PATCH 036/363] travis: enable leak detection in address sanitiser
Since #2849 was merged, there are no further leaks detected by the
address sanitiser. This makes it a good target to enable for Travis,
which will enable regression testing.
Closes #2851.
---
.travis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.travis.yml b/.travis.yml
index 54c047db2..cc883e8c6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -32,7 +32,7 @@ matrix:
env:
- CXXFLAGS="-g -fno-omit-frame-pointer -fsanitize=address"
- ASAN_SYMBOLIZER_PATH="/usr/bin/llvm-symbolizer-3.6"
- - ASAN_OPTIONS=check_initialization_order=1:detect_stack_use_after_return=1:detect_leaks=0
+ - ASAN_OPTIONS=check_initialization_order=1:detect_stack_use_after_return=1:detect_leaks=1
before_install: export CXX=clang++-3.6
- os: osx
From daf94e14d404060537317c5d925e8732ff4f8f44 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Tue, 29 Mar 2016 15:24:58 +0200
Subject: [PATCH 037/363] Document more keybindings
Fixes #2866.
---
doc_src/index.hdr.in | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index ff2d5ab36..ca3075390 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -909,7 +909,7 @@ Similar to bash, fish has Emacs and Vi editing modes. The default editing mode i
\subsection emacs-mode Emacs mode commands
-- @key{Tab} completes the current token.
+- @key{Tab} completes the current token. @key{Shift, Tab} completes the current token and starts the pager's search mode.
- @key{Home} or @key{Control,A} moves the cursor to the beginning of the line.
@@ -935,7 +935,7 @@ Similar to bash, fish has Emacs and Vi editing modes. The default editing mode i
- @key{Control,L} clears and repaints the screen.
-- @key{Control,W} moves the previous word to the killring.
+- @key{Control,W} moves the previous path component (everything up to the previous "/") to the killring.
- @key{Alt,D} moves the next word to the killring.
@@ -951,6 +951,11 @@ Similar to bash, fish has Emacs and Vi editing modes. The default editing mode i
- @key{Alt,H} (or @key{F1}) shows the manual page for the current command, if one exists.
+- @key{Control, t} transposes the last two characters
+
+- @key{Alt,t} transposes the last two words
+
+
You can change these key bindings using the bind builtin command.
From 19dd28e4006d952d8f03cbc773c4bb75807f7e51 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Tue, 29 Mar 2016 15:54:20 +0200
Subject: [PATCH 038/363] Document pager search
Fixes #2866.
---
doc_src/index.hdr.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index ca3075390..023bf3f3c 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -304,7 +304,7 @@ Autosuggestions are a powerful way to quickly summon frequently entered commands
\section completion Tab completion
-Tab completion is one of the most time saving features of any modern shell. By tapping the tab key, the user asks `fish` to guess the rest of the command or parameter that the user is currently typing. If `fish` can only find one possible completion, `fish` will write it out. If there is more than one completion, `fish` will write out the longest prefix that all completions have in common. If the completions differ on the first character, a list of all possible completions is printed. The list features descriptions of the completions and if the list doesn't fit the screen, it is scrollable by using the arrow keys, the page up/page down keys, the tab key or the space bar. Pressing any other key will exit the list and insert the pressed key into the command line.
+Tab completion is one of the most time saving features of any modern shell. By tapping the tab key, the user asks `fish` to guess the rest of the command or parameter that the user is currently typing. If `fish` can only find one possible completion, `fish` will write it out. If there is more than one completion, `fish` will write out the longest prefix that all completions have in common. If the completions differ on the first character, a list of all possible completions is printed. The list features descriptions of the completions and if the list doesn't fit the screen, it is scrollable by using the arrow keys, the page up/page down keys, the tab key or the space bar. Once the list has been entered, pressing any other key will start a search. If the list has not been entered, pressing any other key will exit the list and insert the pressed key into the command line.
These are the general purpose tab completions that `fish` provides:
From d30f8fffc89c0e9f7e69b6c72897c0549fbd2ac5 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Tue, 29 Mar 2016 15:55:02 +0200
Subject: [PATCH 039/363] Reword: Always call suggestions sugggestions
Not completions.
---
doc_src/index.hdr.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index 023bf3f3c..e4eabf48d 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -295,7 +295,7 @@ Help on a specific builtin can also be obtained with the `-h` parameter. For ins
\section autosuggestions Autosuggestions
-fish suggests commands as you type, based on command history, completions, and valid file paths. As you type commands, you will see a completion offered after the cursor, in a muted gray color (which can be changed with the `fish_color_autosuggestion` variable).
+fish suggests commands as you type, based on command history, completions, and valid file paths. As you type commands, you will see a suggestion offered after the cursor, in a muted gray color (which can be changed with the `fish_color_autosuggestion` variable).
To accept the autosuggestion (replacing the command line contents), press right arrow or @key{Control,F}. To accept the first suggested word, press @key{Alt,→,Right} or @key{Alt,F}. If the autosuggestion is not what you want, just ignore it: it won't execute unless you accept it.
From dfb23c4fce11d9d0577a2cb3c9e192bc24f64c8c Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Tue, 29 Mar 2016 15:33:37 -0700
Subject: [PATCH 040/363] fix regression to vi-mode \cc binding
Commit c0e8ad6 on 2015-10-02 to "Make vi bindings inherit the defaults"
inadvertently reverted commit b6b6de3. Fix that regression. And while I
hate to make "git blame" say I changed the entire file make the function
adhere to fish_indent style.
---
share/functions/fish_vi_key_bindings.fish | 377 +++++++++++-----------
1 file changed, 189 insertions(+), 188 deletions(-)
diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish
index de0f8bd6e..7d2623259 100644
--- a/share/functions/fish_vi_key_bindings.fish
+++ b/share/functions/fish_vi_key_bindings.fish
@@ -1,223 +1,224 @@
function fish_vi_key_bindings --description 'vi-like key bindings for fish'
- # The default escape timeout is 300ms. But for users of Vi bindings that can
- # be slightly annoying when trying to switch to Vi "normal" mode. Too,
- # vi-mode users are unlikely to use escape-as-meta. So set a much shorter
- # timeout in this case.
- set -q fish_escape_delay_ms; or set -g fish_escape_delay_ms 10
+ # The default escape timeout is 300ms. But for users of Vi bindings that can
+ # be slightly annoying when trying to switch to Vi "normal" mode. Too,
+ # vi-mode users are unlikely to use escape-as-meta. So set a much shorter
+ # timeout in this case.
+ set -q fish_escape_delay_ms; or set -g fish_escape_delay_ms 10
- set -l init_mode insert
- set -l eol_keys \$ g\$ \e\[F
- set -l bol_keys \^ 0 g\^ \e\[H
- if set -q argv[1]
- set init_mode $argv[1]
- end
+ set -l init_mode insert
+ set -l eol_keys \$ g\$ \e\[F
+ set -l bol_keys \^ 0 g\^ \e\[H
+ if set -q argv[1]
+ set init_mode $argv[1]
+ end
- # Inherit default key bindings.
- # Do this first so vi-bindings win over default.
- bind --erase --all
- fish_default_key_bindings -M insert
- fish_default_key_bindings -M default
+ # Inherit default key bindings.
+ # Do this first so vi-bindings win over default.
+ bind --erase --all
+ fish_default_key_bindings -M insert
+ fish_default_key_bindings -M default
- # Add a way to switch from insert to normal (command) mode.
- bind -M insert -m default \cc force-repaint
- bind -M insert -m default \e backward-char force-repaint
+ # Add way to kill current command line while in insert mode.
+ bind -M insert \cc 'commandline ""'
+ # Add a way to switch from insert to normal (command) mode.
+ bind -M insert -m default \e backward-char force-repaint
- #
- # normal (command) mode
- #
- bind :q exit
- bind \cd exit
- bind \cc 'commandline ""'
- bind h backward-char
- bind l forward-char
- bind \e\[C forward-char
- bind \e\[D backward-char
+ #
+ # normal (command) mode
+ #
+ bind :q exit
+ bind \cd exit
+ bind \cc 'commandline ""'
+ bind h backward-char
+ bind l forward-char
+ bind \e\[C forward-char
+ bind \e\[D backward-char
- # Some linux VTs output these (why?)
- bind \eOC forward-char
- bind \eOD backward-char
+ # Some linux VTs output these (why?)
+ bind \eOC forward-char
+ bind \eOD backward-char
- bind -k right forward-char
- bind -k left backward-char
- bind -m insert \n execute
- bind -m insert \r execute
- bind -m insert i force-repaint
- bind -m insert I beginning-of-line force-repaint
- bind -m insert a forward-char force-repaint
- bind -m insert A end-of-line force-repaint
- bind -m visual v begin-selection force-repaint
+ bind -k right forward-char
+ bind -k left backward-char
+ bind -m insert \n execute
+ bind -m insert \r execute
+ bind -m insert i force-repaint
+ bind -m insert I beginning-of-line force-repaint
+ bind -m insert a forward-char force-repaint
+ bind -m insert A end-of-line force-repaint
+ bind -m visual v begin-selection force-repaint
- #bind -m insert o "commandline -a \n" down-line force-repaint
- #bind -m insert O beginning-of-line "commandline -i \n" up-line force-repaint # doesn't work
+ #bind -m insert o "commandline -a \n" down-line force-repaint
+ #bind -m insert O beginning-of-line "commandline -i \n" up-line force-repaint # doesn't work
- bind gg beginning-of-buffer
- bind G end-of-buffer
+ bind gg beginning-of-buffer
+ bind G end-of-buffer
- for key in $eol_keys
- bind $key end-of-line
- end
- for key in $bol_keys
- bind $key beginning-of-line
- end
+ for key in $eol_keys
+ bind $key end-of-line
+ end
+ for key in $bol_keys
+ bind $key beginning-of-line
+ end
- bind u history-search-backward
- bind \cr history-search-forward
+ bind u history-search-backward
+ bind \cr history-search-forward
- bind [ history-token-search-backward
- bind ] history-token-search-forward
+ bind [ history-token-search-backward
+ bind ] history-token-search-forward
- bind k up-or-search
- bind j down-or-search
- bind \e\[A up-or-search
- bind \e\[B down-or-search
- bind -k down down-or-search
- bind -k up up-or-search
- bind \eOA up-or-search
- bind \eOB down-or-search
+ bind k up-or-search
+ bind j down-or-search
+ bind \e\[A up-or-search
+ bind \e\[B down-or-search
+ bind -k down down-or-search
+ bind -k up up-or-search
+ bind \eOA up-or-search
+ bind \eOB down-or-search
- bind b backward-word
- bind B backward-bigword
- bind ge backward-word
- bind gE backward-bigword
- bind w forward-word forward-char
- bind W forward-bigword forward-char
- bind e forward-char forward-word backward-char
- bind E forward-bigword backward-char
+ bind b backward-word
+ bind B backward-bigword
+ bind ge backward-word
+ bind gE backward-bigword
+ bind w forward-word forward-char
+ bind W forward-bigword forward-char
+ bind e forward-char forward-word backward-char
+ bind E forward-bigword backward-char
- bind x delete-char
- bind X backward-delete-char
+ bind x delete-char
+ bind X backward-delete-char
- bind -k dc delete-char
+ bind -k dc delete-char
- bind -k backspace backward-delete-char
- bind \x7f backward-delete-char
- bind \e\[3\;2~ backward-delete-char # Mavericks Terminal.app shift-delete
+ bind -k backspace backward-delete-char
+ bind \x7f backward-delete-char
+ bind \e\[3\;2~ backward-delete-char # Mavericks Terminal.app shift-delete
- bind dd kill-whole-line
- bind D kill-line
- bind d\$ kill-line
- bind d\^ backward-kill-line
- bind dw kill-word
- bind dW kill-bigword
- bind diw forward-char forward-char backward-word kill-word
- bind diW forward-char forward-char backward-bigword kill-bigword
- bind daw forward-char forward-char backward-word kill-word
- bind daW forward-char forward-char backward-bigword kill-bigword
- bind de kill-word
- bind dE kill-bigword
- bind db backward-kill-word
- bind dB backward-kill-bigword
- bind dge backward-kill-word
- bind dgE backward-kill-bigword
+ bind dd kill-whole-line
+ bind D kill-line
+ bind d\$ kill-line
+ bind d\^ backward-kill-line
+ bind dw kill-word
+ bind dW kill-bigword
+ bind diw forward-char forward-char backward-word kill-word
+ bind diW forward-char forward-char backward-bigword kill-bigword
+ bind daw forward-char forward-char backward-word kill-word
+ bind daW forward-char forward-char backward-bigword kill-bigword
+ bind de kill-word
+ bind dE kill-bigword
+ bind db backward-kill-word
+ bind dB backward-kill-bigword
+ bind dge backward-kill-word
+ bind dgE backward-kill-bigword
- bind -m insert s delete-char force-repaint
- bind -m insert S kill-whole-line force-repaint
- bind -m insert cc kill-whole-line force-repaint
- bind -m insert C kill-line force-repaint
- bind -m insert c\$ kill-line force-repaint
- bind -m insert c\^ backward-kill-line force-repaint
- bind -m insert cw kill-word force-repaint
- bind -m insert cW kill-bigword force-repaint
- bind -m insert ciw forward-char forward-char backward-word kill-word force-repaint
- bind -m insert ciW forward-char forward-char backward-bigword kill-bigword force-repaint
- bind -m insert caw forward-char forward-char backward-word kill-word force-repaint
- bind -m insert caW forward-char forward-char backward-bigword kill-bigword force-repaint
- bind -m insert ce kill-word force-repaint
- bind -m insert cE kill-bigword force-repaint
- bind -m insert cb backward-kill-word force-repaint
- bind -m insert cB backward-kill-bigword force-repaint
- bind -m insert cge backward-kill-word force-repaint
- bind -m insert cgE backward-kill-bigword force-repaint
+ bind -m insert s delete-char force-repaint
+ bind -m insert S kill-whole-line force-repaint
+ bind -m insert cc kill-whole-line force-repaint
+ bind -m insert C kill-line force-repaint
+ bind -m insert c\$ kill-line force-repaint
+ bind -m insert c\^ backward-kill-line force-repaint
+ bind -m insert cw kill-word force-repaint
+ bind -m insert cW kill-bigword force-repaint
+ bind -m insert ciw forward-char forward-char backward-word kill-word force-repaint
+ bind -m insert ciW forward-char forward-char backward-bigword kill-bigword force-repaint
+ bind -m insert caw forward-char forward-char backward-word kill-word force-repaint
+ bind -m insert caW forward-char forward-char backward-bigword kill-bigword force-repaint
+ bind -m insert ce kill-word force-repaint
+ bind -m insert cE kill-bigword force-repaint
+ bind -m insert cb backward-kill-word force-repaint
+ bind -m insert cB backward-kill-bigword force-repaint
+ bind -m insert cge backward-kill-word force-repaint
+ bind -m insert cgE backward-kill-bigword force-repaint
- bind '~' capitalize-word
- bind gu downcase-word
- bind gU upcase-word
+ bind '~' capitalize-word
+ bind gu downcase-word
+ bind gU upcase-word
- bind J end-of-line delete-char
- bind K 'man (commandline -t) ^/dev/null; or echo -n \a'
+ bind J end-of-line delete-char
+ bind K 'man (commandline -t) ^/dev/null; or echo -n \a'
- bind yy kill-whole-line yank
- bind Y kill-whole-line yank
- bind y\$ kill-line yank
- bind y\^ backward-kill-line yank
- bind yw kill-word yank
- bind yW kill-bigword yank
- bind yiw forward-char forward-char backward-word kill-word yank
- bind yiW forward-char forward-char backward-bigword kill-bigword yank
- bind yaw forward-char forward-char backward-word kill-word yank
- bind yaW forward-char forward-char backward-bigword kill-bigword yank
- bind ye kill-word yank
- bind yE kill-bigword yank
- bind yb backward-kill-word yank
- bind yB backward-kill-bigword yank
- bind yge backward-kill-word yank
- bind ygE backward-kill-bigword yank
+ bind yy kill-whole-line yank
+ bind Y kill-whole-line yank
+ bind y\$ kill-line yank
+ bind y\^ backward-kill-line yank
+ bind yw kill-word yank
+ bind yW kill-bigword yank
+ bind yiw forward-char forward-char backward-word kill-word yank
+ bind yiW forward-char forward-char backward-bigword kill-bigword yank
+ bind yaw forward-char forward-char backward-word kill-word yank
+ bind yaW forward-char forward-char backward-bigword kill-bigword yank
+ bind ye kill-word yank
+ bind yE kill-bigword yank
+ bind yb backward-kill-word yank
+ bind yB backward-kill-bigword yank
+ bind yge backward-kill-word yank
+ bind ygE backward-kill-bigword yank
- bind f forward-jump
- bind F backward-jump
- bind t forward-jump and backward-char
- bind T backward-jump and forward-char
+ bind f forward-jump
+ bind F backward-jump
+ bind t forward-jump and backward-char
+ bind T backward-jump and forward-char
- # in emacs yank means paste
- bind p yank
- bind P backward-char yank
- bind gp yank-pop
+ # in emacs yank means paste
+ bind p yank
+ bind P backward-char yank
+ bind gp yank-pop
- ### Overrides
- # This is complete in vim
- bind -M insert \cx end-of-line
+ ### Overrides
+ # This is complete in vim
+ bind -M insert \cx end-of-line
- bind '"*p' "commandline -i ( xsel -p; echo )[1]"
- bind '"*P' backward-char "commandline -i ( xsel -p; echo )[1]"
+ bind '"*p' "commandline -i ( xsel -p; echo )[1]"
+ bind '"*P' backward-char "commandline -i ( xsel -p; echo )[1]"
- #
- # Lowercase r, enters replace-one mode
- #
- bind -m replace-one r force-repaint
- bind -M replace-one -m default '' delete-char self-insert backward-char force-repaint
- bind -M replace-one -m default \e cancel force-repaint
+ #
+ # Lowercase r, enters replace-one mode
+ #
+ bind -m replace-one r force-repaint
+ bind -M replace-one -m default '' delete-char self-insert backward-char force-repaint
+ bind -M replace-one -m default \e cancel force-repaint
- #
- # visual mode
- #
- bind -M visual \e\[C forward-char
- bind -M visual \e\[D backward-char
- bind -M visual -k right forward-char
- bind -M visual -k left backward-char
- bind -M insert \eOC forward-char
- bind -M insert \eOD backward-char
- bind -M visual h backward-char
- bind -M visual l forward-char
+ #
+ # visual mode
+ #
+ bind -M visual \e\[C forward-char
+ bind -M visual \e\[D backward-char
+ bind -M visual -k right forward-char
+ bind -M visual -k left backward-char
+ bind -M insert \eOC forward-char
+ bind -M insert \eOD backward-char
+ bind -M visual h backward-char
+ bind -M visual l forward-char
- bind -M visual k up-line
- bind -M visual j down-line
+ bind -M visual k up-line
+ bind -M visual j down-line
- bind -M visual b backward-word
- bind -M visual B backward-bigword
- bind -M visual ge backward-word
- bind -M visual gE backward-bigword
- bind -M visual w forward-word
- bind -M visual W forward-bigword
- bind -M visual e forward-word
- bind -M visual E forward-bigword
- bind -M visual o swap-selection-start-stop force-repaint
+ bind -M visual b backward-word
+ bind -M visual B backward-bigword
+ bind -M visual ge backward-word
+ bind -M visual gE backward-bigword
+ bind -M visual w forward-word
+ bind -M visual W forward-bigword
+ bind -M visual e forward-word
+ bind -M visual E forward-bigword
+ bind -M visual o swap-selection-start-stop force-repaint
- for key in $eol_keys
- bind -M visual $key end-of-line
- end
- for key in $bol_keys
- bind -M visual $key beginning-of-line
- end
+ for key in $eol_keys
+ bind -M visual $key end-of-line
+ end
+ for key in $bol_keys
+ bind -M visual $key beginning-of-line
+ end
- bind -M visual -m insert c kill-selection end-selection force-repaint
- bind -M visual -m default d kill-selection end-selection force-repaint
- bind -M visual -m default x kill-selection end-selection force-repaint
- bind -M visual -m default X kill-whole-line end-selection force-repaint
- bind -M visual -m default y kill-selection yank end-selection force-repaint
- bind -M visual -m default '"*y' "commandline -s | xsel -p" end-selection force-repaint
+ bind -M visual -m insert c kill-selection end-selection force-repaint
+ bind -M visual -m default d kill-selection end-selection force-repaint
+ bind -M visual -m default x kill-selection end-selection force-repaint
+ bind -M visual -m default X kill-whole-line end-selection force-repaint
+ bind -M visual -m default y kill-selection yank end-selection force-repaint
+ bind -M visual -m default '"*y' "commandline -s | xsel -p" end-selection force-repaint
- bind -M visual -m default \cc end-selection force-repaint
- bind -M visual -m default \e end-selection force-repaint
+ bind -M visual -m default \cc end-selection force-repaint
+ bind -M visual -m default \e end-selection force-repaint
- set fish_bind_mode $init_mode
+ set fish_bind_mode $init_mode
end
From a148b755a66f050c739aa9844daaea72149e3543 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Tue, 29 Mar 2016 16:42:58 -0700
Subject: [PATCH 041/363] more fish_indent cleanup for prev commit
Commit dfb23c4fce11d9d0577a2cb3c9e192bc24f64c8c was supposed to incude
all the edits to make the code compliant with fish_indent.
---
share/functions/fish_vi_key_bindings.fish | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/share/functions/fish_vi_key_bindings.fish b/share/functions/fish_vi_key_bindings.fish
index 7d2623259..75be6644b 100644
--- a/share/functions/fish_vi_key_bindings.fish
+++ b/share/functions/fish_vi_key_bindings.fish
@@ -3,13 +3,14 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
# be slightly annoying when trying to switch to Vi "normal" mode. Too,
# vi-mode users are unlikely to use escape-as-meta. So set a much shorter
# timeout in this case.
- set -q fish_escape_delay_ms; or set -g fish_escape_delay_ms 10
+ set -q fish_escape_delay_ms
+ or set -g fish_escape_delay_ms 10
set -l init_mode insert
set -l eol_keys \$ g\$ \e\[F
set -l bol_keys \^ 0 g\^ \e\[H
if set -q argv[1]
- set init_mode $argv[1]
+ set init_mode $argv[1]
end
# Inherit default key bindings.
@@ -55,10 +56,10 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind G end-of-buffer
for key in $eol_keys
- bind $key end-of-line
+ bind $key end-of-line
end
for key in $bol_keys
- bind $key beginning-of-line
+ bind $key beginning-of-line
end
bind u history-search-backward
@@ -138,7 +139,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind K 'man (commandline -t) ^/dev/null; or echo -n \a'
bind yy kill-whole-line yank
- bind Y kill-whole-line yank
+ bind Y kill-whole-line yank
bind y\$ kill-line yank
bind y\^ backward-kill-line yank
bind yw kill-word yank
@@ -204,13 +205,13 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -M visual o swap-selection-start-stop force-repaint
for key in $eol_keys
- bind -M visual $key end-of-line
+ bind -M visual $key end-of-line
end
for key in $bol_keys
- bind -M visual $key beginning-of-line
+ bind -M visual $key beginning-of-line
end
- bind -M visual -m insert c kill-selection end-selection force-repaint
+ bind -M visual -m insert c kill-selection end-selection force-repaint
bind -M visual -m default d kill-selection end-selection force-repaint
bind -M visual -m default x kill-selection end-selection force-repaint
bind -M visual -m default X kill-whole-line end-selection force-repaint
@@ -218,7 +219,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -M visual -m default '"*y' "commandline -s | xsel -p" end-selection force-repaint
bind -M visual -m default \cc end-selection force-repaint
- bind -M visual -m default \e end-selection force-repaint
+ bind -M visual -m default \e end-selection force-repaint
set fish_bind_mode $init_mode
end
From 0e18e2ba7870bcd907cd804e35062ad49fcb01d4 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Tue, 29 Mar 2016 15:23:42 -0700
Subject: [PATCH 042/363] clarify behavior of ** glob
Fixes #2680
---
doc_src/index.hdr.in | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index e4eabf48d..15c67c379 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -399,7 +399,19 @@ If a star (`*`) or a question mark (`?`) is present in the parameter, `fish` att
- `*` can match any string of characters not containing '/'. This includes matching an empty string.
-- `**` matches any string of characters. This includes matching an empty string. The string may include the `/` character but does not need to.
+- `**` matches any string of characters. This includes matching an empty string. The matched string may include the `/` character; that is, it recurses into subdirectories. Note that augmenting this wildcard with other strings will not match files in the current working directory (`$PWD`) if you separate the strings with a slash ("/"). This is unlike other shells such as zsh. For example, `**\/*.fish` in zsh will match `.fish` files in the PWD but in fish will only match such files in a subdirectory. In fish you should type `***.fish` to match files in the PWD as well as subdirectories.
+
+Other shells, such as zsh, provide a rich glob syntax for restricting the files matched by globs. For example, `**(.)`, to only match regular files. Fish prefers to defer such features to programs, such as `find`, rather than reinventing the wheel. Thus, if you want to limit the wildcard expansion to just regular files the fish approach is to define and use a function. For example,
+
+\fish{cli-dark}
+function ff --description 'Like ** but only returns plain files.'
+ # This also ignores .git directories.
+ find . \( -name .git -type d -prune \) -o -type f | \
+ sed -n -e '/^\.\/\.git$/n' -e 's/^\.\///p'
+end
+\endfish
+
+You would then use it in place of `**` like this, `my_prog (ff)`, to pass only regular files in or below $PWD to `my_prog`.
Wildcard matches are sorted case insensitively. When sorting matches containing numbers, consecutive digits are considered to be one element, so that the strings '1' '5' and '12' would be sorted in the order given.
From aacdaee6a9b0587d87bc176553bf1489453a8530 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Tue, 29 Mar 2016 19:56:14 +0200
Subject: [PATCH 043/363] Add history --help
This was probably an oversight - the builtin supports it, the function doesn't.
---
share/functions/history.fish | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/share/functions/history.fish b/share/functions/history.fish
index 758b5ea56..a26db0f4c 100644
--- a/share/functions/history.fish
+++ b/share/functions/history.fish
@@ -36,6 +36,8 @@ function history --description "Deletes an item from history"
set cmd print
case --merge
set cmd merge
+ case --help
+ set cmd help
case --
set -e argv[$i]
break
@@ -131,6 +133,8 @@ function history --description "Deletes an item from history"
builtin history $argv
case merge
builtin history --merge
+ case help
+ builtin history --help
case clear
# Erase the entire history
echo "Are you sure you want to clear history ? (y/n)"
From 7e014174b876308f7a6105d6571f51ab7c2022f0 Mon Sep 17 00:00:00 2001
From: Sam Yu
Date: Wed, 30 Mar 2016 15:39:55 +0800
Subject: [PATCH 044/363] __fish_print_packages: use libzypp builtin cache for
zypper
---
share/functions/__fish_print_packages.fish | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/share/functions/__fish_print_packages.fish b/share/functions/__fish_print_packages.fish
index be7d17e1e..a6b84b475 100644
--- a/share/functions/__fish_print_packages.fish
+++ b/share/functions/__fish_print_packages.fish
@@ -54,6 +54,12 @@ function __fish_print_packages
# Zypper needs caching as it is slow
if type -q -f zypper
+ # Use libzypp cache file if available
+ if test -f /var/cache/zypp/solv/@System/solv.idx
+ cat /var/cache/zypp/solv/*/solv.idx | awk '!/application:|srcpackage:|product:|pattern:|patch:/ {print $1'\t$package'}'
+ return
+ end
+
# If the cache is less than five minutes old, we do not recalculate it
set -l cache_file $XDG_CACHE_HOME/.zypper-cache.$USER
From 35cee1e39c0ca6bd35f2bb0c18ad6ffca5cc7108 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Wed, 30 Mar 2016 15:35:14 -0700
Subject: [PATCH 045/363] remove "doc" make target and rename "user_doc"
Fixes #2874
---
Makefile.in | 30 ++++++++++++------------------
build_tools/make_tarball.sh | 2 +-
doc_src/FORMATTING.md | 2 +-
3 files changed, 14 insertions(+), 20 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index 056a3d814..c68d7aa5d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -266,29 +266,23 @@ prof: all
#
# User documentation, describing the features of the fish shell.
#
-
-# Depend on the sources (*.hdr.in) and manually make the
-# intermediate *.hdr and doc.h files if needed
-# The sed command deletes everything including and after the first -, for simpler version numbers
-# Cleans up the user_doc/html directory once Doxygen is done.
-
-user_doc: $(HDR_FILES_SRC) Doxyfile.user $(HTML_SRC) $(HELP_SRC) doc.h $(HDR_FILES) lexicon_filter
+# Depend on the sources (*.hdr.in) and manually make the intermediate *.hdr
+# and doc.h files if needed. The sed command deletes everything including and
+# after the first -, for simpler version numbers. Cleans up the user_doc/html
+# directory once Doxygen is done.
+#
+doc: $(HDR_FILES_SRC) Doxyfile.user $(HTML_SRC) $(HELP_SRC) doc.h \
+ $(HDR_FILES) lexicon_filter
(cat Doxyfile.user; echo INPUT_FILTER=./lexicon_filter; \
- echo PROJECT_NUMBER=$(FISH_BUILD_VERSION) | $(SED) "s/-.*//") | doxygen - && touch user_doc; \
- cd user_doc/html && rm -f bc_s.png bdwn.png closed.png ftv2*.png nav*.png open.png sync_*.png tab*.* doxygen.* dynsections.js jquery.js pages.html
-
-#
-# Source code documentation. Also includes user documentation.
-#
-
-doc: src/*.h src/*.cpp doc.h Doxyfile lexicon_filter
- (cat Doxyfile; echo INPUT_FILTER=./lexicon_filter; echo PROJECT_NUMBER=$(FISH_BUILD_VERSION)) | doxygen - ;
-
+ echo PROJECT_NUMBER=$(FISH_BUILD_VERSION) | $(SED) "s/-.*//") | \
+ doxygen - && touch user_doc; \
+ cd user_doc/html && rm -f bc_s.png bdwn.png closed.png ftv2*.png \
+ nav*.png open.png sync_*.png tab*.* doxygen.* dynsections.js \
+ jquery.js pages.html
#
# PDF version of the source code documentation.
#
-
doc/refman.pdf: doc
cd doc/latex && \
make && \
diff --git a/build_tools/make_tarball.sh b/build_tools/make_tarball.sh
index 4f02411bd..1e24de0f9 100755
--- a/build_tools/make_tarball.sh
+++ b/build_tools/make_tarball.sh
@@ -37,7 +37,7 @@ git archive --format=tar --prefix="$prefix"/ HEAD > "$path"
# Don't run autoheader since configure.ac runs it. autoconf is enough.
autoconf
./configure --with-doxygen
-make user_doc share/man
+make doc share/man
echo $VERSION > version
cd /tmp
rm -f "$prefix"
diff --git a/doc_src/FORMATTING.md b/doc_src/FORMATTING.md
index 0a44f3554..0ae1c81e1 100644
--- a/doc_src/FORMATTING.md
+++ b/doc_src/FORMATTING.md
@@ -56,7 +56,7 @@ is transformed into:
`@cmnd{echo} @args{hello} @args{world}`
-which is then transformed by Doxygen into an HTML version (`make user_doc`):
+which is then transformed by Doxygen into an HTML version (`make doc`):
`echo hello world`
From 6888c3d60495f7807468edf1c78ff2c817c64f31 Mon Sep 17 00:00:00 2001
From: Jak Wings
Date: Thu, 31 Mar 2016 14:51:58 +0800
Subject: [PATCH 046/363] rename make target "user_doc" to "doc"
Fixes #2875
---
Makefile.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.in b/Makefile.in
index c68d7aa5d..621d787f8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -213,7 +213,7 @@ endif
#
ifeq ($(HAVE_DOXYGEN), 1)
- user_doc=user_doc
+ user_doc=doc
share_man=share/man
else
user_doc=
From 83233ccc5a6ab8e7521133eebb771af6939750a8 Mon Sep 17 00:00:00 2001
From: Laurence McGlashan
Date: Thu, 31 Mar 2016 22:19:27 +0100
Subject: [PATCH 047/363] Correction to make rule for fish_version
---
Makefile.in | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Makefile.in b/Makefile.in
index 621d787f8..59eb13409 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -238,7 +238,7 @@ FISH-BUILD-VERSION-FILE: FORCE
-include FISH-BUILD-VERSION-FILE
CXXFLAGS += -DFISH_BUILD_VERSION=\"$(FISH_BUILD_VERSION)\"
.PHONY: FORCE
-fish_version.o: FISH-BUILD-VERSION-FILE
+obj/fish_version.o: FISH-BUILD-VERSION-FILE
#
From 4f5d42858c558af73575b1f38e6ad0bc58912b46 Mon Sep 17 00:00:00 2001
From: David Adam
Date: Fri, 1 Apr 2016 07:19:43 +0800
Subject: [PATCH 048/363] travis: move to clang 3.8 for ASan builds
---
.travis.yml | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index cc883e8c6..8307fe85f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -18,22 +18,19 @@ matrix:
addons:
apt:
sources:
- # stick with 3.6; the 3.7 Debian binaries do not support ASan yet
- # https://llvm.org/bugs/show_bug.cgi?id=22757
- - llvm-toolchain-precise-3.6
+ - llvm-toolchain-precise-3.8
- ubuntu-toolchain-r-test
packages:
- - clang-3.6
- - llvm-3.6 # for llvm-symbolizer
+ - clang-3.8
+ - llvm-3.8 # for llvm-symbolizer
- bc
- expect
- gettext
- libncurses5-dev
env:
- CXXFLAGS="-g -fno-omit-frame-pointer -fsanitize=address"
- - ASAN_SYMBOLIZER_PATH="/usr/bin/llvm-symbolizer-3.6"
- ASAN_OPTIONS=check_initialization_order=1:detect_stack_use_after_return=1:detect_leaks=1
- before_install: export CXX=clang++-3.6
+ before_install: export CXX=clang++-3.8
- os: osx
before_install:
From 6fa09e6a70d4116e22df36d33e2f7533cbcbe098 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Fri, 1 Apr 2016 16:28:36 -0700
Subject: [PATCH 049/363] add make targets to lint the code
Fixes #2818
---
.oclint | 8 ++++
CONTRIBUTING.md | 95 ++++++++++++++++++++++---------------------
Makefile.in | 8 ++++
build_tools/lint.fish | 95 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 160 insertions(+), 46 deletions(-)
create mode 100644 .oclint
create mode 100755 build_tools/lint.fish
diff --git a/.oclint b/.oclint
new file mode 100644
index 000000000..cd68e1821
--- /dev/null
+++ b/.oclint
@@ -0,0 +1,8 @@
+rules:
+rule-configurations:
+ # This is the default value (as of the time I wrote this) but I'm making
+ # it explicit since it needs to agree with the value used by clang-format.
+ # Thus, if we ever change the fish style to allow longer lines this should
+ # be changed (as well as the corresponding clang-format config).
+ - key: LONG_LINE
+ value: 100
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d3e2ca1f9..6321cdc7f 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,15 +1,50 @@
-# Style guide
+# Guidelines For Developers
-This is style guide for fish contributors. You should use it for any new code
-that you would add to this project and try to format existing code to use this
-style.
+## Lint Free Code
-## Formatting
+Automated analysis tools like cppcheck and oclint can help identify bugs. They also help ensure the code has a consistent style and avoids patterns that tend to confuse people.
+
+Ultimately we want lint free code. However, at the moment a lot of cleanup is required to reach that goal. For now simply try to avoid introducing new lint.
+
+To make linting the code easy there are two make targets: `lint` and `lint-all`. The latter does just what the name implies. The former will lint any modified but not committed `*.cpp` files. If there is no uncommitted work it will lint the files in the most recent commit.
+
+To install the lint checkers on Mac OS X using HomeBrew:
+
+```
+brew tap oclint/formulae
+brew install oclint
+brew install cppcheck
+```
+
+To install the lint checkers on Linux distros that use Apt:
+
+```
+sudo apt-get install clang
+sudo apt-get install oclint
+sudo apt-get install cppcheck
+```
+
+## Fish Script Style Guide
+
+Fish scripts such as those in the *share/functions* and *tests* directories should be formatted using the `fish_indent` command.
+
+Function names should be all lowercase with undescores separating words. Private functions should begin with an underscore. The first word should be `fish` if the function is unique to fish.
+
+The first word of global variable names should generally be `fish` for public vars or `_fish` for private vars to minimize the possibility of name clashes with user defined vars.
+
+## C++ Style Guide
+
+1. The `clang-format` command is authoritative with respect to indentation, whitespace around operators, etc. **Note**: this rule should be ignored at this time. A subsequent commit will add the necessary config file and make targets. After the happens the code will be cleaned up and this rule will become mandatory.
+
+1. All names in code should be `small_snake_case`. No Hungarian notation is used. Classes and structs names should be followed by `_t`.
1. fish uses the Allman/BSD style of indentation.
-2. Indent with spaces, not tabs.
-3. Use 4 spaces per indent (unless needed like `Makefile`).
-4. Opening curly bracket is on the following line:
+
+1. Indent with spaces, not tabs.
+
+1. Use 4 spaces per indent.
+
+1. Opening curly bracket is on the following line:
// ✔:
struct name
@@ -32,7 +67,7 @@ style.
// code
}
-5. Put space after `if`, `while` and `for` before conditions.
+1. Put space after `if`, `while` and `for` before conditions.
// ✔:
if () {}
@@ -40,7 +75,7 @@ style.
// ✗:
if() {}
-6. Put spaces before and after operators excluding increment and decrement;
+1. Put spaces before and after operators excluding increment and decrement;
// ✔:
int a = 1 + 2 * 3;
@@ -50,7 +85,7 @@ style.
int a=1+2*3;
a ++;
-7. Never put spaces between function name and parameters list.
+1. Never put spaces between function name and parameters list.
// ✔:
func(args);
@@ -58,8 +93,9 @@ style.
// ✗:
func (args);
-8. Never put spaces after `(` and before `)`.
-9. Always put space after comma and semicolon.
+1. Never put spaces after `(` and before `)`.
+
+1. Always put space after comma and semicolon.
// ✔:
func(arg1, arg2);
@@ -70,36 +106,3 @@ style.
func(arg1,arg2);
for (int i = 0;i /dev/null
+ # There are pending changes so lint those files.
+ for arg in $pending
+ set files $files (string split -m 1 ' ' $arg)[2]
+ end
+ else
+ # No pending changes so lint the files in the most recent commit.
+ set files (git show --porcelain --name-only --pretty=oneline head | tail --lines=+2)
+ end
+
+ # Filter out the non-C/C++ files.
+ set c_files (string match -r '.*\.c(?:pp)?$' -- $files)
+else
+ set c_files src/*.cpp
+end
+
+# We now have a list of files to check so run the linters.
+if set -q c_files[1]
+ if type -q cppcheck
+ echo
+ echo ========================================
+ echo Running cppcheck
+ echo ========================================
+ cppcheck -q --verbose --std=posix --std=c11 --language=c++ \
+ --inline-suppr --enable=$cppchecks $cppcheck_args $c_files
+ end
+
+ if type -q oclint
+ echo
+ echo ========================================
+ echo Running oclint
+ echo ========================================
+ if test (uname -s) = "Darwin"
+ if not test -f compile_commands.json
+ xcodebuild > xcodebuild.log
+ oclint-xcodebuild xcodebuild.log > /dev/null
+ end
+ if test $all = yes
+ oclint-json-compilation-database -e '/pcre2-10.20/' \
+ -- -enable-global-analysis
+ else
+ set i_files
+ for f in $c_files
+ set i_files $i_files -i $f
+ end
+ echo oclint-json-compilation-database -e '/pcre2-10.20/' $i_files
+ oclint-json-compilation-database -e '/pcre2-10.20/' $i_files
+ end
+ else
+ # Presumably we're on Linux or other platform not requiring special
+ # handling for oclint to work.
+ oclint $c_files -- $argv
+ end
+ end
+else
+ echo
+ echo 'WARNING: No C/C++ files to check'
+ echo
+end
From bbf0007c46994e89d8d78954b5a0419ee0a60435 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Fri, 1 Apr 2016 21:01:54 -0700
Subject: [PATCH 050/363] remove create_wajig_completions.py script
This script is really old and no longer works correctly. This discussion,
http://comments.gmane.org/gmane.comp.shells.fish.user/4062, from over two
years ago concluded it should be removed.
Resolves #2881
---
create_wajig_completions.py | 121 ------------------------------------
1 file changed, 121 deletions(-)
delete mode 100755 create_wajig_completions.py
diff --git a/create_wajig_completions.py b/create_wajig_completions.py
deleted file mode 100755
index 15dfd1ab8..000000000
--- a/create_wajig_completions.py
+++ /dev/null
@@ -1,121 +0,0 @@
-#!/usr/bin/env python
-# -*- python -*-
-
-# Program to generate fish completion function for wajig.
-# It runs 'wajig command' and analyzes the output to build a
-# completion file which it writes to stdout.
-# To use the result, direct stdout to
-# ~/.fish.d/completions/wajig.fish.
-
-# Author Reuben Thomas, from Don Rozenberg's bash_completion.py and
-# fish's apt-get.fish.
-
-import os
-import re
-import pprint
-pp = pprint.PrettyPrinter()
-
-def escape_quotes(s):
- return re.sub('\'', '\\\'', s)
-
-# Run wajig command
-f = os.popen('wajig commands', 'r')
-
-lines = f.readlines()
-
-option_patt = r'^-([a-z]*)\|--([a-z]*) +([^ ].*)'
-option_patt_r = re.compile(option_patt)
-
-command_patt = r'^([a-z-]*) +([^ ].*)'
-command_patt_r = re.compile(command_patt)
-
-os_str = []
-os_str.append('')
-ol_str = []
-ol_str.append('')
-oh_str = []
-oh_str.append('')
-o_i = 0
-
-c_str = []
-c_str.append('')
-ch_str = []
-ch_str.append('')
-c_i = 0
-
-for l in lines:
- l = l.strip()
- if l == '' or l.find(':') > -1 or l.find('Run') == 0:
- continue
- if l.find('-') == 0:
- mo = option_patt_r.search(l)
- if mo == None:
- continue
- os_str[o_i] = mo.group(1)
- os_str.append('')
- ol_str[o_i] = mo.group(2)
- ol_str.append('')
- oh_str[o_i] = escape_quotes(mo.group(3))
- oh_str.append('')
- o_i += 1
- else:
- mo = command_patt_r.search(l)
- if mo == None:
- continue
- c_str[c_i] = mo.group(1)
- c_str.append('')
- ch_str[c_i] = escape_quotes(mo.group(2))
- ch_str.append('')
- c_i += 1
-
-# For debugging, print the commands and options.
-#print
-#pp.pprint(c_str)
-
-#print
-#pp.pprint(os_str)
-#print
-#pp.pprint(ol_str)
-
-part1 = '''function __fish_wajig_no_subcommand -d (N_ 'Test if wajig has yet to be given the subcommand')
- for i in (commandline -opc)
- if contains -- $i'''
-
-part2 = '''
- return 1
- end
- end
- return 0
-end
-
-function __fish_wajig_use_package -d (N_ 'Test if wajig command should have packages as potential completion')
- for i in (commandline -opc)
- if contains -- $i contains bug build build-depend changelog dependents describe detail hold install installr installrs installs list list-files news package purge purge-depend readme recursive recommended reconfigure reinstall remove remove-depend repackage show showinstall showremove showupgrade size sizes source suggested unhold upgrade versions whatis
- return 0
- end
- end
- return 1
-end
-
-complete -c wajig -n '__fish_wajig_use_package' -a '(__fish_print_packages)' -d (N_ 'Package')'''
-
-wajig = part1
-
-#add the commands.
-for i in range(0, len(c_str) - 1):
- wajig = "%s %s" % (wajig, c_str[i])
-
-#add part2
-wajig = "%s%s" % (wajig, part2)
-
-#add the options.
-wajig = "%s%s" % (wajig, os_str[0].lstrip())
-for i in range(1, len(os_str) - 1):
- wajig = "%s\ncomplete -c apt-get -s %s -l %s -d (N_ '%s')" % (wajig, os_str[i], ol_str[i], oh_str[i])
-
-#add the commands.
-for i in range(0, len(c_str) - 1):
- wajig = "%s\ncomplete -f -n '__fish_wajig_no_subcommand' -c wajig -a '%s' -d(N_ '%s')" % (wajig, c_str[i], ch_str[i])
-
-#print it all
-print wajig
From 3f1fc332e7451187b1b9806f544bc8199fa412a8 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Sat, 2 Apr 2016 22:18:31 -0700
Subject: [PATCH 051/363] remove unused wgetopt() method found by linting
---
src/wgetopt.cpp | 8 --------
src/wgetopt.h | 1 -
2 files changed, 9 deletions(-)
diff --git a/src/wgetopt.cpp b/src/wgetopt.cpp
index 80ffdcc90..c2905ab0a 100644
--- a/src/wgetopt.cpp
+++ b/src/wgetopt.cpp
@@ -573,14 +573,6 @@ int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *opts
}
}
-int wgetopter_t::wgetopt(int argc, wchar_t **argv, const wchar_t *optstring)
-{
- return _wgetopt_internal(argc, argv, optstring,
- (const struct woption *) 0,
- (int *) 0,
- 0);
-}
-
int wgetopter_t::wgetopt_long(int argc, wchar_t **argv, const wchar_t *options, const struct woption *long_options, int *opt_index)
{
return _wgetopt_internal(argc, argv, options, long_options, opt_index, 0);
diff --git a/src/wgetopt.h b/src/wgetopt.h
index ad1558703..794ccc652 100644
--- a/src/wgetopt.h
+++ b/src/wgetopt.h
@@ -147,7 +147,6 @@ class wgetopter_t
{
}
- int wgetopt(int argc, wchar_t **argv, const wchar_t *optstring);
int wgetopt_long(int argc, wchar_t **argv, const wchar_t *options, const struct woption *long_options, int *opt_index);
int wgetopt_long_only(int argc, wchar_t **argv, const wchar_t *options, const struct woption *long_options, int *opt_index);
};
From 9dd6873e5855f69b01f2e3705a49a4231c992e71 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Sun, 3 Apr 2016 19:02:46 -0700
Subject: [PATCH 052/363] lint: remove or comment out unused functions
Cppcheck has identified a lot of unused functions. This removes funcs that
are unlikely to ever be used. Others that might be useful for debugging I've
commented out with "#if 0".
---
src/builtin.cpp | 4 ++++
src/common.cpp | 5 -----
src/common.h | 3 ---
src/expand.cpp | 56 ----------------------------------------------
src/expand.h | 1 -
src/fish_tests.cpp | 8 ++++---
src/io.cpp | 4 ++++
src/io.h | 4 +++-
src/parser.cpp | 2 --
src/proc.cpp | 12 +++++++---
10 files changed, 25 insertions(+), 74 deletions(-)
diff --git a/src/builtin.cpp b/src/builtin.cpp
index f4de72c73..dd67817a3 100644
--- a/src/builtin.cpp
+++ b/src/builtin.cpp
@@ -3925,6 +3925,8 @@ static int builtin_history(parser_t &parser, io_streams_t &streams, wchar_t **ar
return STATUS_BUILTIN_ERROR;
}
+#if 0
+// Disabled for the 2.2.0 release: https://github.com/fish-shell/fish-shell/issues/1809.
int builtin_parse(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
struct sigaction act;
@@ -3966,6 +3968,7 @@ int builtin_parse(parser_t &parser, io_streams_t &streams, wchar_t **argv)
}
return STATUS_BUILTIN_OK;
}
+#endif
int builtin_true(parser_t &parser, io_streams_t &streams, wchar_t **argv)
{
@@ -3992,6 +3995,7 @@ static const builtin_data_t builtin_datas[]=
{
{ L"[", &builtin_test, N_(L"Test a condition") },
#if 0
+ // Disabled for the 2.2.0 release: https://github.com/fish-shell/fish-shell/issues/1809.
{ L"__fish_parse", &builtin_parse, N_(L"Try out the new parser") },
#endif
{ L"and", &builtin_generic, N_(L"Execute command if previous command suceeded") },
diff --git a/src/common.cpp b/src/common.cpp
index a796baca1..84c3de65a 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -689,11 +689,6 @@ void debug(int level, const char *msg, ...)
errno = errno_old;
}
-void print_stderr(const wcstring &str)
-{
- fprintf(stderr, "%ls\n", str.c_str());
-}
-
void read_ignore(int fd, void *buff, size_t count)
{
size_t ignore __attribute__((unused));
diff --git a/src/common.h b/src/common.h
index 74640988c..d6eb01910 100644
--- a/src/common.h
+++ b/src/common.h
@@ -811,9 +811,6 @@ ssize_t read_loop(int fd, void *buff, size_t count);
void debug(int level, const char *msg, ...);
void debug(int level, const wchar_t *msg, ...);
-/** Writes a string to stderr, followed by a newline */
-void print_stderr(const wcstring &str);
-
/**
Replace special characters with backslash escape sequences. Newline is
replaced with \n, etc.
diff --git a/src/expand.cpp b/src/expand.cpp
index c2b4258c8..de67ffa84 100644
--- a/src/expand.cpp
+++ b/src/expand.cpp
@@ -1998,62 +1998,6 @@ bool fish_xdm_login_hack_hack_hack_hack(std::vector *cmds, int argc
return result;
}
-bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector *args)
-{
- static signed char isSUSE = -1;
- if (isSUSE == 0)
- return false;
-
- bool result = false;
- if (args && ! args->empty())
- {
- const wcstring &cmd = args->at(0).completion;
- if (cmd.find(L"DBUS_SESSION_BUS_") != wcstring::npos)
- {
- /* See if we are SUSE */
- if (isSUSE < 0)
- {
- struct stat buf = {};
- isSUSE = (0 == stat("/etc/SuSE-release", &buf));
- }
-
- if (isSUSE)
- {
- /* Look for an equal sign */
- size_t where = cmd.find(L'=');
- if (where != wcstring::npos)
- {
- /* Oh my. It's presumably of the form foo=bar; find the = and split */
- const wcstring key = wcstring(cmd, 0, where);
-
- /* Trim whitespace and semicolon */
- wcstring val = wcstring(cmd, where+1);
- size_t last_good = val.find_last_not_of(L"\n ;");
- if (last_good != wcstring::npos)
- val.resize(last_good + 1);
-
- args->clear();
- append_completion(args, L"set");
- if (key == L"DBUS_SESSION_BUS_ADDRESS")
- append_completion(args, L"-x");
- append_completion(args, key);
- append_completion(args, val);
- result = true;
- }
- else if (string_prefixes_string(L"export DBUS_SESSION_BUS_ADDRESS;", cmd))
- {
- /* Nothing, we already exported it */
- args->clear();
- append_completion(args, L"echo");
- append_completion(args, L"-n");
- result = true;
- }
- }
- }
- }
- return result;
-}
-
bool expand_abbreviation(const wcstring &src, wcstring *output)
{
if (src.empty())
diff --git a/src/expand.h b/src/expand.h
index 731acd711..6ae91cca3 100644
--- a/src/expand.h
+++ b/src/expand.h
@@ -168,7 +168,6 @@ bool expand_abbreviation(const wcstring &src, wcstring *output);
/* Terrible hacks */
bool fish_xdm_login_hack_hack_hack_hack(std::vector *cmds, int argc, const char * const *argv);
-bool fish_openSUSE_dbus_hack_hack_hack_hack(std::vector *args);
#endif
diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp
index 5bacab80e..9afb43441 100644
--- a/src/fish_tests.cpp
+++ b/src/fish_tests.cpp
@@ -2887,8 +2887,7 @@ public:
static void test_history(void);
static void test_history_merge(void);
static void test_history_formats(void);
- static void test_history_speed(void);
-
+ // static void test_history_speed(void);
static void test_history_races(void);
static void test_history_races_pound_on_history();
};
@@ -3378,6 +3377,8 @@ void history_tests_t::test_history_formats(void)
}
}
+#if 0
+// This test isn't run at this time. It was added by commit b9283d48 but not actually enabled.
void history_tests_t::test_history_speed(void)
{
say(L"Testing history speed (pid is %d)", getpid());
@@ -3403,6 +3404,7 @@ void history_tests_t::test_history_speed(void)
hist->clear();
delete hist;
}
+#endif
static void test_new_parser_correctness(void)
{
@@ -4483,8 +4485,8 @@ int main(int argc, char **argv)
if (should_test_function("history_merge")) history_tests_t::test_history_merge();
if (should_test_function("history_races")) history_tests_t::test_history_races();
if (should_test_function("history_formats")) history_tests_t::test_history_formats();
- //history_tests_t::test_history_speed();
if (should_test_function("string")) test_string();
+ // history_tests_t::test_history_speed();
say(L"Encountered %d errors in low-level tests", err_count);
if (s_test_run_count == 0)
diff --git a/src/io.cpp b/src/io.cpp
index da326f559..614528305 100644
--- a/src/io.cpp
+++ b/src/io.cpp
@@ -183,6 +183,9 @@ void io_chain_t::append(const io_chain_t &chain)
this->insert(this->end(), chain.begin(), chain.end());
}
+#if 0
+// This isn't used so the lint tools were complaining about its presence. I'm keeping it in the
+// source because it could be useful for debugging.
void io_print(const io_chain_t &chain)
{
if (chain.empty())
@@ -206,6 +209,7 @@ void io_print(const io_chain_t &chain)
}
}
}
+#endif
/* If the given fd is used by the io chain, duplicates it repeatedly until an fd not used in the io chain is found, or we run out. If we return a new fd or an error, closes the old one. Any fd created is marked close-on-exec. Returns -1 on failure (in which case the given fd is still closed). */
static int move_fd_to_unused(int fd, const io_chain_t &io_chain)
diff --git a/src/io.h b/src/io.h
index adc59be17..181099adf 100644
--- a/src/io.h
+++ b/src/io.h
@@ -304,7 +304,9 @@ struct io_streams_t
}
};
-/** Print debug information about the specified IO redirection chain to stderr. */
+#if 0
+// Print debug information about the specified IO redirection chain to stderr.
void io_print(const io_chain_t &chain);
+#endif
#endif
diff --git a/src/parser.cpp b/src/parser.cpp
index 2097aecf6..2862df609 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -842,8 +842,6 @@ int parser_t::eval_acquiring_tree(const wcstring &cmd, const io_chain_t &io, enu
return 0;
}
- //print_stderr(block_stack_description());
-
/* Determine the initial eval level. If this is the first context, it's -1; otherwise it's the eval level of the top context. This is sort of wonky because we're stitching together a global notion of eval level from these separate objects. A better approach would be some profile object that all contexts share, and that tracks the eval levels on its own. */
int exec_eval_level = (execution_contexts.empty() ? -1 : execution_contexts.back()->current_eval_level());
diff --git a/src/proc.cpp b/src/proc.cpp
index f5c833e2a..1a0d64792 100644
--- a/src/proc.cpp
+++ b/src/proc.cpp
@@ -94,15 +94,21 @@ size_t job_iterator_t::count() const
return this->job_list->size();
}
+#if 0
+// This isn't used so the lint tools were complaining about its presence. I'm keeping it in the
+// source because it could be useful for debugging. However, it would probably be better to add a
+// verbose or debug option to the builtin `jobs` command.
void print_jobs(void)
{
job_iterator_t jobs;
job_t *j;
- while ((j = jobs.next()))
- {
- printf("%p -> %ls -> (foreground %d, complete %d, stopped %d, constructed %d)\n", j, j->command_wcstr(), job_get_flag(j, JOB_FOREGROUND), job_is_completed(j), job_is_stopped(j), job_get_flag(j, JOB_CONSTRUCTED));
+ while (j = jobs.next()) {
+ printf("%p -> %ls -> (foreground %d, complete %d, stopped %d, constructed %d)\n",
+ j, j->command_wcstr(), job_get_flag(j, JOB_FOREGROUND), job_is_completed(j),
+ job_is_stopped(j), job_get_flag(j, JOB_CONSTRUCTED));
}
}
+#endif
int is_interactive_session=0;
int is_subshell=0;
From 411d573ba986af636e01dc07796954385b8ba4c7 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Sun, 3 Apr 2016 20:23:43 -0700
Subject: [PATCH 053/363] convert atypical env_universal_common logging
This is a quick and dirty conversion of the atypical, and undocumented,
logging done by env_universal_common.cpp to the usual `debug()` pattern. I
didn't want to drop the messages because they could be useful when
debugging future issues. So I simply converted them to the lowest debug
level using the normal debug() function.
Fixes #2887
---
src/env_universal_common.cpp | 34 ++++++++++++++--------------------
src/env_universal_common.h | 6 ------
2 files changed, 14 insertions(+), 26 deletions(-)
diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp
index 71fb1667d..a3815886a 100644
--- a/src/env_universal_common.cpp
+++ b/src/env_universal_common.cpp
@@ -498,7 +498,7 @@ void env_universal_t::load_from_fd(int fd, callback_data_list_t *callbacks)
const file_id_t current_file = file_id_for_fd(fd);
if (current_file == last_read_file)
{
- UNIVERSAL_LOG("Sync elided based on fstat()");
+ debug(5, L"universal log sync elided based on fstat()");
}
else
{
@@ -525,7 +525,7 @@ bool env_universal_t::load_from_path(const wcstring &path, callback_data_list_t
/* Check to see if the file is unchanged. We do this again in load_from_fd, but this avoids opening the file unnecessarily. */
if (last_read_file != kInvalidFileID && file_id_for_path(path) == last_read_file)
{
- UNIVERSAL_LOG("Sync elided based on fast stat()");
+ debug(5, L"universal log sync elided based on fast stat()");
return true;
}
@@ -533,7 +533,7 @@ bool env_universal_t::load_from_path(const wcstring &path, callback_data_list_t
int fd = wopen_cloexec(path, O_RDONLY);
if (fd >= 0)
{
- UNIVERSAL_LOG("Reading from file");
+ debug(5, L"universal log reading from file");
this->load_from_fd(fd, callbacks);
close(fd);
result = true;
@@ -788,7 +788,7 @@ bool env_universal_t::open_and_acquire_lock(const wcstring &path, int *out_fd)
/* Returns true if modified variables were written, false if not. (There may still be variable changes due to other processes on a false return). */
bool env_universal_t::sync(callback_data_list_t *callbacks)
{
- UNIVERSAL_LOG("sync");
+ debug(5, L"universal log sync");
scoped_lock locker(lock);
/* Our saving strategy:
@@ -810,7 +810,7 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
const wcstring &vars_path = explicit_vars_path.empty() ? default_vars_path() : explicit_vars_path;
if (vars_path.empty()) {
- debug(2, "No universal variable path available");
+ debug(2, L"No universal variable path available");
return false;
}
@@ -818,7 +818,7 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
if (modified.empty())
{
this->load_from_path(vars_path, callbacks);
- UNIVERSAL_LOG("No modifications");
+ debug(5, L"universal log no modifications");
return false;
}
@@ -828,13 +828,13 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
int private_fd = -1;
wcstring private_file_path;
- UNIVERSAL_LOG("Performing full sync");
+ debug(5, L"universal log performing full sync");
/* Open the file */
if (success)
{
success = this->open_and_acquire_lock(vars_path, &vars_fd);
- if (! success) UNIVERSAL_LOG("open_and_acquire_lock() failed");
+ if (! success) debug(5, L"universal log open_and_acquire_lock() failed");
}
/* Read from it */
@@ -849,7 +849,7 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
if (success)
{
success = this->open_temporary_file(directory, &private_file_path, &private_fd);
- if (! success) UNIVERSAL_LOG("open_temporary_file() failed");
+ if (! success) debug(5, L"universal log open_temporary_file() failed");
}
/* Write to it */
@@ -857,7 +857,7 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
{
assert(private_fd >= 0);
success = this->write_to_fd(private_fd, private_file_path);
- if (! success) UNIVERSAL_LOG("write_to_fd() failed");
+ if (! success) debug(5, L"universal log write_to_fd() failed");
}
if (success)
@@ -867,9 +867,9 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
if (wstat(vars_path, &sbuf) >= 0)
{
if (fchown(private_fd, sbuf.st_uid, sbuf.st_gid) == -1)
- UNIVERSAL_LOG("fchown() failed");
+ debug(5, L"universal log fchown() failed");
if (fchmod(private_fd, sbuf.st_mode) == -1)
- UNIVERSAL_LOG("fchmod() failed");
+ debug(5, L"universal log fchmod() failed");
}
/* Linux by default stores the mtime with low precision, low enough that updates that occur in quick succession may
@@ -890,7 +890,7 @@ bool env_universal_t::sync(callback_data_list_t *callbacks)
/* Apply new file */
success = this->move_new_vars_file_into_place(private_file_path, vars_path);
- if (! success) UNIVERSAL_LOG("move_new_vars_file_into_place() failed");
+ if (! success) debug(5, L"universal log move_new_vars_file_into_place() failed");
}
if (success)
@@ -983,7 +983,7 @@ void env_universal_t::parse_message_internal(const wcstring &msgstr, var_table_t
{
const wchar_t *msg = msgstr.c_str();
- // debug( 3, L"parse_message( %ls );", msg );
+ // debug(3, L"parse_message( %ls );", msg);
if (msg[0] == L'#')
return;
@@ -1745,9 +1745,3 @@ static bool bool_from_env_var(const char *name, bool default_value)
const char *var = getenv(name);
return var ? from_string(var) : default_value;
}
-
-bool universal_log_enabled()
-{
- return bool_from_env_var(UNIVERSAL_LOGGING_ENV_NAME, false);
-}
-
diff --git a/src/env_universal_common.h b/src/env_universal_common.h
index 60cf00278..edc360167 100644
--- a/src/env_universal_common.h
+++ b/src/env_universal_common.h
@@ -167,13 +167,7 @@ class universal_notifier_t
virtual bool notification_fd_became_readable(int fd);
};
-bool universal_log_enabled();
-#define UNIVERSAL_LOG(x) do { if (universal_log_enabled()) fprintf(stderr, "UNIVERSAL LOG: %s\n", x); } while (0)
-
/* Environment variable for requesting a particular universal notifier. See fetch_default_strategy_from_environment for names. */
#define UNIVERSAL_NOTIFIER_ENV_NAME "fish_universal_notifier"
-/* Environment variable for enabling universal variable logging (to stderr) */
-#define UNIVERSAL_LOGGING_ENV_NAME "fish_universal_log"
-
#endif
From 0953590cca7cdc2dab75af5a85c8e2f15d4b8ab2 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Mon, 4 Apr 2016 18:22:48 +0200
Subject: [PATCH 054/363] cd completion: No description for absolute paths
This also removes the "pushd/popd" dance and only executes the CDPATH
stuff when we need to.
---
share/functions/__fish_complete_cd.fish | 46 +++++++++++++++----------
1 file changed, 27 insertions(+), 19 deletions(-)
diff --git a/share/functions/__fish_complete_cd.fish b/share/functions/__fish_complete_cd.fish
index ac871d224..cdbd02a78 100644
--- a/share/functions/__fish_complete_cd.fish
+++ b/share/functions/__fish_complete_cd.fish
@@ -1,24 +1,32 @@
function __fish_complete_cd -d "Completions for the cd command"
- set -l cdpath $CDPATH
- [ -z "$cdpath" ]; and set cdpath "."
- # Remove the real path to "." (i.e. $PWD) from cdpath if we're in it
- # so it doesn't get printed in the descriptions
- set -l ind
- if begin; set ind (contains -i -- $PWD $cdpath)
- and contains -- "." $cdpath
- end
- set -e cdpath[$ind]
- end
- for i in $cdpath
- set -l desc
- # Don't show description for current directory
- # and replace $HOME with "~"
- [ $i = "." ]; or set -l desc (string replace -r -- "^$HOME" "~" "$i")
- pushd $i
- for d in (commandline -ct)*/
+ set -l token (commandline -ct)
+ # Absolute path - no descriptions and no CDPATH
+ if string match -q '/*' -- $token
+ for d in $token*/
# Check if it's accessible - the glob only matches directories
- [ -x $d ]; and printf "%s\t%s\n" $d $desc
+ [ -x $d ]; and printf "%s\n" $d
+ end
+ else # Relative path - check $CDPATH and use that as description
+ set -l cdpath $CDPATH
+ [ -z "$cdpath" ]; and set cdpath "."
+ # Remove the real path to "." (i.e. $PWD) from cdpath if we're in it
+ # so it doesn't get printed in the descriptions
+ if set -l ind (contains -i -- $PWD $cdpath)
+ and contains -- "." $cdpath
+ set -e cdpath[$ind]
+ end
+ # TODO: There's a subtlety regarding descriptions - if $cdpath[1]/foo and $cdpath[2]/foo exist, we print both
+ # but want the first description to win - this currently works, but is not guaranteed
+ for i in $cdpath
+ set -l desc
+ # Don't show description for current directory
+ # and replace $HOME with "~"
+ [ $i = "." ]; or set -l desc (string replace -r -- "^$HOME" "~" "$i")
+ # This assumes the CDPATH component itself is cd-able
+ for d in $i/$token*/
+ # Remove the cdpath component again
+ [ -x $d ]; and printf "%s\t%s\n" (string replace -r "^$i/" "" -- $d) $desc
+ end
end
- popd
end
end
From 47f1a92cc4c3c7056f4172974f10a8dd402cf55c Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Mon, 4 Apr 2016 14:34:28 -0700
Subject: [PATCH 055/363] fixes for cppcheck lint warnings
Refine the linting behavior.
Fix several of the, mostly trivial, lint errors.
---
build_tools/lint.fish | 18 ++++++++++----
src/builtin_string.cpp | 5 ++--
src/common.cpp | 6 -----
src/env_universal_common.cpp | 46 +++++++++++++++++-------------------
src/fish_tests.cpp | 6 ++---
src/key_reader.cpp | 4 ++--
src/parse_tree.cpp | 5 ++--
src/parse_util.cpp | 6 +++--
src/wgetopt.cpp | 4 ++--
9 files changed, 51 insertions(+), 49 deletions(-)
diff --git a/build_tools/lint.fish b/build_tools/lint.fish
index 3fd90b244..09ab6f462 100755
--- a/build_tools/lint.fish
+++ b/build_tools/lint.fish
@@ -57,8 +57,14 @@ if set -q c_files[1]
echo ========================================
echo Running cppcheck
echo ========================================
+ # The stderr to stdout redirection is because cppcheck, incorrectly
+ # IMHO, writes its diagnostic messages to stderr. Anyone running
+ # this who wants to capture its output will expect those messages to be
+ # written to stdout.
cppcheck -q --verbose --std=posix --std=c11 --language=c++ \
- --inline-suppr --enable=$cppchecks $cppcheck_args $c_files
+ --template "[{file}:{line}]: {severity} ({id}): {message}" \
+ --suppress=missingIncludeSystem \
+ --inline-suppr --enable=$cppchecks $cppcheck_args $c_files 2>&1
end
if type -q oclint
@@ -66,6 +72,10 @@ if set -q c_files[1]
echo ========================================
echo Running oclint
echo ========================================
+ # The stderr to stdout redirection is because oclint, incorrectly
+ # writes its final summary counts of the errors detected to stderr.
+ # Anyone running this who wants to capture its output will expect those
+ # messages to be written to stdout.
if test (uname -s) = "Darwin"
if not test -f compile_commands.json
xcodebuild > xcodebuild.log
@@ -73,19 +83,19 @@ if set -q c_files[1]
end
if test $all = yes
oclint-json-compilation-database -e '/pcre2-10.20/' \
- -- -enable-global-analysis
+ -- -enable-global-analysis 2>&1
else
set i_files
for f in $c_files
set i_files $i_files -i $f
end
echo oclint-json-compilation-database -e '/pcre2-10.20/' $i_files
- oclint-json-compilation-database -e '/pcre2-10.20/' $i_files
+ oclint-json-compilation-database -e '/pcre2-10.20/' $i_files 2>&1
end
else
# Presumably we're on Linux or other platform not requiring special
# handling for oclint to work.
- oclint $c_files -- $argv
+ oclint $c_files -- $argv 2>&1
end
end
else
diff --git a/src/builtin_string.cpp b/src/builtin_string.cpp
index ab864e88d..8911d1ab0 100644
--- a/src/builtin_string.cpp
+++ b/src/builtin_string.cpp
@@ -794,7 +794,7 @@ public:
size_t arglen = wcslen(arg);
PCRE2_SIZE bufsize = (arglen == 0) ? 16 : 2 * arglen;
wchar_t *output = (wchar_t *)malloc(sizeof(wchar_t) * bufsize);
- if (output == 0)
+ if (output == NULL)
{
DIE_MEM();
}
@@ -820,8 +820,9 @@ public:
if (bufsize < MAX_REPLACE_SIZE)
{
bufsize = std::min(2 * bufsize, MAX_REPLACE_SIZE);
+ // cppcheck-suppress memleakOnRealloc
output = (wchar_t *)realloc(output, sizeof(wchar_t) * bufsize);
- if (output == 0)
+ if (output == NULL)
{
DIE_MEM();
}
diff --git a/src/common.cpp b/src/common.cpp
index 84c3de65a..545288fc0 100644
--- a/src/common.cpp
+++ b/src/common.cpp
@@ -1111,12 +1111,6 @@ static void escape_string_internal(const wchar_t *orig_in, size_t in_len, wcstri
wcstring escape(const wchar_t *in, escape_flags_t flags)
{
- if (!in)
- {
- debug(0, L"%s called with null input", __func__);
- FATAL_EXIT();
- }
-
wcstring result;
escape_string_internal(in, wcslen(in), &result, flags);
return result;
diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp
index a3815886a..751136159 100644
--- a/src/env_universal_common.cpp
+++ b/src/env_universal_common.cpp
@@ -663,47 +663,44 @@ bool env_universal_t::load()
return success;
}
-bool env_universal_t::open_temporary_file(const wcstring &directory, wcstring *out_path, int *out_fd)
+bool env_universal_t::open_temporary_file(const wcstring &directory, wcstring *out_path,
+ int *out_fd)
{
- /* Create and open a temporary file for writing within the given directory */
- /* Try to create a temporary file, up to 10 times. We don't use mkstemps because we want to open it CLO_EXEC. This should almost always succeed on the first try. */
- assert(! string_suffixes_string(L"/", directory));
-
+ // Create and open a temporary file for writing within the given directory. Try to create a
+ // temporary file, up to 10 times. We don't use mkstemps because we want to open it CLO_EXEC.
+ // This should almost always succeed on the first try.
+ assert(!string_suffixes_string(L"/", directory));
+
bool success = false;
+ int saved_errno;
const wcstring tmp_name_template = directory + L"/fishd.tmp.XXXXXX";
wcstring tmp_name;
+
for (size_t attempt = 0; attempt < 10 && ! success; attempt++)
{
int result_fd = -1;
char *narrow_str = wcs2str(tmp_name_template.c_str());
#if HAVE_MKOSTEMP
result_fd = mkostemp(narrow_str, O_CLOEXEC);
- if (result_fd >= 0)
- {
- tmp_name = str2wcstring(narrow_str);
- }
#else
- if (mktemp(narrow_str))
+ // cppcheck-suppress redundantAssignment
+ result_fd = mkstemp(narrow_str);
+ if (result_fd != -1)
{
- /* It was successfully templated; try opening it atomically */
- tmp_name = str2wcstring(narrow_str);
- result_fd = wopen_cloexec(tmp_name, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, 0644);
+ fcntl(result_fd, F_SETFD, O_CLOEXEC);
}
#endif
-
- if (result_fd >= 0)
- {
- /* Success */
- *out_fd = result_fd;
- *out_path = str2wcstring(narrow_str);
- success = true;
- }
+
+ saved_errno = errno;
+ success = result_fd != -1;
+ *out_fd = result_fd;
+ *out_path = str2wcstring(narrow_str);
free(narrow_str);
}
- if (! success)
+
+ if (!success)
{
- int err = errno;
- report_error(err, L"Unable to open file '%ls'", tmp_name.c_str());
+ report_error(saved_errno, L"Unable to open file '%ls'", out_path->c_str());
}
return success;
}
@@ -1228,6 +1225,7 @@ class universal_notifier_shmem_poller_t : public universal_notifier_t
/* Read the current seed */
this->poll();
+ // cppcheck-suppress memleak // addr not really leaked
}
public:
diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp
index 9afb43441..6250513cb 100644
--- a/src/fish_tests.cpp
+++ b/src/fish_tests.cpp
@@ -458,10 +458,8 @@ static void test_tok()
if (types[i] != token.type)
{
err(L"Tokenization error:");
- wprintf(L"Token number %d of string \n'%ls'\n, got token type %ld\n",
- i+1,
- str,
- (long)token.type);
+ wprintf(L"Token number %zu of string \n'%ls'\n, got token type %ld\n",
+ i + 1, str, (long)token.type);
}
i++;
}
diff --git a/src/key_reader.cpp b/src/key_reader.cpp
index 382f4b229..1cb3b3de4 100644
--- a/src/key_reader.cpp
+++ b/src/key_reader.cpp
@@ -82,9 +82,9 @@ int main(int argc, char **argv)
if ((c=input_common_readch(0)) == EOF)
break;
if ((c > 31) && (c != 127))
- sprintf(scratch, "dec: %d hex: %x char: %c\n", c, c, c);
+ sprintf(scratch, "dec: %u hex: %x char: %c\n", c, c, c);
else
- sprintf(scratch, "dec: %d hex: %x\n", c, c);
+ sprintf(scratch, "dec: %u hex: %x\n", c, c);
writestr(scratch);
}
/* reset the terminal to the saved mode */
diff --git a/src/parse_tree.cpp b/src/parse_tree.cpp
index 5939e270d..51ae77202 100644
--- a/src/parse_tree.cpp
+++ b/src/parse_tree.cpp
@@ -690,7 +690,7 @@ void parse_ll_t::dump_stack(void) const
}
}
- fprintf(stderr, "Stack dump (%lu elements):\n", symbol_stack.size());
+ fprintf(stderr, "Stack dump (%zu elements):\n", symbol_stack.size());
for (size_t idx = 0; idx < lines.size(); idx++)
{
fprintf(stderr, " %ls\n", lines.at(idx).c_str());
@@ -1685,9 +1685,8 @@ enum parse_bool_statement_type_t parse_node_tree_t::statement_boolean_type(const
bool parse_node_tree_t::job_should_be_backgrounded(const parse_node_t &job) const
{
assert(job.type == symbol_job);
- bool result = false;
const parse_node_t *opt_background = get_child(job, 2, symbol_optional_background);
- result = opt_background != NULL && opt_background->tag == parse_background;
+ bool result = opt_background != NULL && opt_background->tag == parse_background;
return result;
}
diff --git a/src/parse_util.cpp b/src/parse_util.cpp
index 628e86c59..73db28339 100644
--- a/src/parse_util.cpp
+++ b/src/parse_util.cpp
@@ -1020,14 +1020,16 @@ static const wchar_t *error_format_for_character(wchar_t wc)
void parse_util_expand_variable_error(const wcstring &token, size_t global_token_pos, size_t dollar_pos, parse_error_list_t *errors)
{
- // Note that dollar_pos is probably VARIABLE_EXPAND or VARIABLE_EXPAND_SINGLE, not a literal dollar sign
+ // Note that dollar_pos is probably VARIABLE_EXPAND or VARIABLE_EXPAND_SINGLE,
+ // not a literal dollar sign.
assert(errors != NULL);
assert(dollar_pos < token.size());
const bool double_quotes = (token.at(dollar_pos) == VARIABLE_EXPAND_SINGLE);
const size_t start_error_count = errors->size();
const size_t global_dollar_pos = global_token_pos + dollar_pos;
const size_t global_after_dollar_pos = global_dollar_pos + 1;
- wchar_t char_after_dollar = (dollar_pos + 1 >= token.size() ? L'\0' : token.at(dollar_pos + 1));
+ wchar_t char_after_dollar = dollar_pos + 1 >= token.size() ? 0 : token.at(dollar_pos + 1);
+
switch (char_after_dollar)
{
case BRACKET_BEGIN:
diff --git a/src/wgetopt.cpp b/src/wgetopt.cpp
index c2905ab0a..7951eaea0 100644
--- a/src/wgetopt.cpp
+++ b/src/wgetopt.cpp
@@ -515,7 +515,7 @@ int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *opts
{
if (wopterr)
{
- fwprintf(stderr, _(L"%ls: Invalid option -- %lc\n"), argv[0], c);
+ fwprintf(stderr, _(L"%ls: Invalid option -- %lc\n"), argv[0], (wint_t)c);
}
woptopt = c;
@@ -554,7 +554,7 @@ int wgetopter_t::_wgetopt_internal(int argc, wchar_t **argv, const wchar_t *opts
{
/* 1003.2 specifies the format of this message. */
fwprintf(stderr, _(L"%ls: Option requires an argument -- %lc\n"),
- argv[0], c);
+ argv[0], (wint_t)c);
}
woptopt = c;
if (optstring[0] == ':')
From cb6d5d76c8232264f66c9a1db895d9dd69d77bc3 Mon Sep 17 00:00:00 2001
From: Mark Griffiths
Date: Mon, 4 Apr 2016 13:43:37 +0100
Subject: [PATCH 056/363] update lexicon for latest docs
Closes #2699
Fixes issues with:
* 'string' function synopsis
* Redirection display issues
* Better file & path detection
* Rendering of % & @ chars in both html and man
* @ symbol in tutorial
Improves robustness by implementing an @EOL marker to prevent hold buffer dumping extra chars after the end of an expression.
Added new '{{' and '}}' meta-chars for when you want curly braces in a regexp that was previously tripping up the lexicon.
Improve man/html presentation consistency for
* string
* printf
* prompt_pwd
* type
Use cli-styling for 'practical' examples.
Add tag for presenting content with preceding backslash.
Signed-off-by: Mark Griffiths
---
Doxyfile | 2 +
Doxyfile.help | 2 +
Doxyfile.user | 2 +
Makefile.in | 8 +-
doc_src/FORMATTING.md | 2 +
doc_src/fish_right_prompt.txt | 2 +-
doc_src/index.hdr.in | 28 +++--
doc_src/printf.txt | 2 +-
doc_src/prompt_pwd.txt | 13 +-
doc_src/string.txt | 226 +++++++++++++++-------------------
doc_src/type.txt | 6 +-
doc_src/user_doc.css | 2 +-
lexicon_filter.in | 56 ++++++---
13 files changed, 180 insertions(+), 171 deletions(-)
diff --git a/Doxyfile b/Doxyfile
index d12875a58..cf025f1b1 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -274,6 +274,8 @@ ALIASES += "span{2}=\2"
ALIASES += "spcl{2}=\2"
ALIASES += "bksl{1}=\\\1"
+ALIASES += "pcnt{1}=\%\1"
+ALIASES += "atat{1}=\@"
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
diff --git a/Doxyfile.help b/Doxyfile.help
index 979074144..ec4a97c44 100644
--- a/Doxyfile.help
+++ b/Doxyfile.help
@@ -274,6 +274,8 @@ ALIASES += "span{2}=\2"
ALIASES += "spcl{2}=\2"
ALIASES += "bksl{1}=\\\1"
+ALIASES += "pcnt{1}=\%\1"
+ALIASES += "atat{1}=\@"
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
diff --git a/Doxyfile.user b/Doxyfile.user
index 96c3bc228..ea2752465 100644
--- a/Doxyfile.user
+++ b/Doxyfile.user
@@ -274,6 +274,8 @@ ALIASES += "span{2}=\2"
ALIASES += "spcl{2}=\2"
ALIASES += "bksl{1}=\\1"
+ALIASES += "pcnt{1}=%\1"
+ALIASES += "atat{1}=@"
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
diff --git a/Makefile.in b/Makefile.in
index 98b8a11ca..ede69b0fd 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -103,7 +103,7 @@ FISH_OBJS := obj/function.o obj/builtin.o obj/complete.o obj/env.o obj/exec.o \
obj/parse_productions.o obj/parse_execution.o obj/pager.o obj/utf8.o \
obj/fish_version.o obj/wcstringutil.o
-FISH_INDENT_OBJS := obj/fish_indent.o obj/print_help.o $(FISH_OBJS)
+FISH_INDENT_OBJS := obj/fish_indent.o obj/print_help.o $(FISH_OBJS)
#
# Additional files used by builtin.o
@@ -276,9 +276,9 @@ doc: $(HDR_FILES_SRC) Doxyfile.user $(HTML_SRC) $(HELP_SRC) doc.h \
(cat Doxyfile.user; echo INPUT_FILTER=./lexicon_filter; \
echo PROJECT_NUMBER=$(FISH_BUILD_VERSION) | $(SED) "s/-.*//") | \
doxygen - && touch user_doc; \
- cd user_doc/html && rm -f bc_s.png bdwn.png closed.png ftv2*.png \
- nav*.png open.png sync_*.png tab*.* doxygen.* dynsections.js \
- jquery.js pages.html
+ cd user_doc/html && rm -f arrow*.png bc_s.png bdwn.png closed.png \
+ doc.png folder*.png ftv2*.png nav*.png open.png splitbar.png \
+ sync_*.png tab*.* doxygen.* dynsections.js jquery.js pages.html
#
# PDF version of the source code documentation.
diff --git a/doc_src/FORMATTING.md b/doc_src/FORMATTING.md
index 0ae1c81e1..df6de6f8d 100644
--- a/doc_src/FORMATTING.md
+++ b/doc_src/FORMATTING.md
@@ -160,6 +160,8 @@ The following can be used in \\fish blocks to render some fish scenarios. These
- ``: \This would be shown as an error.\
- ``: \This test will not be parsed for fish markup.\
- ``: \This would be rendered as command/script output.\
+- ``: Render the contents with a preceding backslash. Useful when presenting output.
+- `{{` and `}}`: Required when wanting curly braces in regular expression example.
### Prompts and cursors
diff --git a/doc_src/fish_right_prompt.txt b/doc_src/fish_right_prompt.txt
index 21b4a1954..87de31139 100644
--- a/doc_src/fish_right_prompt.txt
+++ b/doc_src/fish_right_prompt.txt
@@ -20,7 +20,7 @@ A simple right prompt:
\fish
function fish_right_prompt -d "Write out the right prompt"
- date "+%m/%d/%y"
+ date '+%m/%d/%y'
end
\endfish
diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index 15c67c379..a42fb6498 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -528,22 +528,24 @@ The above code demonstrates how to use multiple '`$`' symbols to expand the valu
Lists adjacent to other lists or strings are expanded as cartesian products:
Examples:
-\fish
-echo {good,bad}" apples"
-# Outputs 'good apples bad apples'
+\fish{cli-dark}
+>_ echo {good,bad}" apples"
+good apples bad apples
-set -l a x y z
-set -l b 1 2 3
-echo $a$b
-# Outputs 'x1 y1 z1 x2 y2 z2 x3 y3 z3'
-echo $a"-"$b
-# Outputs 'x-1 y-1 z-1 x-2 y-2 z-2 x-3 y-3 z-3'
+>_ set -l a x y z
+>_ set -l b 1 2 3
-echo {x,y,z}$b
-# Outputs 'x1 y1 z1 x2 y2 z2 x3 y3 z3'
+>_ echo $a$b
+x1 y1 z1 x2 y2 z2 x3 y3 z3
-echo {$b}word
-# Outputs '1word 2word 3word'
+>_ echo $a"-"$b
+x-1 y-1 z-1 x-2 y-2 z-2 x-3 y-3 z-3
+
+>_ echo {x,y,z}$b
+x1 y1 z1 x2 y2 z2 x3 y3 z3
+
+>_ echo {$b}word
+1word 2word 3word
\endfish
Be careful when you try to use braces to separate variable names from text. The dangers noted in the last example above can be avoided by wrapping the variable in double quotes instead of braces (`echo "$b"word`).
diff --git a/doc_src/printf.txt b/doc_src/printf.txt
index ce7796c85..5e22db986 100644
--- a/doc_src/printf.txt
+++ b/doc_src/printf.txt
@@ -60,7 +60,7 @@ This file has been imported from the printf in GNU Coreutils version 6.9. If you
\subsection printf-example Example
\fish
-printf '\%s\\t\%s\n' flounder fish
+printf '%s\\t%s\\n' flounder fish
\endfish
Will print "flounder fish" (separated with a tab character), followed by a newline character. This is useful for writing completions, as fish expects completion scripts to output the option followed by the description, separated with a tab character.
diff --git a/doc_src/prompt_pwd.txt b/doc_src/prompt_pwd.txt
index 7161d8aa9..0eafbf994 100644
--- a/doc_src/prompt_pwd.txt
+++ b/doc_src/prompt_pwd.txt
@@ -13,16 +13,19 @@ To change the number of characters per path component, set $fish_prompt_pwd_dir_
\subsection prompt_pwd-example Examples
-\fish
+\fish{cli-dark}
>_ cd ~/
>_ echo $PWD
-/home/alfa
+/home/alfa
+
>_ prompt_pwd
-~
+~
+
>_ cd /tmp/banana/sausage/with/mustard
>_ prompt_pwd
-/t/b/s/w/mustard
+/t/b/s/w/mustard
+
>_ set -g fish_prompt_pwd_dir_length 3
>_ prompt_pwd
-/tmp/ban/sau/wit/mustard
+/tmp/ban/sau/wit/mustard
\endfish
diff --git a/doc_src/string.txt b/doc_src/string.txt
index 37d244353..fd77da945 100644
--- a/doc_src/string.txt
+++ b/doc_src/string.txt
@@ -3,18 +3,13 @@
\subsection string-synopsis Synopsis
\fish{synopsis}
string length [(-q | --quiet)] [STRING...]
-string sub [(-s | --start) START] [(-l | --length) LENGTH]
- [(-q | --quiet)] [STRING...]
-string split [(-m | --max) MAX] [(-r | --right)] [(-q | --quiet)]
- SEP [STRING...]
+string sub [(-s | --start) START] [(-l | --length) LENGTH] [(-q | --quiet)] [STRING...]
+string split [(-m | --max) MAX] [(-r | --right)] [(-q | --quiet)] SEP [STRING...]
string join [(-q | --quiet)] SEP [STRING...]
-string trim [(-l | --left)] [(-r | --right)] [(-c | --chars CHARS)]
- [(-q | --quiet)] [STRING...]
+string trim [(-l | --left)] [(-r | --right)] [(-c | --chars CHARS)] [(-q | --quiet)] [STRING...]
string escape [(-n | --no-quoted)] [STRING...]
-string match [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)]
- [(-n | --index)] [(-q | --quiet)] PATTERN [STRING...]
-string replace [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)]
- [(-q | --quiet)] PATTERN REPLACEMENT [STRING...]
+string match [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)] [(-n | --index)] [(-q | --quiet)] PATTERN [STRING...]
+string replace [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)] [(-q | --quiet)] PATTERN REPLACEMENT [STRING...]
\endfish
@@ -51,150 +46,129 @@ The following subcommands are available:
\subsection string-example Examples
-\fish
-string length 'hello, world'
-# Output:
-# 12
+\fish{cli-dark}
+>_ string length 'hello, world'
+12
-string length -q $str
+>_ set str foo
+>_ string length -q $str; echo $status
+1
# Equivalent to test -n $str
\endfish
-\fish
-string sub --length 2 abcde
-# Output:
-# ab
+\fish{cli-dark}
+>_ string sub --length 2 abcde
+ab
-string sub -s 2 -l 2 abcde
-# Output:
-# bc
+>_ string sub -s 2 -l 2 abcde
+bc
-string sub --start=-2 abcde
-# Output:
-# de
+>_ string sub --start=-2 abcde
+de
\endfish
-\fish
-string split . example.com
-# Output:
-# example
-# com
+\fish{cli-dark}
+>_ string split . example.com
+example
+com
-string split -r -m1 / /usr/local/bin/fish
-# Output:
-# /usr/local/bin
-# fish
+>_ string split -r -m1 / /usr/local/bin/fish
+/usr/local/bin
+fish
-string split '' abc
-# Output:
-# a
-# b
-# c
+>_ string split '' abc
+a
+b
+c
\endfish
-\fish
-seq 3 | string join ...
-# Output:
-# 1...2...3
+\fish{cli-dark}
+>_ seq 3 | string join ...
+1...2...3
\endfish
-\fish
-string trim ' abc '
-# Output:
-# abc
+\fish{cli-dark}
+>_ string trim ' abc '
+abc
-string trim --right --chars=yz xyzzy zany
-# Output:
-# x
-# zan
+>_ string trim --right --chars=yz xyzzy zany
+x
+zan
\endfish
-\fish
-echo \x07 | string escape
-# Output:
-# \\cg
+\fish{cli-dark}
+>_ echo \\x07 | string escape
+cg
\endfish
-\fish
-# string match glob examples
+\subsection string-example-match-glob Match Glob Examples
-string match '?' a
-# Output:
-# a
+\fish{cli-dark}
+>_ string match '?' a
+a
-string match 'a*b' axxb
-# Output:
-# axxb
+>_ string match 'a*b' axxb
+axxb
-string match -i 'a??B' Axxb
-# Output:
-# Axxb
+>_ string match -i 'a??B' Axxb
+Axxb
-echo 'ok?' | string match '*\\?'
-# Output:
-# ok?
-
-# string match regex examples
-
-string match -r 'cat|dog|fish' 'nice dog'
-# Output:
-# dog
-
-string match -r '(\\d\\d?):(\\d\\d):(\\d\\d)' 2:34:56
-# Output:
-# 2:34:56
-# 2
-# 34
-# 56
-
-string match -r '^(\\w{2,4})\\g1$' papa mud murmur
-# Output:
-# papa
-# pa
-# murmur
-# mur
-
-string match -r -a -n at ratatat
-# Output:
-# 2 2
-# 4 2
-# 6 2
-
-string match -r -i '0x[0-9a-f]{1,8}' 'int magic = 0xBadC0de;'
-# Output:
-# 0xBadC0de
+>_ echo 'ok?' | string match '*\\?'
+>_ ok?
\endfish
-\fish
+\subsection string-example-match-regex Match Regex Examples
-# string replace literal examples
+\fish{cli-dark}
+>_ string match -r 'cat|dog|fish' 'nice dog'
+dog
-string replace is was 'blue is my favorite'
-# Output:
-# blue was my favorite
+>_ string match -r '(\\d\\d?):(\\d\\d):(\\d\\d)' 2:34:56
+2:34:56
+2
+34
+56
-string replace 3rd last 1st 2nd 3rd
-# Output:
-# 1st
-# 2nd
-# last
+>_ string match -r '^(\\w{{2,4}})\\g1$' papa mud murmur
+papa
+pa
+murmur
+mur
-string replace -a ' ' _ 'spaces to underscores'
-# Output:
-# spaces_to_underscores
+>_ string match -r -a -n at ratatat
+2 2
+4 2
+6 2
-# string replace regex examples
-
-string replace -r -a '[^\\d.]+' ' ' '0 one two 3.14 four 5x'
-# Output:
-# 0 3.14 5
-
-string replace -r '(\\w+)\\s+(\\w+)' '$2 $1 $$' 'left right'
-# Output:
-# right left $
-
-string replace -r '\\s*newline\\s*' '\n' 'put a newline here'
-# Output:
-# put a
-# here
+>_ string match -r -i '0x[0-9a-f]{{1,8}}' 'int magic = 0xBadC0de;'
+0xBadC0de
+\endfish
+
+\subsection string-example-replace-literal Replace Literal Examples
+
+\fish{cli-dark}
+>_ string replace is was 'blue is my favorite'
+blue was my favorite
+
+>_ string replace 3rd last 1st 2nd 3rd
+1st
+2nd
+last
+
+>_ string replace -a ' ' _ 'spaces to underscores'
+spaces_to_underscores
+\endfish
+
+\subsection string-example-replace-Regex Replace Regex Examples
+
+\fish{cli-dark}
+>_ string replace -r -a '[^\\d.]+' ' ' '0 one two 3.14 four 5x'
+0 3.14 5
+
+>_ string replace -r '(\\w+)\\s+(\\w+)' '$2 $1 $$' 'left right'
+right left $
+
+>_ string replace -r '\\s*newline\\s*' '\\n' 'put a newline here'
+put a
+here
\endfish
diff --git a/doc_src/type.txt b/doc_src/type.txt
index 2f55d72ab..2da88c94d 100644
--- a/doc_src/type.txt
+++ b/doc_src/type.txt
@@ -26,7 +26,7 @@ The following options are available:
\subsection type-example Example
-\fish
-type fg
-# Outputs the string 'fg is a shell builtin'.
+\fish{cli-dark}
+>_ type fg
+fg is a builtin
\endfish
diff --git a/doc_src/user_doc.css b/doc_src/user_doc.css
index ba1362e22..2ac484ca0 100644
--- a/doc_src/user_doc.css
+++ b/doc_src/user_doc.css
@@ -174,8 +174,8 @@ tt, code, pre, .fish {
.comment, .suggest { color: #555; }
.command, .function, .binary { color: #223aa4; }
.argument, .path, .file { color: #5961cf; }
-.string { color: #6c6d08; }
.operator, .variable, .match, .history { color: #1c8885; }
+.string, .string .operator { color: #858904; }
/* Synopsis variant */
.synopsis {
diff --git a/lexicon_filter.in b/lexicon_filter.in
index 7583cc4ac..e9555e8f2 100644
--- a/lexicon_filter.in
+++ b/lexicon_filter.in
@@ -46,7 +46,12 @@
# Then if it's inline. Remove and process immediately...
/^\\fish.*$/ {
# Catch @ symbol
- s/@/(at)/
+ s/@/@at/g
+ # Catch & symbol
+ s/&\([^a-z]\)/@amp\1/g
+ # Catch {{ & }} symbols
+ s/{{/@curlyL/g
+ s/}}/@curlyR/g
s/^\\fish//
s/\\endfish//
b html
@@ -56,7 +61,12 @@
# Inside \fish block. Process...
/\\endfish/!{
# Catch @ symbol
- s/@/((d))/
+ s/@/@at/g
+ # Catch & symbol
+ s/&\([^a-z]\)/@amp\1/g
+ # Catch {{ & }} symbols
+ s/{{/@curlyL/g
+ s/}}/@curlyR/g
# Preprocess HTML and HTML-like formatting
/<[^>]*>/ {
b html
@@ -103,6 +113,9 @@ s||}|
s||@undr{|
s|]*>|@undr{|
s||}|
+# Backslash (when escaping output)
+s||@bksl{|
+s||}|
t html
#.
# Some handy non-standard extensions
@@ -224,11 +237,11 @@ s/ \\$/ @bksl{ }/
#.
# Normal Directory
s|mkdir |mkdir :|
-s|\([~/:][/]*[.A-Za-z_0-9/-]*\)\\ |\1=|g
-s| \([~/][/]*[.A-Za-z_0-9/=-]*\)| \\\
+s|\([~/:][/]*[.A-Za-z_0-9*/-]*\)\\ |\1=|g
+s| \([~/][/]*[.A-Za-z_0-9*/=-]*\)| \\\
<@path{\1}\
|g
-s| \(:[/]*[.A-Za-z_0-9/=-]*\)| \\\
+s| \(:[/]*[.A-Za-z_0-9*/=-]*\)| \\\
<@path{\1}\
|g
t protect
@@ -255,6 +268,7 @@ s|^\([a-zA-Z][{},a-zA-Z0-9%*._/?!-]*\)|@args{\1}|g
# Pick up loose text after markup.
s/\([})]\)\([a-zA-Z0-9+%*.,][,a-zA-Z0-9%*._/?!-]*\);/\1@args{\2};/g
s/\([})]\)\([a-zA-Z0-9+%*.,][,a-zA-Z0-9%*._/?!-]*\)$/\1@args{\2}/g
+s/\([})]\)\([a-zA-Z0-9+%*.,][,a-zA-Z0-9%*._/?!-]*\)@EOL/\1@args{\2}/g
#.
# Uncomment the following 2 lines (ss) to log the pattern buffer.
s/^.*$/Pattern : &/w lexicon.log
@@ -279,6 +293,8 @@ s,\([^\\ ]*\)\\\n\([^<]*\)<\(@[^}]*[}\\]\),\1\3\2,
t join
# Clean up stray new lines
s/\n//g
+# Clean up past @EOL
+s/@EOL.*$//g
#.
# Uncomment the folowing two lines (ss) to log the buffer before 'cleaning'.
s/^.*$/PreClean: &/w lexicon.log
@@ -475,16 +491,17 @@ x
#.
# Mark up sesitive character entities.
#.
-# We comment out this target because it isn't referenced and if we don't we
-# get warnings about "unused label 'entities'".
-#:entities
s/\</g
s/>/\>/g
-s/((d))/@/g
+s/@amp/\&/g
+s/@curlyL/\{/g
+s/@curlyR/\}/g
+s/@at/@atat{ }/g
#.
# Final post processing
s/};\([^]]\)/}@redr{;}\1/g
s/};$/}@redr{;}/
+s/@sglq{}/''/
s/ \[\([@(]\)/ @args{[}\1/g
s/ \[\([A-Z]*\) / @args{[\1} /g
s/@args{\([a-zA-Z0-9_.]*\)}\]/@args{\1]}/g
@@ -496,7 +513,9 @@ s/ \]$/ @args{]}/g
s/\]}\]$/]]}/
s/\\\([()]\)/@optr{@bksl{\1}}/g
s/\([()]\)/@optr{\1}/g
+s/\\\\\([cdgnstwx?]\)/@bksl{\1}/g
s/\\n/@bksl{n}/
+s/%\([diouxXfgGeEsbmy]\)/@pcnt{\1}/g
s/ \\$//
#.
# Uncomment the folowing two lines (ss) to log the final output, sent to Doxygen.
@@ -516,6 +535,8 @@ b
#.
# Move protected content to hold space and mark up other entities.
:protect
+# Add an 'End of Line' marker
+s/$/@EOL/
s/^.*$/Input : &/w lexicon.log
s/^Input : //
h
@@ -536,6 +557,7 @@ x
s/[^\<]*//
s/^ *\\\n//g
s/\n *\\//g
+ s/\n@EOL//g
s/[()] \\//g
s/^[^\<][^@][^\\]*//
s/\n[]|;) ][^\\]*\\//
@@ -559,11 +581,13 @@ s/^[a-z][a-z]* \n//
# Swap the buffers back.
x
#.
-# A special case. Tidy up after commands.
+# A special case. Tidy up after performing command substitution.
# Redirectors
s/\([^{|] *\)|/\1@redr{|}/g
-s/&$/@redr{\&}/
-s/\([^{&] *\)&[^a-z]/\1@redr{\&}/g
+s/\&@EOL$/@redr{@amp}@EOL/g
+s/@amp@EOL$/@redr{@amp}@EOL/g
+s/\([<>]\)@amp\([0-9]\)/@redr{\1@amp\2}/g
+s/\([^{&] *\)&[^@a-z]/\1@redr{\&}/g
s/\([^{<>^] *\)\([0-9]* *[<>^][<>^]*[^@][a-zA-Z0-9./_-]*\)/\1@redr{\2}/g
s/\\}/}\\/g
#.
@@ -575,11 +599,9 @@ s/[[][0-9$a-zA-Z_;. -]*]/@args{&}/g
s/\($[$]*\)\([A-Za-z_0-9][A-Za-z_0-9]*\)/@vars{@optr{\1}\2}/g
#.
# Files
-s/\([^@]\)\([A-Za-z0-9_-][A-Za-z0-9_-]*\.[a-z0-9*][a-z0-9*]*\)/\1@fsfo{\2}/g
-#.
-# We comment out this target because it isn't referenced and if we don't we
-# get warnings about "unused label 'commands'".
-#:commands
+/@at/ ! {
+ s/\([A-Za-z0-9_*-][A-Za-z0-9_*-]*\.[a-z0-9*][a-z0-9*]*\)/@fsfo{\1}/g
+}
#.
#### This section is built in the Makefile. Just some formatting examples. #####
#.
From 484c1484c9ae01354b1910bae5ed8a729e00b3be Mon Sep 17 00:00:00 2001
From: David Adam
Date: Mon, 4 Apr 2016 14:33:35 +0800
Subject: [PATCH 057/363] Customisable extra configuration, completion and
function directories
- Add options to the autotools build to set the path for the "vendor"
or "extra" configuration snippets, functions and completions
directories.
- Remove the vendor_completions directory from the Xcode build, as
these are relocatable and compiling the paths in does not make sense.
This allows packaging tools like Homebrew and Nix to use a common
directory outside of the main prefix for third-party completions, and
to make these available for programmatic discovery through `pkg-config`.
Closes #2113
---
.gitignore | 1 +
Makefile.in | 17 ++++++++---
configure.ac | 26 ++++++++++++++--
doc_src/index.hdr.in | 52 +++++++++++++++++++++++++++-----
fish.pc.in | 6 ++--
fish.xcodeproj/project.pbxproj | 28 -----------------
share/__fish_build_paths.fish.in | 8 +++++
share/config.fish | 17 ++++++++---
8 files changed, 106 insertions(+), 49 deletions(-)
create mode 100644 share/__fish_build_paths.fish.in
diff --git a/.gitignore b/.gitignore
index 704ec8d01..e0713b06e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -26,6 +26,7 @@ fish_tests
fish.pc
seq
set_color
+share/__fish_build_paths.fish
share/man/
toc.txt
user_doc/
diff --git a/Makefile.in b/Makefile.in
index ede69b0fd..5526fa6db 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -53,6 +53,9 @@ mandir = @mandir@
sysconfdir = @sysconfdir@
docdir = @docdir@
localedir = @localedir@
+extra_completionsdir = @extra_completionsdir@
+extra_functionsdir = @extra_functionsdir@
+extra_snippetsdir = @extra_snippetsdir@
#
# pcre2
@@ -224,7 +227,7 @@ endif
# Make everything needed for installing fish
#
-all: $(PROGRAMS) $(user_doc) $(share_man) $(TRANSLATIONS) fish.pc
+all: $(PROGRAMS) $(user_doc) $(share_man) $(TRANSLATIONS) fish.pc share/__fish_build_paths.fish
@echo fish has now been built.
@echo Use \'$(MAKE) install\' to install fish.
.PHONY: all
@@ -467,6 +470,9 @@ doc.h: $(HDR_FILES)
-e "s,@sysconfdir\@,$(sysconfdir),g" \
-e "s,@datadir\@,$(datadir),g" \
-e "s,@docdir\@,$(docdir),g" \
+ -e "s,@extra_completionsdir\@,$(extra_completionsdir),g" \
+ -e "s,@extra_functionsdir\@,$(extra_functionsdir),g" \
+ -e "s,@extra_snippetsdir\@,$(extra_snippetsdir),g" \
-e "s|@configure_input\@|$@, generated from $@.in by the Makefile. DO NOT MANUALLY EDIT THIS FILE!|g" \
-e "s,@prefix\@,$(prefix),g" \
-e "s,@fish_build_version\@,$(FISH_BUILD_VERSION),g" \
@@ -657,9 +663,9 @@ install-force: all install-translations
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish/conf.d
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions
- $(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/vendor_completions.d
- $(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/vendor_functions.d
- $(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/vendor_conf.d
+ $(INSTALL) -m 755 -d $(DESTDIR)$(extra_completionsdir)
+ $(INSTALL) -m 755 -d $(DESTDIR)$(extra_functionsdir)
+ $(INSTALL) -m 755 -d $(DESTDIR)$(extra_snippetsdir)
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/man/man1
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools
@@ -669,6 +675,7 @@ install-force: all install-translations
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools/web_config/sample_prompts
$(INSTALL) -m 644 etc/config.fish $(DESTDIR)$(sysconfdir)/fish/
$(INSTALL) -m 644 share/config.fish $(DESTDIR)$(datadir)/fish/
+ $(INSTALL) -m 644 share/__fish_build_paths.fish $(DESTDIR)$(datadir)/fish/
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/pkgconfig
$(INSTALL) -m 644 fish.pc $(DESTDIR)$(datadir)/pkgconfig
for i in $(COMPLETIONS_DIR_FILES:%='%'); do \
@@ -899,7 +906,7 @@ clean:
rm -f doc_src/index.hdr doc_src/commands.hdr
rm -f lexicon_filter lexicon.txt lexicon.log
rm -f compile_commands.json xcodebuild.log
- rm -f FISH-BUILD-VERSION-FILE fish.pc
+ rm -f FISH-BUILD-VERSION-FILE fish.pc share/__fish_build_paths.fish
if test "$(HAVE_DOXYGEN)" = 1; then \
rm -rf doc user_doc share/man; \
fi
diff --git a/configure.ac b/configure.ac
index af4fc5aff..f31825ce8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -845,7 +845,7 @@ You may need to install the PCRE2 development library for your system.])
fi
fi
-# Re-test as value may have changed
+# Re-test as value may have changed.
if test "x$included_pcre2" = "xyes"; then
# Build configure/Makefile for pcre2
AC_MSG_NOTICE([using included PCRE2 library])
@@ -862,7 +862,29 @@ if test "x$included_pcre2" = "xyes"; then
LIBS="$LIBS $PCRE2_LIBS"
fi
-# Tell the world what we know
+# Allow configurable extra directories.
+AC_SUBST(extra_completionsdir)
+AC_ARG_WITH([extra-completionsdir],
+ AS_HELP_STRING([--with-extra-completionsdir=DIR],
+ [path for extra completions]),
+ [extra_completionsdir=$withval],
+ [extra_completionsdir='${datadir}/fish/vendor_completions.d'])
+
+AC_SUBST(extra_functionsdir)
+AC_ARG_WITH([extra_functionsdir],
+ AS_HELP_STRING([--with-extra-functionsdir=DIR],
+ [path for extra functions]),
+ [extra_functionsdir=$withval],
+ [extra_functionsdir='${datadir}/fish/vendor_functions.d'])
+
+AC_SUBST(extra_snippetsdir)
+AC_ARG_WITH([extra-snippetsdir],
+ AS_HELP_STRING([--with-extra-snippetsdir=DIR],
+ [path for extra snippets]),
+ [extra_snippetsdir=$withval],
+ [extra_snippetsdir='${datadir}/fish/vendor_conf.d'])
+
+# Tell the world what we know.
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index a42fb6498..b75ee5e1d 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -247,11 +247,21 @@ Functions can be defined on the commandline or in a configuration file, but they
Fish automatically searches through any directories in the array variable `$fish_function_path`, and any functions defined are automatically loaded when needed. A function definition file must have a filename consisting of the name of the function plus the suffix '`.fish`'.
-The default value for `$fish_function_path` is `~/.config/fish/functions` `/etc/fish/functions` `/usr/share/fish/functions`. The exact path to the last two of these may be slightly different depending on what install path prefix was chosen at configuration time. The rationale behind having three different directories is that the first one is for user specific functions, the second one is for system-wide additional functions and the last one is for default fish functions. The path list is searched in order, meaning that by default, the system administrator can override default fish functions, and the user can override functions defined by the system administrator.
+By default, Fish searches the following for functions, using the first available file that it finds:
+- A directory for end-users to keep their own functions, usually `~/.config/fish/functions` (controlled by the `XDG_CONFIG_HOME` environment variable).
+- A directory for systems administrators to install functions for all users on the system, usually `/etc/fish/functions`.
+- A directory for third-party software vendors to ship their own functions for their software, usually `/usr/share/fish/vendor_functions.d`.
+- The functions shipped with fish, usually installed in `/usr/share/fish/functions`.
+
+These paths are controlled by parameters set at build, install, or run time, and may vary from the defaults listed above.
+
+This wide search may be confusing. If you are unsure, your functions probably belong in `~/.config/fish/functions`.
It is very important that function definition files only contain the definition for the specified function and nothing else. Otherwise, it is possible that autoloading a function files requires that the function already be loaded, which creates a circular dependency.
-Autoloading also won't work for event handlers, since fish cannot know that a function is supposed to be executed when an event occurs when it hasn't yet loaded the function. See there for details.
+Autoloading also won't work for event handlers, since fish cannot know that a function is supposed to be executed when an event occurs when it hasn't yet loaded the function. See the event handlers section for more information.
+
+If you are developing another program, you may wish to install functions which are available for all users of the fish shell on a system. They can be installed to the "vendor" functions directory. As this path may vary from system to system, the `pkgconfig` framework should be used to discover this path with the output of `pkg-config --variable functionsdir fish`.
\subsubsection syntax-conditional Conditional execution of code and flow control
@@ -381,9 +391,20 @@ Functions beginning with the string `__fish_print_` print a newline separated li
Completions can be defined on the commandline or in a configuration file, but they can also be automatically loaded. Fish automatically searches through any directories in the array variable `$fish_complete_path`, and any completions defined are automatically loaded when needed. A completion file must have a filename consisting of the name of the command to complete and the suffix '`.fish`'.
-The default value for `$fish_complete_path` is `~/.config/fish/completions` `/etc/fish/completions` `/usr/share/fish/vendor_completions.d` `/usr/share/fish/completions` `~/.local/share/generated_completions`. (Some paths may be slightly different depending on where fish is installed). If a suitable file is found in one of these directories, it will be automatically loaded and the search will be stopped. The large number of directories searched may be confusing. It is to allow, respectively, user-specific completions, system-wide completions, completions installed by other packages, default completions that ship with fish, and finally, completions generated from manual pages. If you are unsure, put your completions in `~/.config/fish/completions`.
+By default, Fish searches the following for completions, using the first available file that it finds:
+- A directory for end-users to keep their own completions, usually `~/.config/fish/completions` (controlled by the `XDG_CONFIG_HOME` environment variable);
+- A directory for systems administrators to install completions for all users on the system, usually `/etc/fish/completions`;
+- A directory for third-party software vendors to ship their own completions for their software, usually `/usr/share/fish/vendor_completions.d`;
+- The completions shipped with fish, usually installed in `/usr/share/fish/completions`; and
+- Completions automatically generated from the operating system's manual, usually stored in `~/.local/share/generated_completions`.
-If you have written new completions for a common Unix command, please consider sharing your work by submitting it via the instructions in Further help and development. If you are developing another program and would like to ship completions with your program, install them to `/usr/share/fish/vendor_completions.d` or similar directory. Systems using the `pkgconfig` framework can discover this path from the output of `pkg-config --variable completionsdir fish`.
+These paths are controlled by parameters set at build, install, or run time, and may vary from the defaults listed above.
+
+This wide search may be confusing. If you are unsure, your completions probably belong in `~/.config/fish/completions`.
+
+If you have written new completions for a common Unix command, please consider sharing your work by submitting it via the instructions in Further help and development.
+
+If you are developing another program and would like to ship completions with your program, install them to the "vendor" completions directory. As this path may vary from system to system, the `pkgconfig` framework should be used to discover this path with the output of `pkg-config --variable completionsdir fish`.
\section expand Parameter expansion (Globbing)
@@ -1085,9 +1106,27 @@ Note that functions cannot be started in the background. Functions that are stop
\section initialization Initialization files
-On startup, `fish` evaluates the files `/usr/share/fish/config.fish` (Or `/usr/local/fish...` if you installed fish in `/usr/local`), `/etc/fish/config.fish` (Or `~/etc/fish/...` if you installed fish in your home directory) and `~/.config/fish/config.fish` (Or any other directory specified by the `$XDG_CONFIG_HOME` variable), in that order.
+On startup, Fish evaluates a number of configuration files, which can be used to control the behavior of the shell.
-The first file should not be directly edited, the second one is meant for systemwide configuration and the last one is meant for user configuration. If you want to run a command only on starting an interactive shell, use the exit status of the command `status --is-interactive` to determine if the shell is interactive. If you want to run a command only when using a login shell, use `status --is-login` instead.
+Configuration files are evaluated in the following order:
+- Configuration shipped with fish, which should not be edited, usually `/usr/share/fish/config.fish`.
+- System-wide configuration files, where administrators can include initialization that should be run for all users on the system - similar to `/etc/profile` for POSIX-style shells - usually `/etc/fish/config.fish`;
+- "Unit" configuration files ending in `.fish`, in the directories:
+ - `~/.config/fish/conf.d/`
+ - `/etc/fish/conf.d`
+ - `/usr/share/fish/vendor_conf.d`
+
+ If there are multiple files with the same name in these directories, only the first will be executed.
+
+- User initialization, usually in `~/.config/fish/config.fish` (controlled by the `XDG_CONFIG_HOME` environment variable).
+
+These paths are controlled by parameters set at build, install, or run time, and may vary from the defaults listed above.
+
+This wide search may be confusing. If you are unsure, use `~/.config/fish/config.fish`.
+
+These files are all executed on the startup of every shell. If you want to run a command only on starting an interactive shell, use the exit status of the command `status --is-interactive` to determine if the shell is interactive. If you want to run a command only when using a login shell, use `status --is-login` instead. This will speed up the starting of non-interactive or non-login shells.
+
+If you are developing another program, you may wish to install configuration which is run for all users of the fish shell on a system. This is discouraged; if not carefully written, they may have side-effects or slow the startup of the shell. Additionally, users of other shells will not benefit from the Fish-specific configuration. However, if they are absolutely required, you may install them to the "vendor" configuration directory. As this path may vary from system to system, the `pkgconfig` framework should be used to discover this path with the output of `pkg-config --variable confdir fish`.
Examples:
@@ -1107,7 +1146,6 @@ function on_exit --on-process %self
end
\endfish
-Right after reading /usr/share/fish/config.fish and before reading /etc/fish/config.fish, fish will also read files ending in ".fish" in ~/.config/fish/conf.d/, /etc/fish/conf.d and /usr/share/fish/vendor_conf.d (the exact values depend on $XDG_CONFIG_HOME, $__fish_sysconfdir and $__fish_datadir). If there are files with the same name in two or all of these, fish will only attempt to read the first (skipping all files with that name if it is unreadable). ~/.config takes precedence over /etc/ which takes precedence over /usr. The path to the latter can also be gotten via `pkg-config` as "confdir", and is meant for third-party applications to integrate with fish.
\section other Other features
diff --git a/fish.pc.in b/fish.pc.in
index c8fabd7e8..d110a2fbe 100644
--- a/fish.pc.in
+++ b/fish.pc.in
@@ -1,8 +1,8 @@
prefix=@prefix@
datadir=@datadir@
-completionsdir=${datadir}/fish/vendor_completions.d
-functionsdir=${datadir}/fish/vendor_functions.d
-confdir=${datadir}/fish/vendor_conf.d
+completionsdir=@extra_completionsdir@
+functionsdir=@extra_functionsdir@
+confdir=@extra_snippetsdir@
Name: fish
Description: fish, the friendly interactive shell
diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj
index 0f7e5efc3..6d2ca9028 100644
--- a/fish.xcodeproj/project.pbxproj
+++ b/fish.xcodeproj/project.pbxproj
@@ -24,7 +24,6 @@
buildPhases = (
D07D266915E33B86009E43F6 /* CopyFiles */,
D07D266B15E33B86009E43F6 /* Copy Files */,
- D01A25E11AF58D8C002F9E92 /* ShellScript */,
D01A2CA716965ADD00767098 /* CopyFiles */,
);
dependencies = (
@@ -55,7 +54,6 @@
D0F019FC15A977B40034B3B1 /* CopyFiles */,
D033780F15DC6D2A00A634BA /* CopyFiles */,
D01A2C9B16964C8200767098 /* Copy Files */,
- D01A25E01AF58CD0002F9E92 /* ShellScript */,
);
dependencies = (
D0F01A1315AA36280034B3B1 /* PBXTargetDependency */,
@@ -1048,32 +1046,6 @@
shellPath = /bin/sh;
shellScript = ./build_tools/xcode_version_gen.sh;
};
- D01A25E01AF58CD0002F9E92 /* ShellScript */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "mkdir -p -m 755 \"${TARGET_BUILD_DIR}/base/share/fish/vendor_completions.d\"";
- };
- D01A25E11AF58D8C002F9E92 /* ShellScript */ = {
- isa = PBXShellScriptBuildPhase;
- buildActionMask = 8;
- files = (
- );
- inputPaths = (
- );
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 1;
- shellPath = /bin/sh;
- shellScript = "mkdir -p -m 755 \"${INSTALL_ROOT}/${INSTALL_PATH}/share/fish/vendor_completions.d\"";
- };
D0A564EB168CFDDE00AF6161 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
diff --git a/share/__fish_build_paths.fish.in b/share/__fish_build_paths.fish.in
new file mode 100644
index 000000000..4b923d7ef
--- /dev/null
+++ b/share/__fish_build_paths.fish.in
@@ -0,0 +1,8 @@
+# @configure_input@
+# This function is generated by the autotools build to "compile in"
+# the local "vendor" completions, functions and configuration snippets.
+# It is sourced by share/config.fish, if it exists.
+
+set __extra_completionsdir @extra_completionsdir@
+set __extra_functionsdir @extra_functionsdir@
+set __extra_snippetsdir @extra_snippetsdir@
diff --git a/share/config.fish b/share/config.fish
index fe45f70d7..3f7986525 100644
--- a/share/config.fish
+++ b/share/config.fish
@@ -45,11 +45,20 @@ end
# __fish_datadir, __fish_sysconfdir, __fish_help_dir, __fish_bin_dir
# are expected to have been set up by read_init from fish.cpp
+# Grab extra directories (as specified by the build process, usually for
+# third-party packages to ship completions &c.
+set -l __extra_completionsdir
+set -l __extra_functionsdir
+set -l __extra_snippetsdir
+if test -f $__fish_datadir/__fish_build_paths.fish
+ source $__fish_datadir/__fish_build_paths.fish
+end
+
# Set up function and completion paths. Make sure that the fish
# default functions/completions are included in the respective path.
if not set -q fish_function_path
- set fish_function_path $configdir/fish/functions $__fish_sysconfdir/functions $__fish_datadir/vendor_functions.d $__fish_datadir/functions
+ set fish_function_path $configdir/fish/functions $__fish_sysconfdir/functions $__extra_functionsdir $__fish_datadir/functions
end
if not contains $__fish_datadir/functions $fish_function_path
@@ -57,7 +66,7 @@ if not contains $__fish_datadir/functions $fish_function_path
end
if not set -q fish_complete_path
- set fish_complete_path $configdir/fish/completions $__fish_sysconfdir/completions $__fish_datadir/vendor_completions.d $__fish_datadir/completions $userdatadir/fish/generated_completions
+ set fish_complete_path $configdir/fish/completions $__fish_sysconfdir/completions $__extra_completionsdir $__fish_datadir/completions $userdatadir/fish/generated_completions
end
if not contains $__fish_datadir/completions $fish_complete_path
@@ -155,9 +164,9 @@ function . --description 'Evaluate contents of file (deprecated, see "source")'
end
# As last part of initialization, source the conf directories
-# Implement precedence (User > Admin > Vendors > Fish) by basically doing "basename"
+# Implement precedence (User > Admin > Extra (e.g. vendors) > Fish) by basically doing "basename"
set -l sourcelist
-for file in $configdir/fish/conf.d/*.fish $__fish_sysconfdir/conf.d/*.fish $__fish_datadir/vendor_conf.d/*.fish
+for file in $configdir/fish/conf.d/*.fish $__fish_sysconfdir/conf.d/*.fish $__extra_snippetsdir/*.fish
set -l basename (string replace -r '^.*/' '' -- $file)
contains -- $basename $sourcelist; and continue
set sourcelist $sourcelist $basename
From 8f33b55ccc501f8460d4d5ff8bd5ef7861a0ee3a Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Mon, 4 Apr 2016 16:55:40 -0700
Subject: [PATCH 058/363] remove unused special color "ignore"
Resolve lint warning about unused method "rgb_color_t::ignore()".
Fixes #2893
---
.gitignore | 2 ++
src/builtin_set_color.cpp | 6 +++---
src/color.cpp | 18 +++++-------------
src/color.h | 15 ++-------------
src/output.cpp | 22 +++++++---------------
src/output.h | 9 +++------
6 files changed, 22 insertions(+), 50 deletions(-)
diff --git a/.gitignore b/.gitignore
index e0713b06e..717e32434 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,5 @@ lexicon.txt
lexicon_filter
lexicon.log
DerivedData/
+compile_commands.json
+xcodebuild.log
diff --git a/src/builtin_set_color.cpp b/src/builtin_set_color.cpp
index b3c7ebaff..449e38954 100644
--- a/src/builtin_set_color.cpp
+++ b/src/builtin_set_color.cpp
@@ -137,7 +137,7 @@ static int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **
for (; w.woptind < argc; w.woptind++)
{
rgb_color_t fg = rgb_color_t(argv[w.woptind]);
- if (fg.is_none() || fg.is_ignore())
+ if (fg.is_none())
{
streams.err.append_format(_(L"%ls: Unknown color '%ls'\n"), argv[0], argv[w.woptind]);
return STATUS_BUILTIN_ERROR;
@@ -155,10 +155,10 @@ static int builtin_set_color(parser_t &parser, io_streams_t &streams, wchar_t **
// #1323: We may have multiple foreground colors. Choose the best one.
// If we had no foreground coor, we'll get none(); if we have at least one we expect not-none
const rgb_color_t fg = best_color(fgcolors, output_get_color_support());
- assert(fgcolors.empty() || !(fg.is_none() || fg.is_ignore()));
+ assert(fgcolors.empty() || !fg.is_none());
const rgb_color_t bg = rgb_color_t(bgcolor ? bgcolor : L"");
- if (bgcolor && (bg.is_none() || bg.is_ignore()))
+ if (bgcolor && bg.is_none())
{
streams.err.append_format(_(L"%ls: Unknown color '%ls'\n"), argv[0], bgcolor);
return STATUS_BUILTIN_ERROR;
diff --git a/src/color.cpp b/src/color.cpp
index 19adc390f..4c3c89d21 100644
--- a/src/color.cpp
+++ b/src/color.cpp
@@ -1,6 +1,4 @@
-/** \file color.cpp Color class implementation
-*/
-
+// Color class implementation.
#include "color.h"
#include "fallback.h" // IWYU pragma: keep
#include
@@ -21,10 +19,6 @@ bool rgb_color_t::try_parse_special(const wcstring &special)
{
this->type = type_reset;
}
- else if (! wcscasecmp(name, L"ignore"))
- {
- this->type = type_ignore;
- }
else
{
this->type = type_none;
@@ -240,22 +234,22 @@ rgb_color_t rgb_color_t::normal()
{
return rgb_color_t(type_normal);
}
+
rgb_color_t rgb_color_t::reset()
{
return rgb_color_t(type_reset);
}
-rgb_color_t rgb_color_t::ignore()
-{
- return rgb_color_t(type_ignore);
-}
+
rgb_color_t rgb_color_t::none()
{
return rgb_color_t(type_none);
}
+
rgb_color_t rgb_color_t::white()
{
return rgb_color_t(type_named, 7);
}
+
rgb_color_t rgb_color_t::black()
{
return rgb_color_t(type_named, 0);
@@ -382,8 +376,6 @@ wcstring rgb_color_t::description() const
return L"reset";
case type_normal:
return L"normal";
- case type_ignore:
- return L"ignore";
default:
abort();
return L"";
diff --git a/src/color.h b/src/color.h
index 988bfdb8a..1faa35a6b 100644
--- a/src/color.h
+++ b/src/color.h
@@ -1,5 +1,4 @@
-/** \file color.h Color class.
- */
+// Color class.
#ifndef FISH_COLOR_H
#define FISH_COLOR_H
@@ -24,8 +23,7 @@ class rgb_color_t
type_named,
type_rgb,
type_normal,
- type_reset,
- type_ignore
+ type_reset
};
unsigned char type:4;
@@ -79,18 +77,9 @@ class rgb_color_t
/** Returns the normal special color */
static rgb_color_t normal();
- /** Returns the ignore special color */
- static rgb_color_t ignore();
-
/** Returns the none special color */
static rgb_color_t none();
- /** Returns whether the color is the ignore special color */
- bool is_ignore(void) const
- {
- return type == type_ignore;
- }
-
/** Returns whether the color is the normal special color */
bool is_normal(void) const
{
diff --git a/src/output.cpp b/src/output.cpp
index dbd97eb4b..033d14098 100644
--- a/src/output.cpp
+++ b/src/output.cpp
@@ -246,25 +246,17 @@ void set_color(rgb_color_t c, rgb_color_t c2)
was_underline=0;
}
- if (! last_color2.is_normal() &&
- ! last_color2.is_reset() &&
- ! last_color2.is_ignore())
+ if (!last_color2.is_normal() && !last_color2.is_reset())
{
- /*
- Background was set
- */
- last_bg_set=1;
+ // Background was set.
+ last_bg_set = 1;
}
- if (! c2.is_normal() &&
- ! c2.is_ignore())
+ if (!c2.is_normal())
{
- /*
- Background is set
- */
- bg_set=1;
- if (c==c2)
- c = (c2==rgb_color_t::white())?rgb_color_t::black():rgb_color_t::white();
+ // Background is set.
+ bg_set = 1;
+ if (c == c2) c = (c2==rgb_color_t::white())?rgb_color_t::black():rgb_color_t::white();
}
if ((enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0))
diff --git a/src/output.h b/src/output.h
index 68ad2a2e5..acdd26127 100644
--- a/src/output.h
+++ b/src/output.h
@@ -27,9 +27,7 @@ enum
FISH_COLOR_MAGENTA,
FISH_COLOR_CYAN,
FISH_COLOR_WHITE,
- /** The default fg color of the terminal */
- FISH_COLOR_NORMAL,
- FISH_COLOR_IGNORE,
+ FISH_COLOR_NORMAL, // the default fg color of the terminal
FISH_COLOR_RESET
};
@@ -41,9 +39,8 @@ enum
screen to flicker, the function takes care to write as little as
possible.
- Possible values for color are any form the FISH_COLOR_* enum,
- FISH_COLOR_IGNORE and FISH_COLOR_RESET. FISH_COLOR_IGNORE will
- leave the color unchanged, and FISH_COLOR_RESET will perform an
+ Possible values for color are any form the FISH_COLOR_* enum
+ and FISH_COLOR_RESET. FISH_COLOR_RESET will perform an
exit_attribute_mode, even if set_color thinks it is already in
FISH_COLOR_NORMAL mode.
From a4642f141f7781792909cff385ff2316530416ee Mon Sep 17 00:00:00 2001
From: Aaron Gyes
Date: Sat, 2 Apr 2016 22:19:44 -0700
Subject: [PATCH 059/363] don't try to use st_gen (inode generation) number
Per discussion in pull-request #2891, it's not available on Linux (we just
fill it with zero), and unless run as root on OS X (or other BSD system) it
will be zero. Remove it from file_id_t. Also fix the initialization of the
file_id_t structure.
Fixes #2891
---
src/wutil.cpp | 10 ++--------
src/wutil.h | 3 +--
2 files changed, 3 insertions(+), 10 deletions(-)
diff --git a/src/wutil.cpp b/src/wutil.cpp
index a4494470d..0b11989a4 100644
--- a/src/wutil.cpp
+++ b/src/wutil.cpp
@@ -28,7 +28,7 @@
typedef std::string cstring;
-const file_id_t kInvalidFileID = {(dev_t)-1LL, (ino_t)-1LL, (uint64_t)-1LL, -1, -1, (uint32_t)-1};
+const file_id_t kInvalidFileID = {(dev_t)-1LL, (ino_t)-1LL, (uint64_t)-1LL, -1, -1, -1, -1};
#ifndef PATH_MAX
#ifdef MAXPATHLEN
@@ -555,12 +555,7 @@ file_id_t file_id_t::file_id_from_stat(const struct stat *buf)
result.change_nanoseconds = 0;
result.mod_nanoseconds = 0;
#endif
-
-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
- result.generation = buf->st_gen;
-#else
- result.generation = 0;
-#endif
+
return result;
}
@@ -619,7 +614,6 @@ int file_id_t::compare_file_id(const file_id_t &rhs) const
if (! ret) ret = compare(device, rhs.device);
if (! ret) ret = compare(inode, rhs.inode);
if (! ret) ret = compare(size, rhs.size);
- if (! ret) ret = compare(generation, rhs.generation);
if (! ret) ret = compare(change_seconds, rhs.change_seconds);
if (! ret) ret = compare(change_nanoseconds, rhs.change_nanoseconds);
if (! ret) ret = compare(mod_seconds, rhs.mod_seconds);
diff --git a/src/wutil.h b/src/wutil.h
index a14dfa9b1..f16e28c06 100644
--- a/src/wutil.h
+++ b/src/wutil.h
@@ -143,8 +143,7 @@ struct file_id_t
long change_nanoseconds;
time_t mod_seconds;
long mod_nanoseconds;
- uint32_t generation;
-
+
bool operator==(const file_id_t &rhs) const;
bool operator!=(const file_id_t &rhs) const;
From fd1b7ba52901179c19f5997b650518993d919f52 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Fri, 1 Apr 2016 20:48:11 -0700
Subject: [PATCH 060/363] support making fish code match the style guide
This changes implements two new make targets: `style` and `style-all`. These
make it easy to ensure that a change conforms to the project style guides for
C++ and fish code.
Fixes #571
---
.clang-format | 8 +++
CONTRIBUTING.md | 135 ++++++++++++++++++-----------------------
Makefile.in | 10 ++-
build_tools/lint.fish | 21 +++----
build_tools/style.fish | 90 +++++++++++++++++++++++++++
5 files changed, 174 insertions(+), 90 deletions(-)
create mode 100644 .clang-format
mode change 100755 => 100644 build_tools/lint.fish
create mode 100755 build_tools/style.fish
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 000000000..d154da600
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,8 @@
+# Use the Google style with these modifications:
+#
+# 1) lines can be up to 100 chars long rather than 80, and
+# 2) use a four space indent rather than two spaces.
+#
+BasedOnStyle: Google
+ColumnLimit: 100
+IndentWidth: 4
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6321cdc7f..af2ad6907 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,13 +1,57 @@
# Guidelines For Developers
+This document provides guidelines for making changes to the fish-shell project. This includes rules for how to format the code, naming conventions, etc. It also includes recommended best practices such as creating a Travis-CI account so you can verify your changes pass all the tests before making a pull-request.
+
+See the bottom of this document for help on installing the linting and style reformatting tools discussed in the following sections.
+
## Lint Free Code
-Automated analysis tools like cppcheck and oclint can help identify bugs. They also help ensure the code has a consistent style and avoids patterns that tend to confuse people.
+Automated analysis tools like cppcheck and oclint can point out potential bugs. They also help ensure the code has a consistent style and that it avoids patterns that tend to confuse people.
Ultimately we want lint free code. However, at the moment a lot of cleanup is required to reach that goal. For now simply try to avoid introducing new lint.
To make linting the code easy there are two make targets: `lint` and `lint-all`. The latter does just what the name implies. The former will lint any modified but not committed `*.cpp` files. If there is no uncommitted work it will lint the files in the most recent commit.
+## Ensuring Your Changes Conform to the Style Guides
+
+The following sections discuss the specific rules for the style that should be used when writing fish code. To ensure your changes conform to the style rules you simply need to run
+
+```
+make style
+```
+
+before commiting your change. If you've already committed your changes that's okay since it will then check the files in the most recent commit. This can be useful after you've merged someone elses change and want to check that it's style is acceptable.
+
+If you want to check the style of the entire code base run
+
+```
+make style-all
+```
+
+## Fish Script Style Guide
+
+Fish scripts such as those in the *share/functions* and *tests* directories should be formatted using the `fish_indent` command.
+
+Function names should be all lowercase with undescores separating words. Private functions should begin with an underscore. The first word should be `fish` if the function is unique to fish.
+
+The first word of global variable names should generally be `fish` for public vars or `_fish` for private vars to minimize the possibility of name clashes with user defined vars.
+
+## C++ Style Guide
+
+1. The [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) forms the basis of the fish C++ style guide. There are two major deviations for the fish project. First, a four, rather than two, space indent. Second, line lengths up to 100, rather than 80, characters.
+
+1. The `clang-format` command is authoritative with respect to indentation, whitespace around operators, etc. **Note**: this rule should be ignored at this time. After the code is cleaned up this rule will become mandatory.
+
+1. All names in code should be `small_snake_case`. No Hungarian notation is used. Classes and structs names should be followed by `_t`.
+
+1. Always attach braces to the surrounding context.
+
+1. Indent with spaces, not tabs and use four spaces per indent.
+
+## Installing the Required Tools
+
+### Installing the Linting Tools
+
To install the lint checkers on Mac OS X using HomeBrew:
```
@@ -24,85 +68,24 @@ sudo apt-get install oclint
sudo apt-get install cppcheck
```
-## Fish Script Style Guide
+### Installing the Reformatting Tools
-Fish scripts such as those in the *share/functions* and *tests* directories should be formatted using the `fish_indent` command.
+To install the reformatting tool on Mac OS X using HomeBrew:
-Function names should be all lowercase with undescores separating words. Private functions should begin with an underscore. The first word should be `fish` if the function is unique to fish.
+```
+brew install clang-format
+```
-The first word of global variable names should generally be `fish` for public vars or `_fish` for private vars to minimize the possibility of name clashes with user defined vars.
+To install the reformatting tool on Linux distros that use Apt:
-## C++ Style Guide
+```
+apt-cache search clang-format
+```
-1. The `clang-format` command is authoritative with respect to indentation, whitespace around operators, etc. **Note**: this rule should be ignored at this time. A subsequent commit will add the necessary config file and make targets. After the happens the code will be cleaned up and this rule will become mandatory.
+That will list the versions available. Pick the newest one available (3.6 for Ubuntu 14.04 as I write this) and install it:
-1. All names in code should be `small_snake_case`. No Hungarian notation is used. Classes and structs names should be followed by `_t`.
+```
+sudo apt-get install clang-format-3.6
+sudo ln -s /usr/bin/clang-format-3.6 /usr/bin/clang-format
-1. fish uses the Allman/BSD style of indentation.
-
-1. Indent with spaces, not tabs.
-
-1. Use 4 spaces per indent.
-
-1. Opening curly bracket is on the following line:
-
- // ✔:
- struct name
- {
- // code
- };
-
- void func()
- {
- // code
- }
-
- if (...)
- {
- // code
- }
-
- // ✗:
- void func() {
- // code
- }
-
-1. Put space after `if`, `while` and `for` before conditions.
-
- // ✔:
- if () {}
-
- // ✗:
- if() {}
-
-1. Put spaces before and after operators excluding increment and decrement;
-
- // ✔:
- int a = 1 + 2 * 3;
- a++;
-
- // ✗:
- int a=1+2*3;
- a ++;
-
-1. Never put spaces between function name and parameters list.
-
- // ✔:
- func(args);
-
- // ✗:
- func (args);
-
-1. Never put spaces after `(` and before `)`.
-
-1. Always put space after comma and semicolon.
-
- // ✔:
- func(arg1, arg2);
-
- for (int i = 0; i < LENGTH; i++) {}
-
- // ✗:
- func(arg1,arg2);
-
- for (int i = 0;i&1
+ cppcheck -q --verbose --std=posix --std=c11 --language=c++ --template "[{file}:{line}]: {severity} ({id}): {message}" --suppress=missingIncludeSystem --inline-suppr --enable=$cppchecks $cppcheck_args $c_files 2>& 1
end
if type -q oclint
@@ -82,20 +78,19 @@ if set -q c_files[1]
oclint-xcodebuild xcodebuild.log > /dev/null
end
if test $all = yes
- oclint-json-compilation-database -e '/pcre2-10.20/' \
- -- -enable-global-analysis 2>&1
+ oclint-json-compilation-database -e '/pcre2-10.20/' -- -enable-global-analysis 2>& 1
else
set i_files
for f in $c_files
set i_files $i_files -i $f
end
echo oclint-json-compilation-database -e '/pcre2-10.20/' $i_files
- oclint-json-compilation-database -e '/pcre2-10.20/' $i_files 2>&1
+ oclint-json-compilation-database -e '/pcre2-10.20/' $i_files 2>& 1
end
else
# Presumably we're on Linux or other platform not requiring special
# handling for oclint to work.
- oclint $c_files -- $argv 2>&1
+ oclint $c_files -- $argv 2>& 1
end
end
else
diff --git a/build_tools/style.fish b/build_tools/style.fish
new file mode 100755
index 000000000..76cf920d5
--- /dev/null
+++ b/build_tools/style.fish
@@ -0,0 +1,90 @@
+#!/usr/bin/env fish
+#
+# This is meant to be run by "make style" or "make style-all". It is not meant to
+# be run directly from a shell prompt although it can be.
+#
+# This runs C++ files and fish scripts (*.fish) through their respective code
+# formatting programs.
+#
+set c_files
+set f_files
+set all no
+
+if test "$argv[1]" = "--all"
+ set all yes
+ set -e argv[1]
+end
+
+if set -q argv[1]
+ echo "Unexpected arguments: '$argv'"
+ exit 1
+end
+
+if test $all = yes
+ set c_files src/*.h src/*.cpp
+ set f_files ***.fish
+else
+ # We haven't been asked to reformat all the source. If there are uncommitted
+ # changes reformat those, else reformat the files in the most recent commit.
+ set pending (git status --porcelain --short --untracked-files=all | sed -e 's/^ *//')
+ if count $pending > /dev/null
+ # There are pending changes so lint those files.
+ for arg in $pending
+ set files $files (string split -m 1 ' ' $arg)[2]
+ end
+ else
+ # No pending changes so lint the files in the most recent commit.
+ set files (git show --name-only --pretty=oneline head | tail --lines=+2)
+ end
+
+ # Extract just the C/C++ files.
+ set c_files (string match -r '^.*\.(?:c|cpp|h)$' -- $files)
+ # Extract just the fish files.
+ set f_files (string match -r '^.*\.fish$' -- $files)
+end
+
+# Run the C++ reformatter if we have any C++ files.
+if set -q c_files[1]
+ if type -q clang-format
+ echo
+ echo ========================================
+ echo Running clang-format
+ echo ========================================
+ for file in $c_files
+ clang-format $file > $file.new
+ if cmp --quiet $file $file.new
+ echo $file was correctly formatted
+ rm $file.new
+ else
+ echo $file was NOT correctly formatted
+ mv $file.new $file
+ end
+ end
+ else
+ echo
+ echo 'WARNING: Cannot find clang-format command'
+ echo
+ end
+end
+
+# Run the fish reformatter if we have any fish files.
+if set -q f_files[1]
+ if not type -q fish_indent
+ make fish_indent
+ set PATH . $PATH
+ end
+ echo
+ echo ========================================
+ echo Running fish_indent
+ echo ========================================
+ for file in $f_files
+ fish_indent < $file > $file.new
+ if cmp --quiet $file $file.new
+ echo $file was correctly formatted
+ rm $file.new
+ else
+ echo $file was NOT correctly formatted
+ mv $file.new $file
+ end
+ end
+end
From 3435e94994268caba16e67780bb71381332334b7 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Mon, 4 Apr 2016 21:32:03 -0700
Subject: [PATCH 061/363] make the string man page more readable
I didn't notice when I merged commit cb6d5d76c8232264f66c9a1db895d9dd69d77bc3
by thebespokepixel.com that it removed the explicit wrapping in the `string`
man page. That makes `man string` harder to read so reinstate the explicit
wrapping.
---
doc_src/string.txt | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/doc_src/string.txt b/doc_src/string.txt
index fd77da945..1a3f2ea11 100644
--- a/doc_src/string.txt
+++ b/doc_src/string.txt
@@ -3,13 +3,18 @@
\subsection string-synopsis Synopsis
\fish{synopsis}
string length [(-q | --quiet)] [STRING...]
-string sub [(-s | --start) START] [(-l | --length) LENGTH] [(-q | --quiet)] [STRING...]
-string split [(-m | --max) MAX] [(-r | --right)] [(-q | --quiet)] SEP [STRING...]
+string sub [(-s | --start) START] [(-l | --length) LENGTH] [(-q | --quiet)]
+ [STRING...]
+string split [(-m | --max) MAX] [(-r | --right)] [(-q | --quiet)] SEP
+ [STRING...]
string join [(-q | --quiet)] SEP [STRING...]
-string trim [(-l | --left)] [(-r | --right)] [(-c | --chars CHARS)] [(-q | --quiet)] [STRING...]
+string trim [(-l | --left)] [(-r | --right)] [(-c | --chars CHARS)]
+ [(-q | --quiet)] [STRING...]
string escape [(-n | --no-quoted)] [STRING...]
-string match [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)] [(-n | --index)] [(-q | --quiet)] PATTERN [STRING...]
-string replace [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)] [(-q | --quiet)] PATTERN REPLACEMENT [STRING...]
+string match [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)]
+ [(-n | --index)] [(-q | --quiet)] PATTERN [STRING...]
+string replace [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)]
+ [(-q | --quiet)] PATTERN REPLACEMENT [STRING...]
\endfish
From 9e93ddc0978644d0670e192052619bb4710041e7 Mon Sep 17 00:00:00 2001
From: Mark Griffiths
Date: Tue, 5 Apr 2016 13:31:31 +0100
Subject: [PATCH 062/363] Fix a couple of minor issues in string examples
Print correct return code in 2nd example
Remove syntax colouring in \cg
Signed-off-by: Mark Griffiths
---
doc_src/string.txt | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/doc_src/string.txt b/doc_src/string.txt
index 1a3f2ea11..bae21dc99 100644
--- a/doc_src/string.txt
+++ b/doc_src/string.txt
@@ -57,7 +57,7 @@ The following subcommands are available:
>_ set str foo
>_ string length -q $str; echo $status
-1
+0
# Equivalent to test -n $str
\endfish
@@ -103,7 +103,7 @@ The following subcommands are available:
\fish{cli-dark}
>_ echo \\x07 | string escape
-cg
+cg
\endfish
\subsection string-example-match-glob Match Glob Examples
From 200a10e78d0df7001c6c2a7c71e7139cccf4277c Mon Sep 17 00:00:00 2001
From: David Adam
Date: Tue, 5 Apr 2016 22:22:12 +0800
Subject: [PATCH 063/363] Rename "snippets" to "conf" internally, and document
them as snippets
Discussed in #2896.
---
Makefile.in | 6 +++---
configure.ac | 12 ++++++------
doc_src/index.hdr.in | 2 +-
fish.pc.in | 2 +-
share/__fish_build_paths.fish.in | 4 ++--
share/config.fish | 4 ++--
6 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index b176c5f69..ea008211a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -55,7 +55,7 @@ docdir = @docdir@
localedir = @localedir@
extra_completionsdir = @extra_completionsdir@
extra_functionsdir = @extra_functionsdir@
-extra_snippetsdir = @extra_snippetsdir@
+extra_confdir = @extra_confdir@
#
# pcre2
@@ -472,7 +472,7 @@ doc.h: $(HDR_FILES)
-e "s,@docdir\@,$(docdir),g" \
-e "s,@extra_completionsdir\@,$(extra_completionsdir),g" \
-e "s,@extra_functionsdir\@,$(extra_functionsdir),g" \
- -e "s,@extra_snippetsdir\@,$(extra_snippetsdir),g" \
+ -e "s,@extra_confdir\@,$(extra_confdir),g" \
-e "s|@configure_input\@|$@, generated from $@.in by the Makefile. DO NOT MANUALLY EDIT THIS FILE!|g" \
-e "s,@prefix\@,$(prefix),g" \
-e "s,@fish_build_version\@,$(FISH_BUILD_VERSION),g" \
@@ -665,7 +665,7 @@ install-force: all install-translations
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions
$(INSTALL) -m 755 -d $(DESTDIR)$(extra_completionsdir)
$(INSTALL) -m 755 -d $(DESTDIR)$(extra_functionsdir)
- $(INSTALL) -m 755 -d $(DESTDIR)$(extra_snippetsdir)
+ $(INSTALL) -m 755 -d $(DESTDIR)$(extra_confdir)
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/man/man1
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/tools
diff --git a/configure.ac b/configure.ac
index f31825ce8..72a210fe6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -877,12 +877,12 @@ AC_ARG_WITH([extra_functionsdir],
[extra_functionsdir=$withval],
[extra_functionsdir='${datadir}/fish/vendor_functions.d'])
-AC_SUBST(extra_snippetsdir)
-AC_ARG_WITH([extra-snippetsdir],
- AS_HELP_STRING([--with-extra-snippetsdir=DIR],
- [path for extra snippets]),
- [extra_snippetsdir=$withval],
- [extra_snippetsdir='${datadir}/fish/vendor_conf.d'])
+AC_SUBST(extra_confdir)
+AC_ARG_WITH([extra-confdir],
+ AS_HELP_STRING([--with-extra-confdir=DIR],
+ [path for extra conf]),
+ [extra_confdir=$withval],
+ [extra_confdir='${datadir}/fish/vendor_conf.d'])
# Tell the world what we know.
AC_CONFIG_FILES([Makefile])
diff --git a/doc_src/index.hdr.in b/doc_src/index.hdr.in
index b75ee5e1d..7e889d8e6 100644
--- a/doc_src/index.hdr.in
+++ b/doc_src/index.hdr.in
@@ -1111,7 +1111,7 @@ On startup, Fish evaluates a number of configuration files, which can be used to
Configuration files are evaluated in the following order:
- Configuration shipped with fish, which should not be edited, usually `/usr/share/fish/config.fish`.
- System-wide configuration files, where administrators can include initialization that should be run for all users on the system - similar to `/etc/profile` for POSIX-style shells - usually `/etc/fish/config.fish`;
-- "Unit" configuration files ending in `.fish`, in the directories:
+- Configuration snippets in files ending in `.fish`, in the directories:
- `~/.config/fish/conf.d/`
- `/etc/fish/conf.d`
- `/usr/share/fish/vendor_conf.d`
diff --git a/fish.pc.in b/fish.pc.in
index d110a2fbe..04fd75ce8 100644
--- a/fish.pc.in
+++ b/fish.pc.in
@@ -2,7 +2,7 @@ prefix=@prefix@
datadir=@datadir@
completionsdir=@extra_completionsdir@
functionsdir=@extra_functionsdir@
-confdir=@extra_snippetsdir@
+confdir=@extra_confdir@
Name: fish
Description: fish, the friendly interactive shell
diff --git a/share/__fish_build_paths.fish.in b/share/__fish_build_paths.fish.in
index 4b923d7ef..8308cf50c 100644
--- a/share/__fish_build_paths.fish.in
+++ b/share/__fish_build_paths.fish.in
@@ -1,8 +1,8 @@
# @configure_input@
# This function is generated by the autotools build to "compile in"
-# the local "vendor" completions, functions and configuration snippets.
+# the local "vendor" completions, functions and configuration conf.
# It is sourced by share/config.fish, if it exists.
set __extra_completionsdir @extra_completionsdir@
set __extra_functionsdir @extra_functionsdir@
-set __extra_snippetsdir @extra_snippetsdir@
+set __extra_confdir @extra_confdir@
diff --git a/share/config.fish b/share/config.fish
index 3f7986525..86e8d9b7d 100644
--- a/share/config.fish
+++ b/share/config.fish
@@ -49,7 +49,7 @@ end
# third-party packages to ship completions &c.
set -l __extra_completionsdir
set -l __extra_functionsdir
-set -l __extra_snippetsdir
+set -l __extra_confdir
if test -f $__fish_datadir/__fish_build_paths.fish
source $__fish_datadir/__fish_build_paths.fish
end
@@ -166,7 +166,7 @@ end
# As last part of initialization, source the conf directories
# Implement precedence (User > Admin > Extra (e.g. vendors) > Fish) by basically doing "basename"
set -l sourcelist
-for file in $configdir/fish/conf.d/*.fish $__fish_sysconfdir/conf.d/*.fish $__extra_snippetsdir/*.fish
+for file in $configdir/fish/conf.d/*.fish $__fish_sysconfdir/conf.d/*.fish $__extra_confdir/*.fish
set -l basename (string replace -r '^.*/' '' -- $file)
contains -- $basename $sourcelist; and continue
set sourcelist $sourcelist $basename
From 8e8b5a648197ca83af50064bc9492ca855e9d705 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Tue, 5 Apr 2016 18:49:06 -0700
Subject: [PATCH 064/363] augment the guide for contributing
Include information about how to deal with lint warnings and suppress
`clang-format` reformatting of blocks of code.
Move information only relevant to developers from the README.md to the
CONTRIBUTING.md document.
Closes #2901
---
CONTRIBUTING.md | 62 +++++++++++++++++++++++++++++++++++++++++++
README.md | 30 +++------------------
build_tools/lint.fish | 0
3 files changed, 66 insertions(+), 26 deletions(-)
mode change 100644 => 100755 build_tools/lint.fish
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index af2ad6907..2c8473190 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -12,6 +12,26 @@ Ultimately we want lint free code. However, at the moment a lot of cleanup is re
To make linting the code easy there are two make targets: `lint` and `lint-all`. The latter does just what the name implies. The former will lint any modified but not committed `*.cpp` files. If there is no uncommitted work it will lint the files in the most recent commit.
+### Dealing With Lint Warnings
+
+You are strongly encouraged to address a lint warning by refactoring the code, changing variable names, or whatever action is implied by the warning.
+
+### Suppressing Lint Warnings
+
+Once in a while the lint tools emit a false positive warning. For example, cppcheck might suggest a memory leak is present when that is not the case. To suppress that cppcheck warning you should insert a line like the following immediately prior to the line cppcheck warned about:
+
+```
+// cppcheck-suppress memleak // addr not really leaked
+```
+
+The explanatory portion of the suppression comment is optional. For other types of warnings replace "memleak" with the value inside the parenthesis (e.g., "nullPointerRedundantCheck") from a warning like the following:
+
+```
+[src/complete.cpp:1727]: warning (nullPointerRedundantCheck): Either the condition 'cmd_node' is redundant or there is possible null pointer dereference: cmd_node.
+```
+
+Suppressing oclint warnings is more complicated to describe so I'll refer you to the [OCLint HowTo](http://docs.oclint.org/en/latest/howto/suppress.html#annotations) on the topic.
+
## Ensuring Your Changes Conform to the Style Guides
The following sections discuss the specific rules for the style that should be used when writing fish code. To ensure your changes conform to the style rules you simply need to run
@@ -28,6 +48,16 @@ If you want to check the style of the entire code base run
make style-all
```
+### Suppressing Reformatting of the Code
+
+If you have a good reason for doing so you can tell `clang-format` to not reformat a block of code by enclosing it in comments like this:
+
+```
+// clang-format off
+code to ignore
+// clang-format on
+```
+
## Fish Script Style Guide
Fish scripts such as those in the *share/functions* and *tests* directories should be formatted using the `fish_indent` command.
@@ -48,6 +78,38 @@ The first word of global variable names should generally be `fish` for public va
1. Indent with spaces, not tabs and use four spaces per indent.
+1. Comments should always use the C++ style; i.e., each line of the comment should begin with a `//` and should be limited to 100 characters. Comments that do not begin a line should be separated from the previous text by two spaces.
+
+## Testing
+
+The source code for fish includes a large collection of tests. If you are making any changes to fish, running these tests is highly recommended to make sure the behaviour remains consistent.
+
+You are also strongly encouraged to add tests when changing the functionality of fish. Especially if you are fixing a bug to help ensure there are no regressions in the future (i.e., we don't reintroduce the bug).
+
+### Local testing
+
+The tests can be run on your local computer on all operating systems.
+
+Running the tests is only supported from the autotools build and not xcodebuild. On OS X, you will need to install autoconf — we suggest using [Homebrew](http://brew.sh/) to install these tools.
+
+ autoconf
+ ./configure
+ make test [gmake on BSD]
+
+### Travis CI Build and Test
+
+The Travis Continuous Integration services can be used to test your changes using multiple configurations. This is the same service that the fish shell project uses to ensure new changes haven't broken anything. Thus it is a really good idea that you leverage Travis CI before making a pull-request to avoid embarrasment at breaking the build.
+
+You will need to [fork the fish-shell repository on GitHub](https://help.github.com/articles/fork-a-repo/). Then setup Travis to test your changes before you make a pull-request:
+
+1. [Sign in to Travis CI](https://travis-ci.org/auth) with your GitHub account, accepting the GitHub access permissions confirmation.
+1. Once you're signed in, and your repositories are synchronised, go to your [profile page](https://travis-ci.org/profile) and enable the fish-shell repository.
+1. Push your changes to GitHub.
+
+You'll receive an email when the tests are complete telling you whether or not any tests failed.
+
+You'll find the configuration used to control Travis in the `.travis.yml` file.
+
## Installing the Required Tools
### Installing the Linting Tools
diff --git a/README.md b/README.md
index fc549ef61..648e8eb63 100644
--- a/README.md
+++ b/README.md
@@ -54,32 +54,6 @@ On RedHat, CentOS, or Amazon EC2:
sudo yum install ncurses-devel
-## Testing
-
-The source code for fish includes a large collection of tests. If you are making any changes to fish, running these tests is highly recommended to make sure the behaviour remains consistent.
-
-### Local testing
-
-The tests can be run on your local computer on all operating systems.
-
-Running the tests is only supported from the Autotools build. On OS X, you will require an installation of autoconf; we suggest using [Homebrew](http://brew.sh/) to install these tools.
-
- autoconf
- ./configure
- make test [gmake on BSD]
-
-### Travis CI Build and Test
-
-The Travis Continuous Integration services can be used to test your changes across multiple platforms. You will need to [fork the fish-shell repository on GitHub](https://help.github.com/articles/fork-a-repo/), or push a copy of the code to your GitHub account.
-
- 1. [Sign in to Travis CI](https://travis-ci.org/auth) with your GitHub account, accepting the GitHub access permissions confirmation.
- 2. Once you're signed in, and your repositories are synchronised, go to your [profile page](https://travis-ci.org/profile) and enable the fish-shell repository.
- 3. Push your changes to GitHub.
-
-You'll receive an email when the tests are complete telling you whether or not any tests failed.
-
-You'll find the configuration used to control Travis in the `.travis.yml` file.
-
## Runtime Dependencies
fish requires a curses implementation, such as ncurses, to run.
@@ -116,6 +90,10 @@ To switch your default shell back, you can run:
Substitute /bin/bash with /bin/tcsh or /bin/zsh as appropriate.
+## Contributing Changes to the Code
+
+See the [Guide for Developers](CONTRIBUTING.md).
+
## Contact Us
Questions, comments, rants and raves can be posted to the official fish mailing list at or join us on our [gitter.im channel](https://gitter.im/fish-shell/fish-shell) or IRC channel [#fish at irc.oftc.net](https://webchat.oftc.net/?channels=fish). Or use the [fish tag on Stackoverflow](https://stackoverflow.com/questions/tagged/fish).
diff --git a/build_tools/lint.fish b/build_tools/lint.fish
old mode 100644
new mode 100755
From 4ff8e6e7818747d805ac44be0a36aedef4deaa5c Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Tue, 5 Apr 2016 15:43:24 -0700
Subject: [PATCH 065/363] change how redirections are formatted
Modify `fish_indent` to emit redirections without a space before the target of
the redirection; e.g., "2>&1" rather than "2>& 1" as the former is clearer to
humans.
Fixes #2899
---
doc_src/fish_indent.txt | 2 +
src/fish_indent.cpp | 103 +++++++++++++++++++++++++++++-----------
src/parse_constants.h | 6 ++-
src/parse_tree.cpp | 43 +++++++++++++++++
tests/indent.in | 6 +++
tests/indent.out | 4 ++
6 files changed, 135 insertions(+), 29 deletions(-)
diff --git a/doc_src/fish_indent.txt b/doc_src/fish_indent.txt
index 95b3c1ec8..b4cf13c0d 100644
--- a/doc_src/fish_indent.txt
+++ b/doc_src/fish_indent.txt
@@ -11,6 +11,8 @@ fish_indent [OPTIONS]
The following options are available:
+- `-d` or `--dump` dumps information about the parsed fish commands to stderr
+
- `-i` or `--no-indent` do not indent commands; only reformat to one job per line
- `-v` or `--version` displays the current fish version and then exits
diff --git a/src/fish_indent.cpp b/src/fish_indent.cpp
index 037d9b773..0e31f28e7 100644
--- a/src/fish_indent.cpp
+++ b/src/fish_indent.cpp
@@ -15,10 +15,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
-/** \file fish_indent.cpp
- The fish_indent proegram.
-*/
-
+// The fish_indent proegram.
#include "config.h"
#include
@@ -45,10 +42,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#define SPACES_PER_INDENT 4
-/* An indent_t represents an abstract indent depth. 2 means we are in a doubly-nested block, etc. */
+// An indent_t represents an abstract indent depth. 2 means we are in a doubly-nested block, etc.
typedef unsigned int indent_t;
+static bool dump_parse_tree = false;
-/* Read the entire contents of a file into the specified string */
+// Read the entire contents of a file into the specified string.
static wcstring read_file(FILE *f)
{
wcstring result;
@@ -69,10 +67,12 @@ static wcstring read_file(FILE *f)
return result;
}
-/* Append whitespace as necessary. If we have a newline, append the appropriate indent. Otherwise, append a space. */
-static void append_whitespace(indent_t node_indent, bool do_indent, bool has_new_line, wcstring *out_result)
+// Append whitespace as necessary. If we have a newline, append the appropriate indent. Otherwise,
+// append a space.
+static void append_whitespace(indent_t node_indent, bool do_indent, bool has_new_line,
+ wcstring *out_result)
{
- if (! has_new_line)
+ if (!has_new_line)
{
out_result->push_back(L' ');
}
@@ -82,26 +82,62 @@ static void append_whitespace(indent_t node_indent, bool do_indent, bool has_new
}
}
-static void prettify_node_recursive(const wcstring &source, const parse_node_tree_t &tree, node_offset_t node_idx, indent_t node_indent, parse_token_type_t parent_type, bool *has_new_line, wcstring *out_result, bool do_indent)
+// Dump a parse tree node in a form helpful to someone debugging the behavior of this program.
+static void dump_node(indent_t node_indent, const parse_node_t &node, const wcstring &source)
+{
+ int nextc_idx = node.source_start + node.source_length;
+ wchar_t prevc = node.source_start > 0 ? source[node.source_start - 1] : L' ';
+ wchar_t nextc = nextc_idx < source.size() ? source[nextc_idx] : L' ';
+ wchar_t prevc_str[4] = {prevc, 0, 0, 0};
+ wchar_t nextc_str[4] = {nextc, 0, 0, 0};
+ if (prevc < L' ')
+ {
+ prevc_str[0] = L'\\';
+ prevc_str[1] = L'c';
+ prevc_str[2] = prevc + '@';
+ }
+ if (nextc < L' ')
+ {
+ nextc_str[0] = L'\\';
+ nextc_str[1] = L'c';
+ nextc_str[2] = nextc + '@';
+ }
+ fwprintf(stderr, L"{off %4d, len %4d, indent %2u, %ls} [%ls|%ls|%ls]\n",
+ node.source_start, node.source_length, node_indent,
+ parser_token_types[node.type].c_str(), prevc_str, source.substr(node.source_start,
+ node.source_length).c_str(), nextc_str);
+}
+
+static void prettify_node_recursive(const wcstring &source, const parse_node_tree_t &tree,
+ node_offset_t node_idx, indent_t node_indent, parse_token_type_t parent_type,
+ bool *has_new_line, wcstring *out_result, bool do_indent)
{
const parse_node_t &node = tree.at(node_idx);
const parse_token_type_t node_type = node.type;
+ const parse_token_type_t prev_node_type = node_idx > 0 ?
+ tree.at(node_idx - 1).type : token_type_invalid;
- /* Increment the indent if we are either a root job_list, or root case_item_list, or in an if or while header (#1665) */
- const bool is_root_job_list = (node_type == symbol_job_list && parent_type != symbol_job_list);
- const bool is_root_case_item_list = (node_type == symbol_case_item_list && parent_type != symbol_case_item_list);
- const bool is_if_while_header = ((node_type == symbol_job || node_type == symbol_andor_job_list) &&
- (parent_type == symbol_if_clause || parent_type == symbol_while_header));
- if (is_root_job_list || is_root_case_item_list || is_if_while_header)
+ // Increment the indent if we are either a root job_list, or root case_item_list, or in an if or
+ // while header (#1665).
+ const bool is_root_job_list = node_type == symbol_job_list && parent_type != symbol_job_list;
+ const bool is_root_case_list = node_type == symbol_case_item_list &&
+ parent_type != symbol_case_item_list;
+ const bool is_if_while_header = \
+ (node_type == symbol_job || node_type == symbol_andor_job_list) &&
+ (parent_type == symbol_if_clause || parent_type == symbol_while_header);
+
+ if (is_root_job_list || is_root_case_list || is_if_while_header)
{
node_indent += 1;
}
- /* Handle comments, which come before the text */
- if (node.has_comments())
+ if (dump_parse_tree) dump_node(node_indent, node, source);
+
+ if (node.has_comments()) // handle comments, which come before the text
{
- const parse_node_tree_t::parse_node_list_t comment_nodes = tree.comment_nodes_for_node(node);
- for (size_t i=0; i < comment_nodes.size(); i++)
+ const parse_node_tree_t::parse_node_list_t comment_nodes = (
+ tree.comment_nodes_for_node(node));
+ for (size_t i = 0; i < comment_nodes.size(); i++)
{
const parse_node_t &comment_node = *comment_nodes.at(i);
append_whitespace(node_indent, do_indent, *has_new_line, out_result);
@@ -111,26 +147,30 @@ static void prettify_node_recursive(const wcstring &source, const parse_node_tre
if (node_type == parse_token_type_end)
{
- /* Newline */
out_result->push_back(L'\n');
*has_new_line = true;
}
- else if ((node_type >= FIRST_PARSE_TOKEN_TYPE && node_type <= LAST_PARSE_TOKEN_TYPE) || node_type == parse_special_type_parse_error)
+ else if ((node_type >= FIRST_PARSE_TOKEN_TYPE && node_type <= LAST_PARSE_TOKEN_TYPE) ||
+ node_type == parse_special_type_parse_error)
{
if (node.has_source())
{
- /* Some type representing a particular token */
- append_whitespace(node_indent, do_indent, *has_new_line, out_result);
+ // Some type representing a particular token.
+ if (prev_node_type != parse_token_type_redirection)
+ {
+ append_whitespace(node_indent, do_indent, *has_new_line, out_result);
+ }
out_result->append(source, node.source_start, node.source_length);
*has_new_line = false;
}
}
- /* Recurse to all our children */
+ // Recurse to all our children.
for (node_offset_t idx = 0; idx < node.child_count; idx++)
{
- /* Note we pass our type to our child, which becomes its parent node type */
- prettify_node_recursive(source, tree, node.child_start + idx, node_indent, node_type, has_new_line, out_result, do_indent);
+ // Note we pass our type to our child, which becomes its parent node type.
+ prettify_node_recursive(source, tree, node.child_start + idx, node_indent, node_type,
+ has_new_line, out_result, do_indent);
}
}
@@ -297,9 +337,10 @@ int main(int argc, char *argv[])
} output_type = output_type_plain_text;
bool do_indent = true;
- const char *short_opts = "+hvi";
+ const char *short_opts = "+dhvi";
const struct option long_opts[] =
{
+ { "dump", no_argument, NULL, 'd' },
{ "no-indent", no_argument, NULL, 'i' },
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'v' },
@@ -319,6 +360,12 @@ int main(int argc, char *argv[])
exit_without_destructors(127);
}
+ case 'd':
+ {
+ dump_parse_tree = true;
+ break;
+ }
+
case 'h':
{
print_help("fish_indent", 1);
diff --git a/src/parse_constants.h b/src/parse_constants.h
index e7c6399f3..afc88c6c2 100644
--- a/src/parse_constants.h
+++ b/src/parse_constants.h
@@ -11,6 +11,8 @@
#define PARSE_ASSERT(a) assert(a)
#define PARSER_DIE() do { fprintf(stderr, "Parser dying!\n"); exit_without_destructors(-1); } while (0)
+// IMPORTANT: If the following enum is modified you must update the corresponding parser_token_types
+// array in parse_tree.cpp.
enum parse_token_type_t
{
token_type_invalid,
@@ -41,7 +43,7 @@ enum parse_token_type_t
symbol_plain_statement,
symbol_arguments_or_redirections_list,
symbol_argument_or_redirection,
-
+
symbol_andor_job_list,
symbol_argument_list,
@@ -80,6 +82,8 @@ enum parse_token_type_t
FIRST_PARSE_TOKEN_TYPE = parse_token_type_string,
LAST_PARSE_TOKEN_TYPE = parse_token_type_end
} __packed;
+// Array of strings corresponding to the enums above instantiated in parse_tree.cpp.
+extern wcstring parser_token_types[];
/* These must be maintained in sorted order (except for none, which isn't a keyword). This enables us to do binary search. */
enum parse_keyword_t
diff --git a/src/parse_tree.cpp b/src/parse_tree.cpp
index 51ae77202..3d2f7b8c7 100644
--- a/src/parse_tree.cpp
+++ b/src/parse_tree.cpp
@@ -16,6 +16,49 @@
#include
#include
+// This array provides strings for each symbol in enum parse_token_type_t in parse_constants.h.
+wcstring parser_token_types[] = {
+ L"token_type_invalid",
+ L"symbol_job_list",
+ L"symbol_job",
+ L"symbol_job_continuation",
+ L"symbol_statement",
+ L"symbol_block_statement",
+ L"symbol_block_header",
+ L"symbol_for_header",
+ L"symbol_while_header",
+ L"symbol_begin_header",
+ L"symbol_function_header",
+ L"symbol_if_statement",
+ L"symbol_if_clause",
+ L"symbol_else_clause",
+ L"symbol_else_continuation",
+ L"symbol_switch_statement",
+ L"symbol_case_item_list",
+ L"symbol_case_item",
+ L"symbol_boolean_statement",
+ L"symbol_decorated_statement",
+ L"symbol_plain_statement",
+ L"symbol_arguments_or_redirections_list",
+ L"symbol_argument_or_redirection",
+ L"symbol_andor_job_list",
+ L"symbol_argument_list",
+ L"symbol_freestanding_argument_list",
+ L"symbol_argument",
+ L"symbol_redirection",
+ L"symbol_optional_background",
+ L"symbol_end_command",
+ L"parse_token_type_string",
+ L"parse_token_type_pipe",
+ L"parse_token_type_redirection",
+ L"parse_token_type_background",
+ L"parse_token_type_end",
+ L"parse_token_type_terminate",
+ L"parse_special_type_parse_error",
+ L"parse_special_type_tokenizer_error",
+ L"parse_special_type_comment",
+ };
+
using namespace parse_productions;
static bool production_is_empty(const production_t *production)
diff --git a/tests/indent.in b/tests/indent.in
index 83ef915b3..a1143c676 100644
--- a/tests/indent.in
+++ b/tests/indent.in
@@ -83,3 +83,9 @@ echo -n '
if begin ; false; end; echo hi ; end
while begin ; false; end; echo hi ; end
' | ../test/root/bin/fish_indent
+
+echo \nTest redir formatting
+# issue 2899
+echo -n '
+echo < stdin >>appended yes 2>&1 no > stdout maybe 2>& 4 | cat 2>| cat
+' | ../test/root/bin/fish_indent
diff --git a/tests/indent.out b/tests/indent.out
index b2eaf08a4..6b38a72fd 100644
--- a/tests/indent.out
+++ b/tests/indent.out
@@ -91,3 +91,7 @@ while begin
end
echo hi
end
+
+Test redir formatting
+
+echo >appended yes 2>&1 no >stdout maybe 2>&4 | cat 2>| cat
From 02f18cae0aa9c44beade38b1b14c9f59d54b9078 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Wed, 6 Apr 2016 13:04:44 -0700
Subject: [PATCH 066/363] fix setting of $argv for `source` w/no args
Fixes #139
---
src/builtin.cpp | 2 +-
tests/test1.in | 8 +++++++-
tests/test1.out | 4 ++++
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/builtin.cpp b/src/builtin.cpp
index dd67817a3..86213a762 100644
--- a/src/builtin.cpp
+++ b/src/builtin.cpp
@@ -3375,7 +3375,7 @@ static int builtin_source(parser_t &parser, io_streams_t &streams, wchar_t **arg
parser.push_block(new source_block_t(fn_intern));
reader_push_current_filename(fn_intern);
- env_set_argv((argc>2)?(argv+2):(argv+1));
+ env_set_argv(argc > 1 ? argv + 2 : argv + 1);
res = reader_read(fd, streams.io_chain ? *streams.io_chain : io_chain_t());
diff --git a/tests/test1.in b/tests/test1.in
index d52d558ee..ff6075cc8 100644
--- a/tests/test1.in
+++ b/tests/test1.in
@@ -166,5 +166,11 @@ function always_fails
end
end
-always_fails ; echo $status
+# Verify $argv set correctly in sourced scripts.
+# Issue #139
+echo 'echo "source argv {$argv}"' | source
+echo 'echo "source argv {$argv}"' | source -
+echo 'echo "source argv {$argv}"' | source - abc
+echo 'echo "source argv {$argv}"' | source - abc def
+always_fails ; echo $status
diff --git a/tests/test1.out b/tests/test1.out
index fb5ea8c8a..26251a3bf 100644
--- a/tests/test1.out
+++ b/tests/test1.out
@@ -52,4 +52,8 @@ pipe 11
pipe 12
Checking for infinite loops in no-execute
before comment after comment
+source argv {}
+source argv {}
+source argv {abc}
+source argv {abc def}
1
From 35e282928ade1b46f9faec8d8bd04c6fe66eafcc Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Wed, 6 Apr 2016 17:18:06 -0700
Subject: [PATCH 067/363] clarify documentation for the `source` command
Make it clear that fish 2.3.0 changed how `$argv` is initialized.
---
doc_src/source.txt | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/doc_src/source.txt b/doc_src/source.txt
index dba14045c..abb99af5f 100644
--- a/doc_src/source.txt
+++ b/doc_src/source.txt
@@ -7,7 +7,7 @@ source FILENAME [ARGUMENTS...]
\subsection source-description Description
-`source` evaluates the commands of the specified file in the current shell. This is different from starting a new process to perform the commands (i.e. `fish < FILENAME`) since the commands will be evaluated by the current shell, which means that changes in shell variables will affect the current shell. If additional arguments are specified after the file name, they will be inserted into the $argv variable.
+`source` evaluates the commands of the specified file in the current shell. This is different from starting a new process to perform the commands (i.e. `fish < FILENAME`) since the commands will be evaluated by the current shell, which means that changes in shell variables will affect the current shell. If additional arguments are specified after the file name, they will be inserted into the `$argv` variable. The `$argv` variable will not include the name of the sourced file.
If no file is specified, or if the file name '`-`' is used, stdin will be read.
@@ -22,3 +22,7 @@ The return status of `source` is the return status of the last job to execute. I
source ~/.config/fish/config.fish
# Causes fish to re-read its initialization file.
\endfish
+
+\subsection Caveats
+
+In fish versions prior to 2.3.0 the `$argv` variable would have a single element (the name of the sourced file) if no arguments are present. Otherwise it would contain arguments without the name of the sourced file. That behavior was very confusing and unlike other shells such as bash and zsh.
From c37c93fcf66d94ce8882cec186fc73e74f28870b Mon Sep 17 00:00:00 2001
From: David Adam
Date: Wed, 6 Apr 2016 22:57:45 +0800
Subject: [PATCH 068/363] configure: remove tiny leftover from xsel build
---
configure.ac | 2 --
1 file changed, 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index 72a210fe6..2a96f63be 100644
--- a/configure.ac
+++ b/configure.ac
@@ -15,8 +15,6 @@ AC_INIT(fish,
m4_esyscmd([cut -f 3 -d ' ' FISH-BUILD-VERSION-FILE | tr -d '\n']),
fish-users@lists.sourceforge.net)
-conf_arg=$@
-
#
# List of output variables produced by this configure script
#
From e1e1e558ce3191dcbda451c8a344b0d56de00910 Mon Sep 17 00:00:00 2001
From: David Adam
Date: Thu, 7 Apr 2016 11:07:44 +0800
Subject: [PATCH 069/363] pcre2: add maintainer mode and disable by default
---
Makefile.in | 2 +-
pcre2-10.20/Makefile.in | 9 +++++----
pcre2-10.20/aclocal.m4 | 36 ++++++++++++++++++++++++++++++++++++
pcre2-10.20/configure | 38 ++++++++++++++++++++++++++++++++++++++
pcre2-10.20/configure.ac | 5 +++++
5 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/Makefile.in b/Makefile.in
index ea008211a..341b9420d 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -821,7 +821,7 @@ $(PCRE2_LIB): $(PCRE2_H)
$(MAKE) -C $(PCRE2_DIR) libpcre2-$(PCRE2_WIDTH).la
$(PCRE2_H):
- (cd $(PCRE2_DIR) && ./config.status --enable-maintainer-mode)
+ (cd $(PCRE2_DIR) && ./config.status)
#
# Build the fish_tests program.
diff --git a/pcre2-10.20/Makefile.in b/pcre2-10.20/Makefile.in
index 9c24e5a2e..defe5d688 100644
--- a/pcre2-10.20/Makefile.in
+++ b/pcre2-10.20/Makefile.in
@@ -708,6 +708,7 @@ LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
@@ -1197,7 +1198,7 @@ all: $(BUILT_SOURCES)
.SUFFIXES: .c .lo .log .o .obj .test .test$(EXEEXT) .trs
am--refresh: Makefile
@:
-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
@@ -1223,9 +1224,9 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
-$(top_srcdir)/configure: $(am__configure_deps)
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
@@ -1236,7 +1237,7 @@ src/config.h: src/stamp-h1
src/stamp-h1: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
@rm -f src/stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status src/config.h
-$(top_srcdir)/src/config.h.in: $(am__configure_deps)
+$(top_srcdir)/src/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f src/stamp-h1
touch $@
diff --git a/pcre2-10.20/aclocal.m4 b/pcre2-10.20/aclocal.m4
index d1a41f717..db6146ab0 100644
--- a/pcre2-10.20/aclocal.m4
+++ b/pcre2-10.20/aclocal.m4
@@ -920,6 +920,42 @@ fi
rmdir .tst 2>/dev/null
AC_SUBST([am__leading_dot])])
+# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996-2014 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless 'enable' is passed literally.
+# For symmetry, 'disable' may be passed as well. Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+ [enable], [m4_define([am_maintainer_other], [disable])],
+ [disable], [m4_define([am_maintainer_other], [enable])],
+ [m4_define([am_maintainer_other], [enable])
+ m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+ dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+ AC_ARG_ENABLE([maintainer-mode],
+ [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode],
+ am_maintainer_other[ make rules and dependencies not useful
+ (and sometimes confusing) to the casual installer])],
+ [USE_MAINTAINER_MODE=$enableval],
+ [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+ AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+ AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+ MAINT=$MAINTAINER_MODE_TRUE
+ AC_SUBST([MAINT])dnl
+]
+)
+
# Check to see how 'make' treats includes. -*- Autoconf -*-
# Copyright (C) 2001-2014 Free Software Foundation, Inc.
diff --git a/pcre2-10.20/configure b/pcre2-10.20/configure
index 15777d450..21e553b3c 100755
--- a/pcre2-10.20/configure
+++ b/pcre2-10.20/configure
@@ -734,6 +734,9 @@ CFLAGS
CC
ac_ct_AR
AR
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
AM_BACKSLASH
AM_DEFAULT_VERBOSITY
AM_DEFAULT_V
@@ -803,6 +806,7 @@ ac_subst_files=''
ac_user_opts='
enable_option_checking
enable_silent_rules
+enable_maintainer_mode
enable_dependency_tracking
enable_shared
enable_static
@@ -1481,6 +1485,9 @@ Optional Features:
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
--enable-silent-rules less verbose build output (undo: "make V=1")
--disable-silent-rules verbose build output (undo: "make V=0")
+ --enable-maintainer-mode
+ enable make rules and dependencies not useful (and
+ sometimes confusing) to the casual installer
--enable-dependency-tracking
do not reject slow dependency extractors
--disable-dependency-tracking
@@ -3129,6 +3136,33 @@ AM_BACKSLASH='\'
ac_config_headers="$ac_config_headers src/config.h"
+# FISH PATCH
+# Enable maintainer mode to avoid spurious rebuilds due to timestamps in git
+# not being stored. Discussion in https://github.com/fish-shell/fish-shell/issues/2469
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+ # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then :
+ enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+ USE_MAINTAINER_MODE=no
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+ if test $USE_MAINTAINER_MODE = yes; then
+ MAINTAINER_MODE_TRUE=
+ MAINTAINER_MODE_FALSE='#'
+else
+ MAINTAINER_MODE_TRUE='#'
+ MAINTAINER_MODE_FALSE=
+fi
+
+ MAINT=$MAINTAINER_MODE_TRUE
+
+
+
# This is a new thing required to stop a warning from automake 1.12
DEPDIR="${am__leading_dot}deps"
@@ -15968,6 +16002,10 @@ else
am__EXEEXT_FALSE=
fi
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+ as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
as_fn_error $? "conditional \"AMDEP\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
diff --git a/pcre2-10.20/configure.ac b/pcre2-10.20/configure.ac
index 20f3937b6..ad6ed7fde 100644
--- a/pcre2-10.20/configure.ac
+++ b/pcre2-10.20/configure.ac
@@ -29,6 +29,11 @@ AM_INIT_AUTOMAKE([dist-bzip2 dist-zip])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_CONFIG_HEADERS(src/config.h)
+# FISH PATCH
+# Enable maintainer mode to avoid spurious rebuilds due to timestamps in git
+# not being stored. Discussion in https://github.com/fish-shell/fish-shell/issues/2469
+AM_MAINTAINER_MODE
+
# This is a new thing required to stop a warning from automake 1.12
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
From 9c755467240d7d2bbfb6a9cdb5e34d411ec9c99b Mon Sep 17 00:00:00 2001
From: David Adam
Date: Thu, 7 Apr 2016 11:13:38 +0800
Subject: [PATCH 070/363] Update osx/config.h for removed ifdefs
---
osx/config.h | 3 ---
1 file changed, 3 deletions(-)
diff --git a/osx/config.h b/osx/config.h
index cab160a34..0a5530168 100644
--- a/osx/config.h
+++ b/osx/config.h
@@ -197,9 +197,6 @@
/* Define to 1 if the winsize struct and TIOCGWINSZ macro exist */
#define HAVE_WINSIZE 1
-/* Define to 1 if getopt_long exists and works. */
-#define HAVE_WORKING_GETOPT_LONG 1
-
/* Define to 1 if the _nl_msg_cat_cntr symbol is exported. */
/* #undef HAVE__NL_MSG_CAT_CNTR */
From 8477126ae4c55d41adb9153f4632c09fffed4626 Mon Sep 17 00:00:00 2001
From: Fabian Homborg
Date: Thu, 7 Apr 2016 18:26:10 +0200
Subject: [PATCH 071/363] Correct true-color statement in set_color docs
- OSX Terminal does not support it
- We do some detection
---
doc_src/set_color.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/doc_src/set_color.txt b/doc_src/set_color.txt
index 087c9ac96..d08373ca6 100644
--- a/doc_src/set_color.txt
+++ b/doc_src/set_color.txt
@@ -44,6 +44,6 @@ set_color normal; echo "Normal is nice" # This will reset background, too
Fish uses a heuristic to decide if your terminal supports the 256 color palette (as opposed to the more limited 16 color palette of older terminals). If you've done the equivalent of `set fish_term256 1` that will be true. If the $TERM value contains "256color" (e.g., "xterm-256color") that will be true. If your $TERM value is "xterm" and $TERM_PROGRAM is not set to "Apple_Terminal" that will be true. If your terminal supports the full 256 color palette (which is pretty much every color terminal emulator written in the past decade) you should ensure one of the aforementioned conditions is true.
-Many terminals support 24-bit (i.e., true-color) color escape sequences. This includes modern xterms, Gnome Terminal, KDE Konsole, and OS X Terminal and iTerm2. Fish does not currently auto-detect whether a given `$TERM` supports 24-bit colors. You can explicitly enable that support via `set fish_term24bit 1`. If you do so fish will not map your RGB color values to the closest known matching color in the ANSI X3.64 color palette.
+Many terminals support 24-bit (i.e., true-color) color escape sequences. This includes modern xterms, Gnome Terminal, KDE Konsole, and iTerm2. Fish currently does some limited attempts to detect whether a given `$TERM` supports 24-bit colors. You can explicitly enable that support via `set fish_term24bit 1`. If you do so fish will not map your RGB color values to the closest known matching color in the ANSI X3.64 color palette.
The `set_color` command uses the terminfo database to look up how to change terminal colors on whatever terminal is in use. Some systems have old and incomplete terminfo databases, and may lack color information for terminals that support it. Fish will use the [ANSI X3.64](https://en.wikipedia.org/wiki/ANSI_escape_code) escape sequences if the terminfo definition says less than 256 colors are supported; otherwise it will use the terminfo definition.
From d2ae00ca44b7ae185835d0e71de244da29f16547 Mon Sep 17 00:00:00 2001
From: ridiculousfish
Date: Thu, 7 Apr 2016 13:29:50 -0700
Subject: [PATCH 072/363] Remove a dead function bool_from_env_var
---
src/env_universal_common.cpp | 6 ------
1 file changed, 6 deletions(-)
diff --git a/src/env_universal_common.cpp b/src/env_universal_common.cpp
index 751136159..900a2d75a 100644
--- a/src/env_universal_common.cpp
+++ b/src/env_universal_common.cpp
@@ -1737,9 +1737,3 @@ bool universal_notifier_t::notification_fd_became_readable(int fd)
{
return false;
}
-
-static bool bool_from_env_var(const char *name, bool default_value)
-{
- const char *var = getenv(name);
- return var ? from_string(var) : default_value;
-}
From 784b438d4a686d6ca317d83133c6827ff23f4453 Mon Sep 17 00:00:00 2001
From: Kurtis Rader
Date: Thu, 7 Apr 2016 13:47:51 -0700
Subject: [PATCH 073/363] fix git command in lint.fish script
---
build_tools/lint.fish | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/build_tools/lint.fish b/build_tools/lint.fish
index ef66d207b..7182322f0 100755
--- a/build_tools/lint.fish
+++ b/build_tools/lint.fish
@@ -35,14 +35,14 @@ else
# We haven't been asked to lint all the source. If there are uncommitted
# changes lint those, else lint the files in the most recent commit.
set pending (git status --porcelain --short --untracked-files=all | sed -e 's/^ *//')
- if count $pending > /dev/null
+ if set -q pending[1]
# There are pending changes so lint those files.
for arg in $pending
set files $files (string split -m 1 ' ' $arg)[2]
end
else
# No pending changes so lint the files in the most recent commit.
- set files (git show --porcelain --name-only --pretty=oneline head | tail --lines=+2)
+ set files (git show --word-diff=porcelain --name-only --pretty=oneline head)[2..-1]
end
# Extract just the C/C++ files.
From 9347630d1e3bbe6aac342ff88378be0e31feee83 Mon Sep 17 00:00:00 2001
From: ridiculousfish
Date: Thu, 7 Apr 2016 13:30:27 -0700
Subject: [PATCH 074/363] Update Xcode project for latest Xcode
---
fish.xcodeproj/project.pbxproj | 2 +-
fish.xcodeproj/xcshareddata/xcschemes/Makefile.xcscheme | 2 +-
fish.xcodeproj/xcshareddata/xcschemes/base.xcscheme | 2 +-
fish.xcodeproj/xcshareddata/xcschemes/fish.app.xcscheme | 2 +-
fish.xcodeproj/xcshareddata/xcschemes/fish_tests.xcscheme | 2 +-
fish.xcodeproj/xcshareddata/xcschemes/install_tree.xcscheme | 2 +-
6 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/fish.xcodeproj/project.pbxproj b/fish.xcodeproj/project.pbxproj
index 6d2ca9028..2d85b93a8 100644
--- a/fish.xcodeproj/project.pbxproj
+++ b/fish.xcodeproj/project.pbxproj
@@ -980,7 +980,7 @@
D0A084F213B3AC130099B651 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0720;
+ LastUpgradeCheck = 0730;
TargetAttributes = {
D008D0C41BC58F8800841177 = {
CreatedOnToolsVersion = 7.0.1;
diff --git a/fish.xcodeproj/xcshareddata/xcschemes/Makefile.xcscheme b/fish.xcodeproj/xcshareddata/xcschemes/Makefile.xcscheme
index 886f78842..ad48a255f 100644
--- a/fish.xcodeproj/xcshareddata/xcschemes/Makefile.xcscheme
+++ b/fish.xcodeproj/xcshareddata/xcschemes/Makefile.xcscheme
@@ -1,6 +1,6 @@
Date: Thu, 7 Apr 2016 15:44:56 -0700
Subject: [PATCH 075/363] Complain less about "bogus" PATH entries
When determining the old path, get the existing value in any scope,
not just the set scope. Also only complain about absolute paths:
relative paths are expected to be invalid sometimes.
---
src/builtin_set.cpp | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/builtin_set.cpp b/src/builtin_set.cpp
index ec530599d..bd871b09d 100644
--- a/src/builtin_set.cpp
+++ b/src/builtin_set.cpp
@@ -64,16 +64,22 @@ static int my_env_set(const wchar_t *key, const wcstring_list_t &val, int scope,
/* Fix for https://github.com/fish-shell/fish-shell/issues/199 . Return success if any path setting succeeds. */
bool any_success = false;
- /* Don't bother validating (or complaining about) values that are already present */
+ /* Don't bother validating (or complaining about) values that are already present.
+ When determining already-present values, use ENV_DEFAULT instead of the passed-in scope because in:
+ set -l PATH stuff $PATH
+ where we are temporarily shadowing a variable, we want to compare against the shadowed value, not the
+ (missing) local value.
+ Also don't bother to complain about relative paths, which don't start with /.
+ */
wcstring_list_t existing_values;
- const env_var_t existing_variable = env_get_string(key, scope);
+ const env_var_t existing_variable = env_get_string(key, ENV_DEFAULT);
if (! existing_variable.missing_or_empty())
tokenize_variable_array(existing_variable, existing_values);
for (i=0; i< val.size() ; i++)
{
const wcstring &dir = val.at(i);
- if (list_contains_string(existing_values, dir))
+ if (!string_prefixes_string(L"/", dir) || list_contains_string(existing_values, dir))
{
any_success = true;
continue;
From 790c7f80c7d0fa1c97380885201eb50a2abcce02 Mon Sep 17 00:00:00 2001
From: Aaron Gyes
Date: Fri, 8 Apr 2016 10:18:58 +0800
Subject: [PATCH 076/363] Implement an --invert/-v for string match, like grep
-v.
Only lines that do not match the pattern are shown.
---
doc_src/string.txt | 12 +++++-
src/builtin_string.cpp | 89 ++++++++++++++++++++++++++----------------
tests/string.in | 25 ++++++++++++
tests/string.out | 17 ++++++++
4 files changed, 107 insertions(+), 36 deletions(-)
diff --git a/doc_src/string.txt b/doc_src/string.txt
index bae21dc99..58de93e40 100644
--- a/doc_src/string.txt
+++ b/doc_src/string.txt
@@ -12,7 +12,7 @@ string trim [(-l | --left)] [(-r | --right)] [(-c | --chars CHARS)]
[(-q | --quiet)] [STRING...]
string escape [(-n | --no-quoted)] [STRING...]
string match [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)]
- [(-n | --index)] [(-q | --quiet)] PATTERN [STRING...]
+ [(-n | --index)] [(-q | --quiet)] [(-v | --invert)] PATTERN [STRING...]
string replace [(-a | --all)] [(-i | --ignore-case)] [(-r | --regex)]
[(-q | --quiet)] PATTERN REPLACEMENT [STRING...]
\endfish
@@ -44,7 +44,7 @@ The following subcommands are available:
- `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.
-- `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. If `-r` or `--regex` is given, PATTERN is interpreted as a Perl-compatible regular expression. 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. Exit status: 0 if at least one match was found, 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. If `-r` or `--regex` is given, PATTERN is interpreted as a Perl-compatible regular expression. 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.
- `replace` is similar to `match` but replaces non-overlapping matching substrings with a replacement string and prints the result. By default, PATTERN is treated as a literal substring to be matched. If `-r` or `--regex` is given, PATTERN is interpreted as a Perl-compatible regular expression, and REPLACEMENT can contain C-style escape sequences like `\t` as well as references to capturing groups by number or name as `$n` or `${n}`. Exit status: 0 if at least one replacement was performed, or 1 otherwise.
@@ -120,6 +120,14 @@ The following subcommands are available:
>_ echo 'ok?' | string match '*\\?'
>_ ok?
+
+>_ string match -r -v "c.*[12]" {cat,dog}(seq 1 4)
+dog1
+dog2
+cat3
+dog3
+cat4
+dog4
\endfish
\subsection string-example-match-regex Match Regex Examples
diff --git a/src/builtin_string.cpp b/src/builtin_string.cpp
index 8911d1ab0..10508a710 100644
--- a/src/builtin_string.cpp
+++ b/src/builtin_string.cpp
@@ -304,9 +304,10 @@ struct match_options_t
bool all;
bool ignore_case;
bool index;
+ bool invert_match;
bool quiet;
- match_options_t(): all(false), ignore_case(false), index(false), quiet(false) { }
+ match_options_t(): all(false), ignore_case(false), index(false), invert_match(false), quiet(false) { }
};
class string_matcher_t
@@ -328,17 +329,15 @@ public:
class wildcard_matcher_t: public string_matcher_t
{
+private:
wcstring wcpattern;
-
public:
wildcard_matcher_t(const wchar_t * /*argv0*/, const wchar_t *pattern, const match_options_t &opts, io_streams_t &streams)
- : string_matcher_t(opts, streams)
+ : string_matcher_t(opts, streams), wcpattern(parse_util_unescape_wildcards(pattern))
{
- wcpattern = parse_util_unescape_wildcards(pattern);
-
if (opts.ignore_case)
{
- for (int i = 0; i < wcpattern.length(); i++)
+ for (size_t i = 0; i < wcpattern.length(); i++)
{
wcpattern[i] = towlower(wcpattern[i]);
}
@@ -352,10 +351,11 @@ public:
// Note: --all is a no-op for glob matching since the pattern is always
// matched against the entire argument
bool match;
+
if (opts.ignore_case)
{
wcstring s = arg;
- for (int i = 0; i < s.length(); i++)
+ for (size_t i = 0; i < s.length(); i++)
{
s[i] = towlower(s[i]);
}
@@ -365,13 +365,11 @@ public:
{
match = wildcard_match(arg, wcpattern, false);
}
- if (match)
+ if (match ^ opts.invert_match)
{
total_matched++;
- }
- if (!opts.quiet)
- {
- if (match)
+
+ if (!opts.quiet)
{
if (opts.index)
{
@@ -458,42 +456,53 @@ class pcre2_matcher_t: public string_matcher_t
// Return values: -1 = error, 0 = no match, 1 = match
if (pcre2_rc == PCRE2_ERROR_NOMATCH)
{
- return 0;
+ if (opts.invert_match && !opts.quiet)
+ {
+ streams.out.append(arg);
+ streams.out.push_back(L'\n');
+ }
+
+ return opts.invert_match ? 1 : 0;
}
- if (pcre2_rc < 0)
+ else if (pcre2_rc < 0)
{
string_error(streams, _(L"%ls: Regular expression match error: %ls\n"),
argv0, pcre2_strerror(pcre2_rc).c_str());
return -1;
}
- if (pcre2_rc == 0)
+ else if (pcre2_rc == 0)
{
// The output vector wasn't big enough. Should not happen.
string_error(streams, _(L"%ls: Regular expression internal error\n"), argv0);
return -1;
}
+
+ else if (opts.invert_match)
+ return 0;
+
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(regex.match);
+
for (int j = 0; j < pcre2_rc; j++)
{
PCRE2_SIZE begin = ovector[2*j];
PCRE2_SIZE end = ovector[2*j + 1];
- if (!opts.quiet)
+
+ if (begin != PCRE2_UNSET && end != PCRE2_UNSET && !opts.quiet)
{
- if (begin != PCRE2_UNSET && end != PCRE2_UNSET)
+ if (opts.index)
{
- if (opts.index)
- {
- streams.out.append_format(L"%lu %lu", (unsigned long)(begin + 1), (unsigned long)(end - begin));
- }
- else if (end > begin) // may have end < begin if \K is used
- {
- streams.out.append(wcstring(&arg[begin], end - begin));
- }
- streams.out.append(L'\n');
+ streams.out.append_format(L"%lu %lu", (unsigned long)(begin + 1), (unsigned long)(end - begin));
}
+ else if (end > begin) // may have end < begin if \K is used
+ {
+ streams.out.append(wcstring(&arg[begin], end - begin));
+ }
+ streams.out.push_back(L'\n');
}
}
- return 1;
+
+ return opts.invert_match ? 0 : 1;
+
}
public:
@@ -525,7 +534,7 @@ public:
// pcre2 match error
return false;
}
- if (rc == 0)
+ else if (rc == 0)
{
// no match
return true;
@@ -533,6 +542,11 @@ public:
matched++;
total_matched++;
+ if (opts.invert_match)
+ {
+ return true;
+ }
+
// Report any additional matches
PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(regex.match);
while (opts.all || matched == 0)
@@ -573,12 +587,13 @@ public:
static int string_match(parser_t &parser, io_streams_t &streams, int argc, wchar_t **argv)
{
- const wchar_t *short_options = L"ainqr";
+ const wchar_t *short_options = L"ainvqr";
const struct woption long_options[] =
{
{ L"all", no_argument, 0, 'a'},
{ L"ignore-case", no_argument, 0, 'i'},
{ L"index", no_argument, 0, 'n'},
+ { L"invert", no_argument, 0, 'v'},
{ L"quiet", no_argument, 0, 'q'},
{ L"regex", no_argument, 0, 'r'},
{ 0, 0, 0, 0 }
@@ -612,6 +627,10 @@ static int string_match(parser_t &parser, io_streams_t &streams, int argc, wchar
opts.index = true;
break;
+ case 'v':
+ opts.invert_match = true;
+ break;
+
case 'q':
opts.quiet = true;
break;
@@ -750,7 +769,7 @@ class regex_replacer_t: public string_replacer_t
compiled_regex_t regex;
wcstring replacement;
- wcstring interpret_escapes(const wchar_t *orig)
+ static wcstring interpret_escapes(const wchar_t *orig)
{
wcstring result;
@@ -782,6 +801,7 @@ public:
bool replace_matches(const wchar_t *arg)
{
+
// A return value of true means all is well (even if no replacements
// were performed), false indicates an unrecoverable error.
if (regex.code == 0)
@@ -1064,7 +1084,7 @@ static int string_split(parser_t &parser, io_streams_t &streams, int argc, wchar
string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
return BUILTIN_STRING_ERROR;
}
-
+
wcstring_list_t splits;
size_t arg_count = 0;
wcstring storage;
@@ -1091,9 +1111,9 @@ static int string_split(parser_t &parser, io_streams_t &streams, int argc, wchar
// If we are from the right, split_about gave us reversed strings, in reversed order!
if (right)
{
- for (size_t i=0; i < splits.size(); i++)
+ for (size_t j = 0; j < splits.size(); j++)
{
- std::reverse(splits[i].begin(), splits[i].end());
+ std::reverse(splits[j].begin(), splits[j].end());
}
std::reverse(splits.begin(), splits.end());
}
@@ -1293,7 +1313,7 @@ static int string_trim(parser_t &parser, io_streams_t &streams, int argc, wchar_
string_error(streams, BUILTIN_ERR_TOO_MANY_ARGUMENTS, argv[0]);
return BUILTIN_STRING_ERROR;
}
-
+
/* if neither left or right is specified, we do both */
if (! do_left && ! do_right)
{
@@ -1339,6 +1359,7 @@ static const struct string_subcommand
const wchar_t *name;
int (*handler)(parser_t &, io_streams_t &, int argc, wchar_t **argv);
}
+
string_subcommands[] =
{
{ L"escape", &string_escape },
diff --git a/tests/string.in b/tests/string.in
index 8afc97ff5..ac858618d 100644
--- a/tests/string.in
+++ b/tests/string.in
@@ -1,5 +1,26 @@
# tests for string builtin
# mostly taken from examples
+
+string match -r -v "c.*" dog can cat diz; and echo "exit 0"
+
+string match -q -r -v "c.*" dog can cat diz; and echo "exit 0"
+
+string match -v "c*" dog can cat diz; and echo "exit 0"
+
+string match -q -v "c*" dog can cat diz; and echo "exit 0"
+
+string match -v "d*" dog dan dat diz; or echo "exit 1"
+
+string match -q -v "d*" dog dan dat diz; or echo "exit 1"
+
+string match -r -v x y; and echo "exit 0"
+
+string match -r -v x x; or echo "exit 1"
+
+string match -q -r -v x y; and echo "exit 0"
+
+string match -q -r -v x x; or echo "exit 1"
+
string length 'hello, world'
string length -q ""; and echo not zero length
@@ -63,3 +84,7 @@ string match -r '[' 'a[sd' 2>/dev/null; or echo "invalid expression error"
string invalidarg 2>/dev/null; or echo "invalid argument error"
string length 2>/dev/null; or echo "missing argument returns 0"
+
+string match -r -v "[dcantg].*" dog can cat diz; or echo "no regexp invert match"
+
+string match -v "???" dog can cat diz; or echo "no glob invert match"
diff --git a/tests/string.out b/tests/string.out
index 45ccb3692..bd3fff457 100644
--- a/tests/string.out
+++ b/tests/string.out
@@ -1,3 +1,18 @@
+dog
+diz
+exit 0
+exit 0
+dog
+diz
+exit 0
+exit 0
+exit 1
+exit 1
+y
+exit 0
+exit 1
+exit 0
+exit 1
12
ab
bc
@@ -45,3 +60,5 @@ aabb
invalid expression error
invalid argument error
missing argument returns 0
+no regexp invert match
+no glob invert match
From 36691df6fe4667645b71b550ce5eea90762ac23a Mon Sep 17 00:00:00 2001
From: Aaron Gyes
Date: Fri, 8 Apr 2016 10:46:51 +0800
Subject: [PATCH 077/363] Stringify many completions and functions, with
--invert stringification.
I believe apm must have been buggy - example output that I found online
showed `tr` was mangling paths with spaces in it. Should be fixed.
Also, use dscl on OS X in __fish_complete_users.fish like
__fish_print_users.fish already does.
---
share/completions/apm.fish | 4 ++--
share/completions/git.fish | 6 +++---
share/completions/gpg.fish | 2 ++
share/completions/npm.fish | 2 +-
share/completions/rustc.fish | 8 ++++----
share/completions/ssh.fish | 4 ++--
share/functions/__fish_complete_pids.fish | 4 ++--
share/functions/__fish_complete_users.fish | 6 ++++--
share/functions/__fish_complete_wvdial_peers.fish | 6 +++---
share/functions/__fish_git_prompt.fish | 4 ++--
share/functions/__fish_paginate.fish | 2 +-
share/functions/__fish_print_abook_emails.fish | 2 +-
share/functions/__fish_print_hostnames.fish | 4 ++--
share/functions/__fish_print_pacman_repos.fish | 2 +-
share/functions/__fish_print_users.fish | 4 ++--
share/tools/web_config/sample_prompts/acidhub.fish | 2 +-
share/tools/web_config/sample_prompts/nim.fish | 4 ++--
17 files changed, 35 insertions(+), 31 deletions(-)
diff --git a/share/completions/apm.fish b/share/completions/apm.fish
index 6b80a1b81..f9bf2f97a 100644
--- a/share/completions/apm.fish
+++ b/share/completions/apm.fish
@@ -61,7 +61,7 @@ end
# Lists all apm config items
function __fish_apm_config_items
- apm config list | grep -v '^;\|^$' | tr "\ =\ " "\t"
+ apm config list | string match -r -v "^\s*;|^\s*\$" | string replace "\w*=\w*" \t
end
# Lists all installed atom packages
@@ -69,7 +69,7 @@ function __fish_apm_list_packages
apm list -b
end
-if apm -h ^| grep -q "Atom Package Manager"
+if apm -h ^| string match -q "Atom Package Manager*"
# Completions for Atom Package Manager
##################
diff --git a/share/completions/git.fish b/share/completions/git.fish
index 8ffdb071c..82ea0e8bf 100644
--- a/share/completions/git.fish
+++ b/share/completions/git.fish
@@ -11,13 +11,13 @@ function __fish_git_commits
end
function __fish_git_branches
- command git branch --no-color -a ^/dev/null | __fish_sgrep -v ' -> ' | string trim -c "* " | string replace -r "^remotes/" ""
+ command git branch --no-color -a ^/dev/null | string match -r -v ' -> ' | string trim -c "* " | string replace -r "^remotes/" ""
end
function __fish_git_unique_remote_branches
# Allow all remote branches with one remote without the remote part
# This is useful for `git checkout` to automatically create a remote-tracking branch
- command git branch --no-color -a ^/dev/null | __fish_sgrep -v ' -> ' | string trim -c "* " | string replace -r "^remotes/[^/]*/" "" | sort | uniq -u
+ command git branch --no-color -a ^/dev/null | string match -r -v ' -> ' | string trim -c "* " | string replace -r "^remotes/[^/]*/" "" | sort | uniq -u
end
function __fish_git_tags
@@ -473,7 +473,7 @@ complete -f -c git -n '__fish_git_using_command status' -l ignore-submodules -x
### tag
complete -f -c git -n '__fish_git_needs_command' -a tag -d 'Create, list, delete or verify a tag object signed with GPG'
-complete -f -c git -n '__fish_git_using_command tag; and __fish_not_contain_opt -s d; and __fish_not_contain_opt -s v; and test (count (commandline -opc | __fish_sgrep -v -e \'^-\')) -eq 3' -a '(__fish_git_branches)' -d 'Branch'
+complete -f -c git -n '__fish_git_using_command tag; and __fish_not_contain_opt -s d; and __fish_not_contain_opt -s v; and test (count (commandline -opc | string match -r -v \'^-\')) -eq 3' -a '(__fish_git_branches)' -d 'Branch'
complete -f -c git -n '__fish_git_using_command tag' -s a -l annotate -d 'Make an unsigned, annotated tag object'
complete -f -c git -n '__fish_git_using_command tag' -s s -l sign -d 'Make a GPG-signed tag'
complete -f -c git -n '__fish_git_using_command tag' -s d -l delete -d 'Remove a tag'
diff --git a/share/completions/gpg.fish b/share/completions/gpg.fish
index 4e9d19104..9c236e654 100644
--- a/share/completions/gpg.fish
+++ b/share/completions/gpg.fish
@@ -47,6 +47,8 @@ function __fish_print_gpg_algo -d "Complete using all algorithms of the type spe
# expire when the function goes out of scope, and the original locale
# will take effect again.
set -lx LC_ALL C
+
+ # XXX this misses certain ciphers in gpg --version - redo this entirely and use fish's annoying group printing as a feature finally!
gpg --version | __fish_sgrep "$argv:"| __fish_sgrep -v "Home:"|cut -d : -f 2 |tr , \n|tr -d " "
end
diff --git a/share/completions/npm.fish b/share/completions/npm.fish
index 05393b858..534967ad0 100644
--- a/share/completions/npm.fish
+++ b/share/completions/npm.fish
@@ -60,7 +60,7 @@ complete -f -c npm -n 'not __fish_npm_needs_option' -a "(__fish_complete_npm)"
# list available npm scripts and their parial content
function __fish_npm_run
- command npm run | command grep -v '^[^ ]' | command grep -v '^$' | command sed "s/^ *//" | while read -l name
+ command npm run | string match -r -v '^[^ ]|^$' | string trim | while read -l name
set -l trim 20
read -l value
echo "$value" | cut -c1-$trim | read -l value
diff --git a/share/completions/rustc.fish b/share/completions/rustc.fish
index d5caa03ca..8dadcaf67 100644
--- a/share/completions/rustc.fish
+++ b/share/completions/rustc.fish
@@ -49,13 +49,13 @@ for line in $rust_docs
end
set -l rust_docs (rustc -W help \
- | egrep \
- '(\s+)(.+)(\s+)(allow|warn|deny|forbid)(\s+){2}([^\n]+)' \
+ | string match -r \
+ '(?:\s+)(?:.+)(?:\s+)(?:allow|warn|deny|forbid)(?:\s+){2}(?:[^\n]+)' \
| string replace -r -i \
'(\s+)(.+)(\s+)(allow|warn|deny|forbid)(\s+){2}([^\n]+)' '$2 $6' \
| string match -r '^.*[^:]$' \
- | egrep -v '^(allow|warn|deny|forbid)$' \
- | egrep -v '^([a-z\-]+)(\s+)(allow|warn|deny|forbid)')
+ | string match -r -v '^(allow|warn|deny|forbid)$' \
+ | string match -r -v '^([a-z\-]+)(\s+)(allow|warn|deny|forbid)')
for line in $rust_docs
set docs (string split -m 1 ' ' $line)
diff --git a/share/completions/ssh.fish b/share/completions/ssh.fish
index 896b542ed..6131c2545 100644
--- a/share/completions/ssh.fish
+++ b/share/completions/ssh.fish
@@ -15,7 +15,7 @@ complete -x -c ssh -d Hostname -a "
"
complete -x -c ssh -d User -a "
-(__fish_print_users | __fish_sgrep -v '^_')@
+(__fish_print_users | string match -r -v '^_')@
"
complete -c ssh --description "Command to run" -x -a '(__fish_complete_subcommand --fcs-skip=2)'
@@ -23,7 +23,7 @@ complete -c ssh -s a --description "Disables forwarding of the authentication ag
complete -c ssh -s A --description "Enables forwarding of the authentication agent"
complete -x -c ssh -s b --description "Interface to transmit from" -a "
(
- cat /proc/net/arp ^/dev/null| __fish_sgrep -v '^IP'|cut -d ' ' -f 1 ^/dev/null
+ cat /proc/net/arp ^/dev/null| string match -r -v '^IP'|cut -d ' ' -f 1 ^/dev/null
)
"
diff --git a/share/functions/__fish_complete_pids.fish b/share/functions/__fish_complete_pids.fish
index 65ba47946..e974ed61f 100644
--- a/share/functions/__fish_complete_pids.fish
+++ b/share/functions/__fish_complete_pids.fish
@@ -1,11 +1,11 @@
function __fish_complete_pids -d "Print a list of process identifiers along with brief descriptions"
# This may be a bit slower, but it's nice - having the tty displayed is really handy
# 'tail -n +2' deletes the first line, which contains the headers
- # 'grep -v...' removes self from the output
+ # %self is removed from output by string match -r -v
set -l SELF %self
# Display the tty if available
# But not if it's just question marks, meaning no tty
- ps axc -o pid,ucomm,tty | grep -v '^\s*'$SELF'\s' | tail -n +2 | string replace -r ' *([0-9]+) +([^ ].*[^ ]|[^ ]) +([^ ]+) *$' '$1\t$2 [$3]' | string replace -r ' *\[\?*\] *$' ''
+ ps axc -o pid,ucomm,tty | string match -r -v '^\s*'$SELF'\s' | tail -n +2 | string replace -r ' *([0-9]+) +([^ ].*[^ ]|[^ ]) +([^ ]+) *$' '$1\t$2 [$3]' | string replace -r ' *\[\?*\] *$' ''
end
diff --git a/share/functions/__fish_complete_users.fish b/share/functions/__fish_complete_users.fish
index 91c254daa..199231be1 100644
--- a/share/functions/__fish_complete_users.fish
+++ b/share/functions/__fish_complete_users.fish
@@ -1,8 +1,10 @@
function __fish_complete_users --description "Print a list of local users, with the real user name as a description"
if test -x /usr/bin/getent
- getent passwd | cut -d : -f 1,5 | sed 's/:/\t/'
+ getent passwd | cut -d : -f 1,5 | string replace -r ':' \t
+ else if test -x /usr/bin/dscl
+ dscl . -list /Users RealName | string match -r -v '^_' | string replace -r ' {2,}' \t
else
- __fish_sgrep -ve '^#' /etc/passwd | cut -d : -f 1,5 | sed 's/:/\t/'
+ string match -v -r '^\s*#' < /etc/passwd | cut -d : -f 1,5 | string replace ':' \t
end
end
diff --git a/share/functions/__fish_complete_wvdial_peers.fish b/share/functions/__fish_complete_wvdial_peers.fish
index 11155b1e2..5eab088bc 100644
--- a/share/functions/__fish_complete_wvdial_peers.fish
+++ b/share/functions/__fish_complete_wvdial_peers.fish
@@ -15,15 +15,15 @@ function __fish_complete_wvdial_peers --description 'Complete wvdial peers' --ar
case -C --config
set store_next true
case '--config=*'
- set cfgfiles (echo $opt | sed 's/--config=//')
+ set cfgfiles (echo $opt | string replace '--config=' '')
end
end
for file in $cfgfiles
if test -f $file
- cat $file | grep '\[Dialer' | sed 's/\[Dialer \(.\+\)\]/\1/'
+ string match -r '\[Dialer' < $file | string replace -r '\[Dialer (.+)\]' '$1'
end
- end | sort -u | grep -v Defaults
+ end | sort -u | string match -v Defaults
end
diff --git a/share/functions/__fish_git_prompt.fish b/share/functions/__fish_git_prompt.fish
index 4fb2f16c8..128a3f975 100644
--- a/share/functions/__fish_git_prompt.fish
+++ b/share/functions/__fish_git_prompt.fish
@@ -286,8 +286,8 @@ function __fish_git_prompt_show_upstream --description "Helper function for __fi
set -l os
set -l commits (command git rev-list --left-right $upstream...HEAD ^/dev/null; set os $status)
if test $os -eq 0
- set -l behind (count (for arg in $commits; echo $arg; end | grep '^<'))
- set -l ahead (count (for arg in $commits; echo $arg; end | grep -v '^<'))
+ set -l behind (count (for arg in $commits; echo $arg; end | string match -r '^<'))
+ set -l ahead (count (for arg in $commits; echo $arg; end | string match -r -v '^<'))
set count "$behind $ahead"
else
set count
diff --git a/share/functions/__fish_paginate.fish b/share/functions/__fish_paginate.fish
index 7887cf6b2..31cdd61fa 100644
--- a/share/functions/__fish_paginate.fish
+++ b/share/functions/__fish_paginate.fish
@@ -5,7 +5,7 @@ function __fish_paginate -d "Paginate the current command using the users defaul
set cmd $PAGER
end
- if commandline -j|grep -v "$cmd *\$" >/dev/null
+ if commandline -j| string match -q -r -v "$cmd *\$"
commandline -aj " ^&1 |$cmd;"
end
diff --git a/share/functions/__fish_print_abook_emails.fish b/share/functions/__fish_print_abook_emails.fish
index c1a8d294e..f32b2aed6 100644
--- a/share/functions/__fish_print_abook_emails.fish
+++ b/share/functions/__fish_print_abook_emails.fish
@@ -1,4 +1,4 @@
function __fish_print_abook_emails --description 'Print email addresses (abook)'
- abook --mutt-query "" | egrep -v '^\s*$'
+ abook --mutt-query "" | string match -r -v '^\s*$'
end
diff --git a/share/functions/__fish_print_hostnames.fish b/share/functions/__fish_print_hostnames.fish
index 385157768..40499d1e7 100644
--- a/share/functions/__fish_print_hostnames.fish
+++ b/share/functions/__fish_print_hostnames.fish
@@ -5,11 +5,11 @@ function __fish_print_hostnames -d "Print a list of known hostnames"
# Print all hosts from /etc/hosts
if type -q getent
# Ignore zero ips
- getent hosts | grep -v '^0.0.0.0' \
+ getent hosts | string match -r -v '^0.0.0.0' \
| string replace -r '[0-9.]*\s*' '' | string split " "
else if test -r /etc/hosts
# Ignore commented lines and functionally empty lines
- grep -v '^\s*0.0.0.0\|^\s*#\|^\s*$' /etc/hosts \
+ string match -r -v '^\s*0.0.0.0|^\s*#|^\s*$' < /etc/hosts \
# Strip comments
| string replace -ra '#.*$' '' \
| string replace -r '[0-9.]*\s*' '' | string trim | string replace -ra '\s+' '\n'
diff --git a/share/functions/__fish_print_pacman_repos.fish b/share/functions/__fish_print_pacman_repos.fish
index 81fe3de5d..1998f7216 100644
--- a/share/functions/__fish_print_pacman_repos.fish
+++ b/share/functions/__fish_print_pacman_repos.fish
@@ -1,3 +1,3 @@
function __fish_print_pacman_repos --description "Print the repositories configured for arch's pacman package manager"
- sed -n -e 's/\[\(.\+\)\]/\1/p' /etc/pacman.conf | grep -v "#\|options"
+ string replace -r -a "\[(.+)\]" "\1" < /etc/pacman.conf | string match -r -v "^#|options"
end
diff --git a/share/functions/__fish_print_users.fish b/share/functions/__fish_print_users.fish
index f6d41fa93..d2915760f 100644
--- a/share/functions/__fish_print_users.fish
+++ b/share/functions/__fish_print_users.fish
@@ -3,9 +3,9 @@ function __fish_print_users --description "Print a list of local users"
if test -x /usr/bin/getent
getent passwd | cut -d : -f 1
else if test -x /usr/bin/dscl # OS X support
- dscl . -list /Users | __fish_sgrep -v '^_'
+ dscl . -list /Users | string match -r -v '^_'
else
- __fish_sgrep -ve '^#' /etc/passwd | cut -d : -f 1
+ string match -v -r '^\w*#' < /etc/passwd | cut -d : -f 1
end
end
diff --git a/share/tools/web_config/sample_prompts/acidhub.fish b/share/tools/web_config/sample_prompts/acidhub.fish
index 45a7223e4..afb702463 100644
--- a/share/tools/web_config/sample_prompts/acidhub.fish
+++ b/share/tools/web_config/sample_prompts/acidhub.fish
@@ -12,7 +12,7 @@ function fish_prompt -d "Write out the prompt"
if [ (_git_branch_name) ]
set -l git_branch (set_color -o blue)(_git_branch_name)
if [ (_is_git_dirty) ]
- for i in (git branch -qv --no-color|grep \*|cut -d' ' -f4-|cut -d] -f1|tr , \n)\
+ for i in (git branch -qv --no-color| string match -r \*|cut -d' ' -f4-|cut -d] -f1|tr , \n)\
(git status --porcelain | cut -c 1-2 | uniq)
switch $i
case "*[ahead *"
diff --git a/share/tools/web_config/sample_prompts/nim.fish b/share/tools/web_config/sample_prompts/nim.fish
index 347af1d4d..5d2dac394 100644
--- a/share/tools/web_config/sample_prompts/nim.fish
+++ b/share/tools/web_config/sample_prompts/nim.fish
@@ -3,7 +3,7 @@
function fish_prompt
and set retc green; or set retc red
- tty|grep -q tty; and set tty tty; or set tty pts
+ tty|string match -q -r tty; and set tty tty; or set tty pts
set_color $retc
if [ $tty = tty ]
@@ -48,7 +48,7 @@ function fish_prompt
echo -n ]
if type -q acpi
- if [ (acpi -a 2> /dev/null | grep off) ]
+ if [ (acpi -a 2> /dev/null | string match -r off) ]
echo -n '─['
set_color -o red
echo -n (acpi -b|cut -d' ' -f 4-)
From e395a0eb6927f298fcc7d0764ed27605941f34c0 Mon Sep 17 00:00:00 2001
From: ridiculousfish
Date: Thu, 7 Apr 2016 15:24:52 -0700
Subject: [PATCH 078/363] Migrate PATH-completion logic from complete.cpp to
expand.cpp
Prior to this fix, when completing a command that doesn't have a /, we
would prepend each component of PATH and then expand the whole thing. So
any special characters in the PATH would be interpreted when performing
tab completion.
With this fix, we pull the PATH resolution out of complete.cpp and
migrate it to expand.cpp. This unifies nicely with the CDPATH resolution
already in that file. This requires introducing a new expand flag
EXPAND_SPECIAL_FOR_COMMAND, which is analogous to EXPAND_SPECIAL_CD
(which is renamed to EXPAND_SPECIAL_FOR_CD). This flag tells expand to
resolve paths against PATH instead of the working directory.
Fixes #952
---
src/complete.cpp | 49 ++----------------------------------------------
src/expand.cpp | 41 +++++++++++++++++++++++++---------------
src/expand.h | 8 ++++++--
src/wildcard.cpp | 8 ++++----
tests/test6.in | 34 +++++++++++++++++++++++++++++++++
tests/test6.out | 2 ++
6 files changed, 74 insertions(+), 68 deletions(-)
diff --git a/src/complete.cpp b/src/complete.cpp
index 8af2c822f..5c817b8d0 100644
--- a/src/complete.cpp
+++ b/src/complete.cpp
@@ -851,8 +851,7 @@ void completer_t::complete_cmd(const wcstring &str_cmd, bool use_function, bool
if (use_command)
{
-
- if (expand_string(str_cmd, &this->completions, EXPAND_FOR_COMPLETIONS | EXECUTABLES_ONLY | this->expand_flags(), NULL) != EXPAND_ERROR)
+ if (expand_string(str_cmd, &this->completions, EXPAND_SPECIAL_FOR_COMMAND | EXPAND_FOR_COMPLETIONS | EXECUTABLES_ONLY | this->expand_flags(), NULL) != EXPAND_ERROR)
{
if (this->wants_descriptions())
{
@@ -869,52 +868,8 @@ void completer_t::complete_cmd(const wcstring &str_cmd, bool use_function, bool
}
if (str_cmd.find(L'/') == wcstring::npos && str_cmd.at(0) != L'~')
{
- if (use_command)
- {
-
- const env_var_t path = this->vars.get(L"PATH");
- if (!path.missing())
- {
- wcstring base_path;
- wcstokenizer tokenizer(path, ARRAY_SEP_STR);
- while (tokenizer.next(base_path))
- {
- if (base_path.empty())
- continue;
-
- /* Make sure the base path ends with a slash */
- if (base_path.at(base_path.size() - 1) != L'/')
- base_path.push_back(L'/');
-
- wcstring nxt_completion = base_path;
- nxt_completion.append(str_cmd);
-
- size_t prev_count = this->completions.size();
- expand_flags_t expand_flags = EXPAND_FOR_COMPLETIONS | EXECUTABLES_ONLY | EXPAND_NO_FUZZY_DIRECTORIES | this->expand_flags();
- if (expand_string(nxt_completion,
- &this->completions,
- expand_flags, NULL) != EXPAND_ERROR)
- {
- /* For all new completions, if COMPLETE_REPLACES_TOKEN is set, then use only the last path component */
- for (size_t i=prev_count; i< this->completions.size(); i++)
- {
- completion_t &c = this->completions.at(i);
- if (c.flags & COMPLETE_REPLACES_TOKEN)
- {
-
- c.completion.erase(0, base_path.size());
- }
- }
- }
- }
- if (this->wants_descriptions())
- this->complete_cmd_desc(str_cmd);
- }
- }
-
if (use_function)
{
- //function_get_names( &possible_comp, cmd[0] == L'_' );
wcstring_list_t names = function_get_names(str_cmd.at(0) == L'_');
for (size_t i=0; i < names.size(); i++)
{
@@ -1361,7 +1316,7 @@ void completer_t::complete_param_expand(const wcstring &str, bool do_file, bool
if (handle_as_special_cd && do_file)
{
- flags |= DIRECTORIES_ONLY | EXPAND_SPECIAL_CD | EXPAND_NO_DESCRIPTIONS;
+ flags |= DIRECTORIES_ONLY | EXPAND_SPECIAL_FOR_CD | EXPAND_NO_DESCRIPTIONS;
}
/* Squelch file descriptions per issue 254 */
diff --git a/src/expand.cpp b/src/expand.cpp
index de67ffa84..cb68eb980 100644
--- a/src/expand.cpp
+++ b/src/expand.cpp
@@ -1800,36 +1800,47 @@ static expand_error_t expand_stage_wildcards(const wcstring &input, std::vector<
const wcstring working_dir = env_get_pwd_slash();
wcstring_list_t effective_working_dirs;
- if (! (flags & EXPAND_SPECIAL_CD))
+ bool for_cd = !!(flags & EXPAND_SPECIAL_FOR_CD);
+ bool for_command = !!(flags & EXPAND_SPECIAL_FOR_COMMAND);
+ if (!for_cd && !for_command)
{
/* Common case */
effective_working_dirs.push_back(working_dir);
}
else
{
- /* Ignore the CDPATH if we start with ./ or / */
- if (string_prefixes_string(L"./", path_to_expand))
- {
- effective_working_dirs.push_back(working_dir);
- }
- else if (string_prefixes_string(L"/", path_to_expand))
+ /* Either EXPAND_SPECIAL_FOR_COMMAND or EXPAND_SPECIAL_FOR_CD. We can handle these mostly the same.
+ There's the following differences:
+ 1. An empty CDPATH should be treated as '.', but an empty PATH should be left empty (no commands can be found).
+ 2. PATH is only "one level," while CDPATH is multiple levels. That is, input like 'foo/bar' should resolve
+ against CDPATH, but not PATH.
+
+ In either case, we ignore the path if we start with ./ or /.
+ Also ignore it if we are doing command completion and we contain a slash, per IEEE 1003.1, chapter 8 under PATH
+ */
+ if (string_prefixes_string(L"./", path_to_expand) ||
+ string_prefixes_string(L"/", path_to_expand) ||
+ (for_command && path_to_expand.find(L'/') != wcstring::npos))
{
effective_working_dirs.push_back(working_dir);
}
else
{
- /* Get the CDPATH and cwd. Perhaps these should be passed in. */
- env_var_t cdpath = env_get_string(L"CDPATH");
- if (cdpath.missing_or_empty())
- cdpath = L".";
+ /* Get the PATH/CDPATH and cwd. Perhaps these should be passed in.
+ An empty CDPATH implies just the current directory, while an empty PATH is left empty.
+ */
+ env_var_t paths = env_get_string(for_cd ? L"CDPATH" : L"PATH");
+ if (paths.missing_or_empty())
+ paths = for_cd ? L"." : L"";
/* Tokenize it into directories */
- wcstokenizer tokenizer(cdpath, ARRAY_SEP_STR);
- wcstring next_cd_path;
- while (tokenizer.next(next_cd_path))
+ wcstokenizer tokenizer(paths, ARRAY_SEP_STR);
+ wcstring next_path;
+ while (tokenizer.next(next_path))
{
/* Ensure that we use the working directory for relative cdpaths like "." */
- effective_working_dirs.push_back(path_apply_working_directory(next_cd_path, working_dir));
+ effective_working_dirs.push_back(path_apply_working_directory(next_path, working_dir));
+
}
}
}
diff --git a/src/expand.h b/src/expand.h
index 6ae91cca3..fafbcd2ad 100644
--- a/src/expand.h
+++ b/src/expand.h
@@ -52,8 +52,12 @@ enum
// Disallow directory abbreviations like /u/l/b for /usr/local/bin. Only
// applicable if EXPAND_FUZZY_MATCH is set.
EXPAND_NO_FUZZY_DIRECTORIES = 1 << 10,
- // Do expansions specifically to support cd (CDPATH, etc).
- EXPAND_SPECIAL_CD = 1 << 11
+ // Do expansions specifically to support cd
+ // This means using CDPATH as a list of potential working directories
+ EXPAND_SPECIAL_FOR_CD = 1 << 11,
+ // Do expansions specifically to support external command completions.
+ // This means using PATH as a list of potential working directories
+ EXPAND_SPECIAL_FOR_COMMAND = 1 << 12
};
typedef int expand_flags_t;
diff --git a/src/wildcard.cpp b/src/wildcard.cpp
index db211818c..202b836d4 100644
--- a/src/wildcard.cpp
+++ b/src/wildcard.cpp
@@ -789,8 +789,8 @@ class wildcard_expander_t
c.prepend_token_prefix(this->original_base);
}
- /* Hack. Implement EXPAND_SPECIAL_CD by descending the deepest unique hierarchy we can, and then appending any components to each new result. */
- if (flags & EXPAND_SPECIAL_CD)
+ /* Hack. Implement EXPAND_SPECIAL_FOR_CD by descending the deepest unique hierarchy we can, and then appending any components to each new result. */
+ if (flags & EXPAND_SPECIAL_FOR_CD)
{
wcstring unique_hierarchy = this->descend_unique_hierarchy(abs_path);
if (! unique_hierarchy.empty())
@@ -1138,8 +1138,8 @@ int wildcard_expand_string(const wcstring &wc, const wcstring &working_directory
/* Fuzzy matching only if we're doing completions */
assert((flags & (EXPAND_FUZZY_MATCH | EXPAND_FOR_COMPLETIONS)) != EXPAND_FUZZY_MATCH);
- /* EXPAND_SPECIAL_CD requires DIRECTORIES_ONLY and EXPAND_FOR_COMPLETIONS and EXPAND_NO_DESCRIPTIONS */
- assert(!(flags & EXPAND_SPECIAL_CD) ||
+ /* EXPAND_SPECIAL_FOR_CD requires DIRECTORIES_ONLY and EXPAND_FOR_COMPLETIONS and EXPAND_NO_DESCRIPTIONS */
+ assert(!(flags & EXPAND_SPECIAL_FOR_CD) ||
((flags & DIRECTORIES_ONLY) && (flags & EXPAND_FOR_COMPLETIONS) && (flags & EXPAND_NO_DESCRIPTIONS)));
/* Hackish fix for 1631. We are about to call c_str(), which will produce a string truncated at any embedded nulls. We could fix this by passing around the size, etc. However embedded nulls are never allowed in a filename, so we just check for them and return 0 (no matches) if there is an embedded null. */
diff --git a/tests/test6.in b/tests/test6.in
index 252eb6068..0d6ef4878 100644
--- a/tests/test6.in
+++ b/tests/test6.in
@@ -72,3 +72,37 @@ if begin; rm -rf test6.tmp.dir; and mkdir test6.tmp.dir; end
else
echo "error: could not create temp environment" >&2
end
+
+# Test command expansion with parened PATHs (#952)
+begin
+ set -l parened_path $PWD/'test6.tmp2.(paren).dir'
+ set -l parened_subpath $parened_path/subdir
+ if not begin
+ rm -rf $parened_path
+ and mkdir $parened_path
+ and mkdir $parened_subpath
+ and ln -s /bin/ls $parened_path/'__test6_(paren)_command'
+ and ln -s /bin/ls $parened_subpath/'__test6_subdir_(paren)_command'
+ end
+ echo "error: could not create command expansion temp environment" >&2
+ end
+
+ # Verify that we can expand commands when PATH has parens
+ set -l PATH $parened_path $PATH
+ set -l completed (complete -C__test6_ | cut -f 1 -d \t)
+ if test "$completed" = '__test6_(paren)_command'
+ echo "Command completion with parened PATHs test passed"
+ else
+ echo "Command completion with parened PATHs test failed. Expected __test6_(paren)_command, got $completed" >&2
+ end
+
+ # Verify that commands with intermediate slashes do NOT expand with respect to PATH
+ set -l completed (complete -Csubdir/__test6_subdir)
+ if test -z "$completed"
+ echo "Command completion with intermediate slashes passed"
+ else
+ echo "Command completion with intermediate slashes: should output nothing, instead got $completed" >&2
+ end
+
+ rm -rf $parened_path
+end
diff --git a/tests/test6.out b/tests/test6.out
index 268b05eab..ca6e69066 100644
--- a/tests/test6.out
+++ b/tests/test6.out
@@ -33,3 +33,5 @@ CCCC:
implicit cd complete works
no implicit cd complete after 'command'
PATH does not cause incorrect implicit cd
+Command completion with parened PATHs test passed
+Command completion with intermediate slashes passed
From 2ff3a366752bf96ccc71bdc70ecc10f31de0f901 Mon Sep 17 00:00:00 2001
From: David Adam
Date: Fri, 8 Apr 2016 12:39:15 +0800
Subject: [PATCH 079/363] CHANGELOG: move release_notes.html to a markdown
document
[ci skip]
---
CHANGELOG.md | 156 ++++++++++++++++++++++++++++++++
release_notes.html | 219 ---------------------------------------------
2 files changed, 156 insertions(+), 219 deletions(-)
create mode 100644 CHANGELOG.md
delete mode 100644 release_notes.html
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 000000000..e42bd92e3
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,156 @@
+# fish 2.0.0
+
+Significant Changes
+-------------------
+
+* **Command substitutions now modify `$status` #547.**
+ Previously the exit status of command substitutions (like `(pwd)`) was ignored; however now it modifies $status. Furthermore, the `set` command now only sets $status on failure; it is untouched on success. This allows for the following pattern:
+
+ ```sh
+ if set python_path (which python)
+ ...
+ end
+ ```
+ Because set does not modify $status on success, the if branch effectively tests whether `which` succeeded, and if so, whether the `set` also succeeded.
+* **Improvements to $PATH handling.**
+ * There is a new variable, `$fish_user_paths`, which can be set universally, and whose contents are appended to $PATH #527
+ * /etc/paths and /etc/paths.d are now respected on OS X
+ * fish no longer modifies $PATH to find its own binaries
+* **Long lines no longer use ellipsis for line breaks**, and copy and paste
+ should no longer include a newline even if the line was broken #300
+* **New syntax for index ranges** (sometimes known as "slices") #212
+* **fish now supports an `else if` statement** #134
+* **Process and pid completion now works on OS X** #129
+* **fish is now relocatable**, and no longer depends on compiled-in paths #125
+* **fish now supports a right prompt (RPROMPT)** through the fish_right_prompt function #80
+* **fish now uses posix_spawn instead of fork when possible**, which is much faster on BSD and OS X #11
+
+Other Notable Fixes
+-------------------
+
+* Updated VCS completions (darcs, cvs, svn, etc.)
+* Avoid calling getcwd on the main thread, as it can hang #696
+* Control-D (forward delete) no longer stops at a period #667
+* Completions for many new commands
+* fish now respects rxvt's unique keybindings #657
+* xsel is no longer built as part of fish. It will still be invoked if installed separately #633
+* __fish_filter_mime no longer spews #628
+* The --no-execute option to fish no longer falls over when reaching the end of a block #624
+* fish_config knows how to find fish even if it's not in the $PATH #621
+* A leading space now prevents writing to history, as is done in bash and zsh #615
+* Hitting enter after a backslash only goes to a new line if it is followed by whitespace or the end of the line #613
+* printf is now a builtin #611
+* Event handlers should no longer fire if signals are blocked #608
+* set_color is now a builtin #578
+* man page completions are now located in a new generated_completions directory, instead of your completions directory #576
+* tab now clears autosuggestions #561
+* tab completion from within a pair of quotes now attempts to "appropriate" the closing quote #552
+* $EDITOR can now be a list: for example, `set EDITOR gvim -f`) #541
+* `case` bodies are now indented #530
+* The profile switch `-p` no longer crashes #517
+* You can now control-C out of `read` #516
+* `umask` is now functional on OS X #515
+* Avoid calling getpwnam on the main thread, as it can hang #512
+* Alt-F or Alt-right-arrow (Option-F or option-right-arrow) now accepts one word of an autosuggestion #435
+* Setting fish as your login shell no longer kills OpenSUSE #367
+* Backslashes now join lines, instead of creating multiple commands #347
+* echo now implements the -e flag to interpret escapes #337
+* When the last token in the user's input contains capital letters, use its case in preference to that of the autosuggestion #335
+* Descriptions now have their own muted color #279
+* Wildcards beginning with a . (for example, `ls .*`) no longer match . and .. #270
+* Recursive wildcards now handle symlink loops #268
+* You can now delete history items from the fish_config web interface #250
+* The OS X build now weak links `wcsdup` and `wcscasecmp` #240
+* fish now saves and restores the process group, which prevents certain processes from being erroneously reported as stopped #197
+* funced now takes an editor option #187
+* Alternating row colors are available in fish pager through `fish_pager_color_secondary` #186
+* Universal variable values are now stored based on your MAC address, not your hostname #183
+* The caret ^ now only does a stderr redirection if it is the first character of a token, making git users happy #168
+* Autosuggestions will no longer cause line wrapping #167
+* Better handling of Unicode combining characters #155
+* fish SIGHUPs processes more often #138
+* fish no longer causes `sudo` to ask for a password every time
+* fish behaves better under Midnight Commander #121
+* `set -e` no longer crashes #100
+* fish now will automatically import history from bash, if there is no fish history #66
+* Backslashed-newlines inside quoted strings now behave more intuitively #52
+* Tab titles should be shown correctly in iTerm2 #47
+* scp remote path completion now sometimes works #42
+* The `read` builtin no longer shows autosuggestions #29
+* Custom key bindings can now be set via the `fish_user_key_bindings` function #21
+* All Python scripts now run correctly under both Python 2 and Python 3 #14
+* The "accept autosuggestion" key can now be configured #19
+* Autosuggestions will no longer suggest invalid commands #6
+
+---
+
+# fishfish Beta r2
+
+Bug Fixes
+---------
+
+* **Implicit cd** is back, for paths that start with one or two dots, a slash, or a tilde.
+* **Overrides of default functions should be fixed.** The "internalized scripts" feature is disabled for now.
+* **Disabled delayed suspend.** This is a strange job-control feature of BSD systems, including OS X. Disabling it frees up Control Y for other purposes; in particular, for yank, which now works on OS X.
+* **fish_indent is fixed.** In particular, the `funced` and `funcsave` functions work again.
+* A SIGTERM now ends the whole execution stack again (resolving #13).
+* Bumped the __fish_config_interactive version number so the default fish_color_autosuggestion kicks in.
+* fish_config better handles combined term256 and classic colors like "555 yellow".
+
+New Features
+------------
+
+* **A history builtin**, and associated interactive function that enables deleting history items. Example usage:
+ * Print all history items beginning with echo: `history --prefix echo`
+ * Print all history items containing foo: `history --contains foo`
+ * Interactively delete some items containing foo: `history --delete --contains foo`
+
+Credit to @siteshwar for implementation. Thanks @siteshwar!
+
+---
+
+# fishfish Beta r1
+
+## Scripting
+* No changes! All existing fish scripts, config files, completions, etc. from trunk should continue to work.
+
+## New Features
+* **Autosuggestions**. Think URL fields in browsers. When you type a command, fish will suggest the rest of the command after the cursor, in a muted gray when possible. You can accept the suggestion with the right arrow key or Ctrl-F. Suggestions come from command history, completions, and some custom code for cd; there's a lot of potential for improvement here. The suggestions are computed on a background pthread, so they never slow down your typing. The autosuggestion feature is incredible. I miss it dearly every time I use anything else.
+
+* **term256 support** where available, specifically modern xterms and OS X Lion. You can specify colors the old way ('set_color cyan') or by specifying RGB hex values ('set_color FF3333'); fish will pick the closest supported color. Some xterms do not advertise term256 support either in the $TERM or terminfo max_colors field, but nevertheless support it. For that reason, fish will default into using it on any xterm (but it can be disabled with an environment variable).
+
+* **Web-based configuration** page. There is a new function 'fish_config'. This spins up a simple Python web server and opens a browser window to it. From this web page, you can set your shell colors and view your functions, variables, and history; all changes apply immediately to all running shells. Eventually all configuration ought to be supported via this mechanism (but in addition to, not instead of, command line mechanisms).
+
+* **Man page completions**. There is a new function 'fish_update_completions'. This function reads all the man1 files from your manpath, removes the roff formatting, parses them to find the commands and options, and outputs fish completions into ~/.config/fish/completions. It won't overwrite existing completion files (except ones that it generated itself).
+
+## Programmatic Changes
+* fish is now entirely in C++. I have no particular love for C++, but it provides a ready memory-model to replace halloc. We've made an effort to keep it to a sane and portable subset (no C++11, no boost, no going crazy with templates or smart pointers), but we do use the STL and a little tr1.
+* halloc is entirely gone, replaced by normal C++ ownership semantics. If you don't know what halloc is, well, now you have two reasons to be happy.
+* All the crufty C data structures are entirely gone. array_list_t, priority_queue_t, hash_table_t, string_buffer_t have been removed and replaced by STL equivalents like std::vector, std::map, and std::wstring. A lot of the string handling now uses std::wstring instead of wchar_t *
+* fish now spawns pthreads for tasks like syntax highlighting that require blocking I/O.
+* History has been completely rewritten. History files now use an extensible YAML-style syntax. History "merging" (multiple shells writing to the same history file) now works better. There is now a maximum history length of about 250k items (256 * 1024).
+* The parser has been "instanced," so you can now create more than one.
+* Total #LoC has shrunk slightly even with the new features.
+
+## Performance
+* fish now runs syntax highlighting in a background thread, so typing commands is always responsive even on slow filesystems.
+* echo, test, and pwd are now builtins, which eliminates many forks.
+* The files in share/functions and share/completions now get 'internalized' into C strings that get compiled in with fish. This substantially reduces the number of files touched at startup. A consequence is that you cannot change these functions without recompiling, but often other functions depend on these "standard" functions, so changing them is perhaps not a good idea anyways.
+
+Here are some system call counts for launching and then exiting fish with the default configuration, on OS X. The first column is fish trunk, the next column is with our changes, and the last column is bash for comparison. This data was collected via dtrace.
+
+
+ | | before | after | bash
+ |
| open | 9 | 4 | 5
+ |
| fork | 28 | 14 | 0
+ |
| stat | 131 | 85 | 11
+ |
| lstat | 670 | 0 | 0
+ |
| read | 332 | 80 | 4
+ |
| write | 172 | 149 | 0
+ |
+
+The large number of forks relative to bash are due to fish's insanely expensive default prompt, which is unchanged in my version. If we switch to a prompt comparable to bash's (lame) default, the forks drop to 16 with trunk, 4 after our changes.
+
+The large reduction in lstat() numbers is due to fish no longer needing to call ttyname() on OS X.
+
+We've got some work to do to be as lean as bash, but we're on the right track.
diff --git a/release_notes.html b/release_notes.html
deleted file mode 100644
index 8f300c5ce..000000000
--- a/release_notes.html
+++ /dev/null
@@ -1,219 +0,0 @@
-
-fishfish shell release notes
-
-
-Release Notes for fish 2.0.0
-
-Significant Changes
-
-
-- Command substitutions now modify $status #547.
-
-Previously the exit status of command substitutions (like (pwd)) was ignored; however now it modifies $status. Furthermore, the set command now only sets $status on failure; it is untouched on success. This allows for the following pattern:
-
-if set python_path (which python)
- ...
-end
-
-
-Because set does not modify $status on success, the if branch effectively tests whether which succeeded, and if so, whether the set also succeeded.
-
-
-
-Improvements to $PATH handling.
-
-
- There is a new variable, $fish_user_paths, which can be set universally, and whose contents are appended to $PATH #527
-- /etc/paths and /etc/paths.d are now respected on OS X
-- fish no longer modifies $PATH to find its own binaries
-
-
-
-
-Long lines no longer use ellipsis for line breaks, and copy and paste should no longer include a newline even if the line was broken #300
-
-New syntax for index ranges (sometimes known as "slices") #212
-
-fish now supports an else if statement #134
-
-Process and pid completion now works on OS X #129
-
-fish is now relocatable, and no longer depends on compiled-in paths #125
-
-fish now supports a right prompt (RPROMPT) through the fish_right_prompt function #80
-
-fish now uses posix_spawn instead of fork when possible, which is much faster on BSD and OS X #11
-
-
-
-Other Notable Fixes
-
-- Updated VCS completions (darcs, cvs, svn, etc.)
-- Avoid calling getcwd on the main thread, as it can hang #696
-- Control-D (forward delete) no longer stops at a period #667
-- Completions for many new commands
-- fish now respects rxvt's unique keybindings #657
-- xsel is no longer built as part of fish. It will still be invoked if installed separately #633
-- __fish_filter_mime no longer spews #628
-- The --no-execute option to fish no longer falls over when reaching the end of a block #624
-- fish_config knows how to find fish even if it's not in the $PATH #621
-- A leading space now prevents writing to history, as is done in bash and zsh #615
-- Hitting enter after a backslash only goes to a new line if it is followed by whitespace or the end of the line #613
-- printf is now a builtin #611
-- Event handlers should no longer fire if signals are blocked #608
-- set_color is now a builtin #578
-- man page completions are now located in a new generated_completions directory, instead of your completions directory #576
-- tab now clears autosuggestions #561
-- tab completion from within a pair of quotes now attempts to "appropriate" the closing quote #552
-- $EDITOR can now be a list: for example, set EDITOR gvim -f) #541
-- case bodies are now indented #530
-- The profile switch -p no longer crashes #517
-- You can now control-C out of read #516
-- umask is now functional on OS X #515
-- Avoid calling getpwnam on the main thread, as it can hang #512
-- Alt-F or Alt-right-arrow (Option-F or option-right-arrow) now accepts one word of an autosuggestion #435
-- Setting fish as your login shell no longer kills OpenSUSE #367
-- Backslashes now join lines, instead of creating multiple commands #347
-- echo now implements the -e flag to interpret escapes #337
-- When the last token in the user's input contains capital letters, use its case in preference to that of the autosuggestion #335
-- Descriptions now have their own muted color #279
-- Wildcards beginning with a . (for example, ls .*) no longer match . and .. #270
-- Recursive wildcards now handle symlink loops #268
-- You can now delete history items from the fish_config web interface #250
-- The OS X build now weak links wcsdup and wcscasecmp #240
-- fish now saves and restores the process group, which prevents certain processes from being erroneously reported as stopped #197
-- funced now takes an editor option #187
-- Alternating row colors are available in fish pager through fish_pager_color_secondary #186
-- Universal variable values are now stored based on your MAC address, not your hostname #183
-- The caret ^ now only does a stderr redirection if it is the first character of a token, making git users happy #168
-- Autosuggestions will no longer cause line wrapping #167
-- Better handling of Unicode combining characters #155
-- fish SIGHUPs processes more often #138
-- fish no longer causes sudo to ask for a password every time
-- fish behaves better under Midnight Commander #121
-- set -e no longer crashes #100
-- fish now will automatically import history from bash, if there is no fish history #66
-- Backslashed-newlines inside quoted strings now behave more intuitively #52
-- Tab titles should be shown correctly in iTerm2 #47
-- scp remote path completion now sometimes works #42
-- The read builtin no longer shows autosuggestions #29
-- Custom key bindings can now be set via the fish_user_key_bindings function #21
-- All Python scripts now run correctly under both Python 2 and Python 3 #14
-- The "accept autosuggestion" key can now be configured #19
-- Autosuggestions will no longer suggest invalid commands #6
-
-
-
-Release Notes for fishfish Beta r2
-
-Bug Fixes
-
-- Implicit cd is back, for paths that start with one or two dots, a slash, or a tilde.
-- Overrides of default functions should be fixed. The "internalized scripts" feature is disabled for now.
-- Disabled delayed suspend. This is a strange job-control feature of BSD systems, including OS X. Disabling it frees up Control Y for other purposes; in particular, for yank, which now works on OS X.
-- fish_indent is fixed. In particular, the funced and funcsave functions work again.
-
- A SIGTERM now ends the whole execution stack again (resolving this issue).
-
- Bumped the __fish_config_interactive version number so the default fish_color_autosuggestion kicks in.
-
- fish_config better handles combined term256 and classic colors like "555 yellow".
-
-
-
-New Features
-
-- A history builtin, and associated interactive function that enables deleting history items. Example usage:
-
-
-- Print all history items beginning with echo: history --prefix echo
-- Print all history items containing foo: history --contains foo
-- Interactively delete some items containing foo: history --delete --contains foo
-
-Credit to Siteshwar for implementation. Thanks Siteshwar!
-
-
-
-
-
-Release Notes for fishfish Beta r1
-
-Scripting
-
- - No changes! All existing fish scripts, config files, completions, etc. from trunk should continue to work.
-
-
-New Features
-
-
-- Autosuggestions. Think URL fields in browsers. When you type a command, fish will suggest the rest of the command after the cursor, in a muted gray when possible. You can accept the suggestion with the right arrow key or Ctrl-F. Suggestions come from command history, completions, and some custom code for cd; there's a lot of potential for improvement here. The suggestions are computed on a background pthread, so they never slow down your typing.
-
-The autosuggestion feature is incredible. I miss it dearly every time I use anything else.
-
-- term256 support where available, specifically modern xterms and OS X Lion. You can specify colors the old way ('set_color cyan') or by specifying RGB hex values ('set_color FF3333'); fish will pick the closest supported color. Some xterms do not advertise term256 support either in the $TERM or terminfo max_colors field, but nevertheless support it. For that reason, fish will default into using it on any xterm (but it can be disabled with an environment variable).
-
-- Web-based configuration page. There is a new function 'fish_config'. This spins up a simple Python web server and opens a browser window to it. From this web page, you can set your shell colors and view your functions, variables, and history; all changes apply immediately to all running shells. Eventually all configuration ought to be supported via this mechanism (but in addition to, not instead of, command line mechanisms).
-
-- Man page completions. There is a new function 'fish_update_completions'. This function reads all the man1 files from your manpath, removes the roff formatting, parses them to find the commands and options, and outputs fish completions into ~/.config/fish/completions. It won't overwrite existing completion files (except ones that it generated itself).
-
-
-
-Programmatic Changes
-
-
-
-- fish is now entirely in C++. I have no particular love for C++, but it provides a ready memory-model to replace halloc. We've made an effort to keep it to a sane and portable subset (no C++11, no boost, no going crazy with templates or smart pointers), but we do use the STL and a little tr1.
-
-- halloc is entirely gone, replaced by normal C++ ownership semantics. If you don't know what halloc is, well, now you have two reasons to be happy.
-
-- All the crufty C data structures are entirely gone. array_list_t, priority_queue_t, hash_table_t, string_buffer_t have been removed and replaced by STL equivalents like std::vector, std::map, and std::wstring. A lot of the string handling now uses std::wstring instead of wchar_t *
-
-- fish now spawns pthreads for tasks like syntax highlighting that require blocking I/O.
-
-- History has been completely rewritten. History files now use an extensible YAML-style syntax. History "merging" (multiple shells writing to the same history file) now works better. There is now a maximum history length of about 250k items (256 * 1024).
-
-- The parser has been "instanced," so you can now create more than one.
-
-- Total #LoC has shrunk slightly even with the new features.
-
-
-Performance
-
-
-
-- fish now runs syntax highlighting in a background thread, so typing commands is always responsive even on slow filesystems.
-
-- echo, test, and pwd are now builtins, which eliminates many forks.
-
-- The files in share/functions and share/completions now get 'internalized' into C strings that get compiled in with fish. This substantially reduces the number of files touched at startup. A consequence is that you cannot change these functions without recompiling, but often other functions depend on these "standard" functions, so changing them is perhaps not a good idea anyways.
-
-
-Here are some system call counts for launching and then exiting fish with the default configuration, on OS X. The first column is fish trunk, the next column is with our changes, and the last column is bash for comparison. This data was collected via dtrace.
-
-
- before after bash
- open 9 4 5
- fork 28 14 0
- stat 131 85 11
- lstat 670 0 0
- read 332 80 4
- write 172 149 0
-
-
-The large number of forks relative to bash are due to fish's insanely expensive default prompt, which is unchanged in my version. If we switch to a prompt comparable to bash's (lame) default, the forks drop to 16 with trunk, 4 after our changes.
-
-
The large reduction in lstat() numbers is due to fish no longer needing to call ttyname() on OS X.
-
-
We've got some work to do to be as lean as bash, but we're on the right track.
-
-