Merge branch 'master' into parser_cleanup

This commit is contained in:
ridiculousfish 2014-03-15 20:24:25 -07:00
commit 5c54ef7b0d
32 changed files with 25433 additions and 21676 deletions

2
.gitignore vendored
View file

@ -20,7 +20,6 @@ doc_src/index.hdr
po/*.gmo
fish
fish_indent
fish_pager
fish_tests
fishd
mimedb
@ -35,3 +34,4 @@ tests/*tmp.*
tests/foo.txt
FISH-BUILD-VERSION-FILE
version
messages.pot

View file

@ -57,7 +57,6 @@ CXXFLAGS = @CXXFLAGS@ $(MACROS) $(EXTRA_CXXFLAGS)
LDFLAGS = @LDFLAGS@
LDFLAGS_FISH = ${LDFLAGS} @LIBS_FISH@ @LDFLAGS_FISH@
LDFLAGS_FISH_INDENT = ${LDFLAGS} @LIBS_FISH_INDENT@
LDFLAGS_FISH_PAGER = ${LDFLAGS} @LIBS_FISH_PAGER@
LDFLAGS_FISHD = ${LDFLAGS} @LIBS_FISHD@
LDFLAGS_MIMEDB = ${LDFLAGS} @LIBS_MIMEDB@
@ -106,15 +105,6 @@ BUILTIN_FILES := builtin_set.cpp builtin_commandline.cpp \
builtin_set_color.cpp builtin_printf.cpp
#
# All objects that the system needs to build fish_pager
#
FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \
input_common.o env_universal.o env_universal_common.o common.o \
print_help.o iothread.o color.o
#
# All objects that the system needs to build fish_tests
#
@ -192,7 +182,7 @@ FUNCTIONS_DIR_FILES := $(wildcard share/functions/*.fish)
# Programs to install
#
PROGRAMS := fish mimedb fish_pager fishd fish_indent
PROGRAMS := fish mimedb fishd fish_indent
#
# Manual pages to install
@ -239,7 +229,7 @@ FISH-BUILD-VERSION-FILE: FORCE
-include FISH-BUILD-VERSION-FILE
CPPFLAGS += -DFISH_BUILD_VERSION=\"$(FISH_BUILD_VERSION)\"
.PHONY: FORCE
env.o fish.o fish_indent.o fish_pager.o fishd.o mimedb.o: FISH-BUILD-VERSION-FILE
env.o fish.o fish_indent.o fishd.o mimedb.o: FISH-BUILD-VERSION-FILE
#
@ -410,10 +400,10 @@ doc.h: $(HDR_FILES)
messages.pot: *.cpp *.h share/completions/*.fish share/functions/*.fish
if test "$(HAVE_GETTEXT)" = 1; then \
xgettext -k_ -kN_ *.cpp *.h -o messages.pot; \
if xgettext -j -k_ -kN_ -k--description -LShell share/completions/*.fish share/functions/*.fish -o messages.pot; then true; else \
echo "Your xgettext version is too old to build the messages.pot file"\
rm messages.pot\
false;\
if xgettext -j -k_ -kN_ -k--description -LShell --from-code=UTF-8 share/completions/*.fish share/functions/*.fish -o messages.pot; then true; else \
echo "Your xgettext version is too old to build the messages.pot file"; \
rm messages.pot; \
false; \
fi; \
fi
@ -699,14 +689,6 @@ fish: $(FISH_OBJS) fish.o
$(CXX) $(CXXFLAGS) $(FISH_OBJS) fish.o $(LDFLAGS_FISH) -o $@
#
# Build the fish_pager program.
#
fish_pager: $(FISH_PAGER_OBJS)
$(CXX) $(CXXFLAGS) $(FISH_PAGER_OBJS) $(LDFLAGS_FISH_PAGER) -o $@
#
# Build the fishd program.
#
@ -863,9 +845,6 @@ fish.o: expand.h intern.h exec.h output.h screen.h history.h path.h input.h
fish.o: input_common.h
fish_indent.o: config.h fallback.h signal.h util.h common.h wutil.h
fish_indent.o: tokenizer.h print_help.h parser_keywords.h
fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h
fish_pager.o: output.h screen.h highlight.h env.h color.h input_common.h
fish_pager.o: env_universal.h env_universal_common.h print_help.h
fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h
fish_tests.o: parse_tree.h tokenizer.h parse_constants.h reader.h complete.h
fish_tests.o: highlight.h env.h color.h builtin.h function.h event.h

View file

@ -7,7 +7,7 @@ For more on fish's design philosophy, see the [design document](http://fishshell
## Quick Start
fish generally works like other shells, like bash or zsh. A few important differences can be found at <http://fishshell.com/tutorial.html> by searching for magic phrase 'unlike other shells'.
fish generally works like other shells, like bash or zsh. A few important differences can be found at <http://fishshell.com/tutorial.html> by searching for the magic phrase 'unlike other shells'.
Detailed user documentation is available by running `help` within fish, and also at <http://fishshell.com/docs/2.0/index.html>
@ -17,8 +17,12 @@ fish is written in a sane subset of C++98, with a few components from C++TR1. It
fish can be built using autotools or Xcode. autoconf 2.60 or later is required.
fish depends on a curses implementation, such as ncurses. The headers and libraries are required for building.
fish requires gettext for translation support.
Building the documentation requires Doxygen 1.5 or newer.
### Autotools Build
autoconf
@ -36,7 +40,7 @@ fish requires gettext for translation support.
xcodebuild install
sudo ditto /tmp/fish.dst /
## Build Dependencies (or, Help, it didn't build!)
## Help, it didn't build!
If fish reports that it could not find curses, try installing a curses development package and build again.
@ -44,23 +48,21 @@ On Debian or Ubuntu you want:
sudo apt-get install libncurses5-dev
on RedHat, CentOS, or Amazon EC2:
On RedHat, CentOS, or Amazon EC2:
sudo yum install ncurses-devel
To build with translation support, make sure you have a gettext package installed.
To build the documentation, make sure you have Doxygen installed.
## Runtime Dependencies
fish requires a number of utilities to operate, which should be present on any Unix, GNU/Linux or OS X system. These include (but are not limited to) grep, awk, sed, which, and getopt. The bc program is also required.
fish requires a curses implementation, such as ncurses, to run.
fish requires a number of utilities to operate, which should be present on any Unix, GNU/Linux or OS X system. These include (but are not limited to) hostname, grep, awk, sed, which, and getopt. fish also requires the bc program.
Translation support requires the gettext program.
Some optional features of fish, such as the manual page completion parser and the web configuration tool, require Python.
In order to generate completions from man pages compressed with either lzma or xz, you may need to install an extra Python package.
Python versions prior to 2.6 are not supported. For Python versions 2.6 to 3.2 you need to install the module `backports.lzma`. How to install it depends on your system and how you installed Python. Most Linux distributions should include it as a package named `backports-lzma` (or similar). From version 3.3 onwards, Python already includes the required module.
In order to generate completions from man pages compressed with either lzma or xz, you may need to install an extra Python package. Python versions prior to 2.6 are not supported. For Python versions 2.6 to 3.2 you need to install the module `backports.lzma`. How to install it depends on your system and how you installed Python. Most Linux distributions should include it as a package named `backports-lzma` (or similar). From version 3.3 onwards, Python already includes the required module.
## Packages for Linux

View file

@ -19,7 +19,7 @@ static const int kAutoloadStalenessInterval = 15;
file_access_attempt_t access_file(const wcstring &path, int mode)
{
//printf("Touch %ls\n", path.c_str());
file_access_attempt_t result = {0};
file_access_attempt_t result = {};
struct stat statbuf;
if (wstat(path, &statbuf))
{

View file

@ -214,7 +214,7 @@ static int builtin_commandline(parser_t &parser, wchar_t **argv)
int line_mode = 0;
int search_mode = 0;
int paging_mode = 0;
const wchar_t *begin, *end;
const wchar_t *begin = NULL, *end = NULL;
current_buffer = (wchar_t *)builtin_complete_get_temporary_buffer();
if (current_buffer)

View file

@ -576,7 +576,7 @@ wcstring wsetlocale(int category, const wchar_t *locale)
return format_string(L"%s", res);
}
bool contains_internal(const wchar_t *a, ...)
bool contains_internal(const wchar_t *a, int vararg_handle, ...)
{
const wchar_t *arg;
va_list va;
@ -584,7 +584,7 @@ bool contains_internal(const wchar_t *a, ...)
CHECK(a, 0);
va_start(va, a);
va_start(va, vararg_handle);
while ((arg=va_arg(va, const wchar_t *))!= 0)
{
if (wcscmp(a,arg) == 0)
@ -598,17 +598,19 @@ bool contains_internal(const wchar_t *a, ...)
return res;
}
/* wcstring variant of contains_internal. The first parameter is a wcstring, the rest are const wchar_t* */
__sentinel bool contains_internal(const wcstring &needle, ...)
/* wcstring variant of contains_internal. The first parameter is a wcstring, the rest are const wchar_t *. vararg_handle exists only to give us a POD-value to apss to va_start */
__sentinel bool contains_internal(const wcstring &needle, int vararg_handle, ...)
{
const wchar_t *arg;
va_list va;
int res = 0;
va_start(va, needle);
const wchar_t *needle_cstr = needle.c_str();
va_start(va, vararg_handle);
while ((arg=va_arg(va, const wchar_t *))!= 0)
{
if (needle == arg)
/* libc++ has an unfortunate implementation of operator== that unconditonally wcslen's the wchar_t* parameter, so prefer wcscmp directly */
if (! wcscmp(needle_cstr, arg))
{
res=1;
break;

View file

@ -228,7 +228,7 @@ extern const wchar_t *program_name;
/**
Check if the specified string element is a part of the specified string list
*/
#define contains( str,... ) contains_internal( str, __VA_ARGS__, NULL )
#define contains( str, ... ) contains_internal( str, 0, __VA_ARGS__, NULL )
/**
Print a stack trace to stderr
@ -688,8 +688,8 @@ wcstring wsetlocale(int category, const wchar_t *locale);
\return zero if needle is not found, of if needle is null, non-zero otherwise
*/
__sentinel bool contains_internal(const wchar_t *needle, ...);
__sentinel bool contains_internal(const wcstring &needle, ...);
__sentinel bool contains_internal(const wchar_t *needle, int vararg_handle, ...);
__sentinel bool contains_internal(const wcstring &needle, int vararg_handle, ...);
/**
Call read while blocking the SIGCHLD signal. Should only be called

View file

@ -55,13 +55,6 @@
*/
#define COMPLETE_SEP_STR L"\004"
/**
* Separator between completion items in fish_pager. This is used for
* completion grouping, e.g. when putting completions with the same
* descriptions on the same line.
*/
#define COMPLETE_ITEM_SEP L'\uf500'
/**
* Character that separates the completion and description on
* programmable completions

View file

@ -26,7 +26,6 @@ AC_SUBST(HAVE_DOXYGEN)
AC_SUBST(LDFLAGS_FISH)
AC_SUBST(LIBS_FISH)
AC_SUBST(LIBS_FISH_INDENT)
AC_SUBST(LIBS_FISH_PAGER)
AC_SUBST(LIBS_FISHD)
AC_SUBST(LIBS_MIMEDB)
@ -435,14 +434,6 @@ LIBS_FISH=$LIBS
LIBS="$LIBS_SHARED"
LIBS_FISH_INDENT=$LIBS
#
# Check for libraries needed by fish_pager.
#
LIBS="$LIBS_SHARED"
AC_SEARCH_LIBS( iconv_open, iconv, , [AC_SEARCH_LIBS( libiconv_open, iconv, , [AC_MSG_ERROR([Could not find an iconv implementation, needed to build fish])] )] )
LIBS_FISH_PAGER=$LIBS
#
# Check for libraries needed by fishd.
#

View file

@ -266,7 +266,7 @@ Next, do the following (assuming fish was installed to /usr/local):
rm -Rf /usr/local/etc/fish /usr/local/share/fish ~/.config/fish
rm /usr/local/share/man/man1/fish*.1
cd /usr/local/bin
rm -f fish mimedb fish_pager fishd fish_indent
rm -f fish mimedb fishd fish_indent
</pre>
*/

View file

@ -1,7 +0,0 @@
\section fish_pager fish_pager - internal command used by fish
\subsection fish_pager-description Description
\c fish_pager is used internally by fish. It should not be used by other
commands, as its interface is liable to change in the future.

View file

@ -58,7 +58,7 @@ signal_list_t;
active, which is the one that new events is written to. The inactive
one contains the events that are currently beeing performed.
*/
static signal_list_t sig_list[]= {{0,0},{0,0}};
static signal_list_t sig_list[]= {{},{}};
/**
The index of sig_list that is the list of signals currently written to

View file

@ -929,7 +929,7 @@ void exec_job(parser_t &parser, job_t *j)
if (p->next)
{
// Be careful to handle failure, e.g. too many open fds
block_output_io_buffer.reset(io_buffer_t::create(false /* = not input */, STDOUT_FILENO));
block_output_io_buffer.reset(io_buffer_t::create(STDOUT_FILENO));
if (block_output_io_buffer.get() == NULL)
{
exec_error = true;
@ -958,7 +958,7 @@ void exec_job(parser_t &parser, job_t *j)
{
if (p->next)
{
block_output_io_buffer.reset(io_buffer_t::create(0));
block_output_io_buffer.reset(io_buffer_t::create(STDOUT_FILENO));
if (block_output_io_buffer.get() == NULL)
{
/* We failed (e.g. no more fds could be created). */
@ -1606,7 +1606,7 @@ static int exec_subshell_internal(const wcstring &cmd, wcstring_list_t *lst, boo
int subcommand_status = -1; //assume the worst
// IO buffer creation may fail (e.g. if we have too many open files to make a pipe), so this may be null
const shared_ptr<io_buffer_t> io_buffer(io_buffer_t::create(0));
const shared_ptr<io_buffer_t> io_buffer(io_buffer_t::create(STDOUT_FILENO));
if (io_buffer.get() != NULL)
{
parser_t &parser = parser_t::principal_parser();

View file

@ -53,31 +53,6 @@ parameter expansion.
#include "parse_util.h"
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on $?
*/
#define COMPLETE_YOU_WANT_STATUS _( L"$? is not a valid variable in fish. If you want the exit status of the last command, try $status.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean %ls{$%ls}%ls? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
/**
Description for child process
*/
@ -871,7 +846,7 @@ void expand_variable_error(parser_t &parser, const wcstring &token, size_t token
*(cpy+token_pos)=0;
wchar_t *name = &cpy[stop_pos+1];
wchar_t *end = wcschr(name, BRACKET_END);
wchar_t *post;
wchar_t *post = NULL;
int is_var=0;
if (end)
{

View file

@ -18,7 +18,6 @@
dependencies = (
D07D265715E33B86009E43F6 /* PBXTargetDependency */,
D07D265915E33B86009E43F6 /* PBXTargetDependency */,
D07D265B15E33B86009E43F6 /* PBXTargetDependency */,
D07D265D15E33B86009E43F6 /* PBXTargetDependency */,
D0A56500168D257900AF6161 /* PBXTargetDependency */,
);
@ -49,7 +48,6 @@
dependencies = (
D0F01A1315AA36280034B3B1 /* PBXTargetDependency */,
D0F01A1515AA362E0034B3B1 /* PBXTargetDependency */,
D0F01A1915AA36310034B3B1 /* PBXTargetDependency */,
D0F01A1715AA36300034B3B1 /* PBXTargetDependency */,
D0A564EF168D09C000AF6161 /* PBXTargetDependency */,
);
@ -172,24 +170,11 @@
D0D02ADB159864C2008E62BD /* tokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855D13B3ACEE0099B651 /* tokenizer.cpp */; };
D0D02ADC159864D5008E62BD /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8C15983CFA008E62BD /* libncurses.dylib */; };
D0D02ADD159864D7008E62BD /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8A15983CDF008E62BD /* libiconv.dylib */; };
D0D02AEA15986549008E62BD /* libncurses.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8C15983CFA008E62BD /* libncurses.dylib */; };
D0D02AEB1598654C008E62BD /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D0D02A8A15983CDF008E62BD /* libiconv.dylib */; };
D0D1CD6C15B7451900F03988 /* fish_pager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854013B3ACEE0099B651 /* fish_pager.cpp */; };
D0D1CD6D15B7452100F03988 /* output.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855113B3ACEE0099B651 /* output.cpp */; };
D0D1CD6E15B7452600F03988 /* wutil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0856113B3ACEE0099B651 /* wutil.cpp */; };
D0D1CD6F15B7452D00F03988 /* input_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854913B3ACEE0099B651 /* input_common.cpp */; };
D0D1CD7015B7453300F03988 /* env_universal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853913B3ACEE0099B651 /* env_universal.cpp */; };
D0D1CD7115B7453700F03988 /* env_universal_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853813B3ACEE0099B651 /* env_universal_common.cpp */; };
D0D1CD7215B7454A00F03988 /* print_help.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0855613B3ACEE0099B651 /* print_help.cpp */; };
D0D1CD7315B7455200F03988 /* color.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0B6B0FE14E88BA400AD6C10 /* color.cpp */; };
D0D1CD7415B7456000F03988 /* iothread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854D13B3ACEE0099B651 /* iothread.cpp */; };
D0D1CD7515B7458B00F03988 /* common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853613B3ACEE0099B651 /* common.cpp */; };
D0D2694915983772005D9B9C /* function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0854413B3ACEE0099B651 /* function.cpp */; };
D0D2694A15983779005D9B9C /* builtin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D0A0853513B3ACEE0099B651 /* builtin.cpp */; };
D0F019F115A977140034B3B1 /* fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D2693C159835CA005D9B9C /* fish */; };
D0F019F215A977270034B3B1 /* fishd in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D02ABC15985EF9008E62BD /* fishd */; };
D0F019F315A977290034B3B1 /* fish_indent in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D02AD01598642A008E62BD /* fish_indent */; };
D0F019F415A9772C0034B3B1 /* fish_pager in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0D02AE415986537008E62BD /* fish_pager */; };
D0F019F815A977AB0034B3B1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0CBD580159EE48F0024809C /* config.fish */; };
D0F019FD15A977CA0034B3B1 /* config.fish in CopyFiles */ = {isa = PBXBuildFile; fileRef = D0C4FD9415A7D7EE00212EF1 /* config.fish */; };
D0F01A0315A978910034B3B1 /* osx_fish_launcher.m in Sources */ = {isa = PBXBuildFile; fileRef = D0D02AFA159871B2008E62BD /* osx_fish_launcher.m */; };
@ -219,13 +204,6 @@
remoteGlobalIDString = D0D02ABB15985EF9008E62BD;
remoteInfo = fishd;
};
D07D265C15E33B86009E43F6 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D0A084F213B3AC130099B651 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D0D02AE315986537008E62BD;
remoteInfo = fish_pager;
};
D07D265E15E33B86009E43F6 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D0A084F213B3AC130099B651 /* Project object */;
@ -268,13 +246,6 @@
remoteGlobalIDString = D0D02ACF1598642A008E62BD;
remoteInfo = fish_indent;
};
D0F01A1815AA36310034B3B1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D0A084F213B3AC130099B651 /* Project object */;
proxyType = 1;
remoteGlobalIDString = D0D02AE315986537008E62BD;
remoteInfo = fish_pager;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@ -355,7 +326,6 @@
D0F019F115A977140034B3B1 /* fish in CopyFiles */,
D0F019F215A977270034B3B1 /* fishd in CopyFiles */,
D0F019F315A977290034B3B1 /* fish_indent in CopyFiles */,
D0F019F415A9772C0034B3B1 /* fish_pager in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -458,7 +428,6 @@
D0A0853D13B3ACEE0099B651 /* expand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = expand.cpp; sourceTree = "<group>"; };
D0A0853E13B3ACEE0099B651 /* fallback.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fallback.cpp; sourceTree = "<group>"; };
D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_indent.cpp; sourceTree = "<group>"; };
D0A0854013B3ACEE0099B651 /* fish_pager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_pager.cpp; sourceTree = "<group>"; };
D0A0854113B3ACEE0099B651 /* fish_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish_tests.cpp; sourceTree = "<group>"; };
D0A0854213B3ACEE0099B651 /* fish.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fish.cpp; sourceTree = "<group>"; };
D0A0854313B3ACEE0099B651 /* fishd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fishd.cpp; sourceTree = "<group>"; };
@ -516,7 +485,6 @@
D0D02AA915985C0C008E62BD /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = osx/Info.plist; sourceTree = "<group>"; };
D0D02ABC15985EF9008E62BD /* fishd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fishd; sourceTree = BUILT_PRODUCTS_DIR; };
D0D02AD01598642A008E62BD /* fish_indent */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fish_indent; sourceTree = BUILT_PRODUCTS_DIR; };
D0D02AE415986537008E62BD /* fish_pager */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fish_pager; sourceTree = BUILT_PRODUCTS_DIR; };
D0D02AFA159871B2008E62BD /* osx_fish_launcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = osx_fish_launcher.m; path = osx/osx_fish_launcher.m; sourceTree = "<group>"; };
D0D2693C159835CA005D9B9C /* fish */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = fish; sourceTree = BUILT_PRODUCTS_DIR; };
D0D9B2B318555D92001AE279 /* parse_constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = parse_constants.h; sourceTree = "<group>"; };
@ -554,15 +522,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
D0D02AE115986537008E62BD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D0D02AEA15986549008E62BD /* libncurses.dylib in Frameworks */,
D0D02AEB1598654C008E62BD /* libiconv.dylib in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D0D26939159835CA005D9B9C /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -676,7 +635,6 @@
D0A0850E13B3ACEE0099B651 /* function.h */,
D0A0854413B3ACEE0099B651 /* function.cpp */,
D0A0853F13B3ACEE0099B651 /* fish_indent.cpp */,
D0A0854013B3ACEE0099B651 /* fish_pager.cpp */,
D0A0854113B3ACEE0099B651 /* fish_tests.cpp */,
D0A0854213B3ACEE0099B651 /* fish.cpp */,
D0A0854313B3ACEE0099B651 /* fishd.cpp */,
@ -789,7 +747,6 @@
D0D02A9A15985A75008E62BD /* fish.app */,
D0D02ABC15985EF9008E62BD /* fishd */,
D0D02AD01598642A008E62BD /* fish_indent */,
D0D02AE415986537008E62BD /* fish_pager */,
D08A328D17B4455100F3A533 /* fish_tests */,
);
name = Products;
@ -890,22 +847,6 @@
productReference = D0D02AD01598642A008E62BD /* fish_indent */;
productType = "com.apple.product-type.tool";
};
D0D02AE315986537008E62BD /* fish_pager */ = {
isa = PBXNativeTarget;
buildConfigurationList = D0D02AE715986537008E62BD /* Build configuration list for PBXNativeTarget "fish_pager" */;
buildPhases = (
D0D02AE015986537008E62BD /* Sources */,
D0D02AE115986537008E62BD /* Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = fish_pager;
productName = fish_pager;
productReference = D0D02AE415986537008E62BD /* fish_pager */;
productType = "com.apple.product-type.tool";
};
D0D2693B159835CA005D9B9C /* fish_shell */ = {
isa = PBXNativeTarget;
buildConfigurationList = D0D26943159835CA005D9B9C /* Build configuration list for PBXNativeTarget "fish_shell" */;
@ -948,7 +889,6 @@
D0D2693B159835CA005D9B9C /* fish_shell */,
D0D02ABB15985EF9008E62BD /* fishd */,
D0D02ACF1598642A008E62BD /* fish_indent */,
D0D02AE315986537008E62BD /* fish_pager */,
D08A328C17B4455100F3A533 /* fish_tests */,
D0A564E6168CFDD800AF6161 /* man_pages */,
D0A084F713B3AC130099B651 /* Makefile */,
@ -1008,7 +948,6 @@
"$(SRCROOT)/doc_src/fish.txt",
"$(SRCROOT)/doc_src/fish_config.txt",
"$(SRCROOT)/doc_src/fish_indent.txt",
"$(SRCROOT)/doc_src/fish_pager.txt",
"$(SRCROOT)/doc_src/fish_prompt.txt",
"$(SRCROOT)/doc_src/fish_right_prompt.txt",
"$(SRCROOT)/doc_src/fish_update_completions.txt",
@ -1081,7 +1020,6 @@
"$(BUILT_PRODUCTS_DIR)/man/man1/fish.1",
"$(BUILT_PRODUCTS_DIR)/man/man1/fish_config.1",
"$(BUILT_PRODUCTS_DIR)/man/man1/fish_indent.1",
"$(BUILT_PRODUCTS_DIR)/man/man1/fish_pager.1",
"$(BUILT_PRODUCTS_DIR)/man/man1/fish_prompt.1",
"$(BUILT_PRODUCTS_DIR)/man/man1/fish_right_prompt.1",
"$(BUILT_PRODUCTS_DIR)/man/man1/fish_update_completions.1",
@ -1125,7 +1063,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "cd \"${SRCROOT}\" ;\n# Run build_documentation.sh\n# Do this in a subshell so that we keep going even if it calls exit\n( . \"./build_tools/build_documentation.sh\" \"./Doxyfile.help\" \"./doc_src\" \"$BUILT_PRODUCTS_DIR\" )\n\n# Copy certain files into man1, destined for share/man/man1 (instead of share/fish/man/man1)\n# These copies will fail of the documentation did not build; that's OK\n# We want to create the directory even if the documentation did not build, so that the Xcode build can still succeed\nmanpathdir=\"${BUILT_PRODUCTS_DIR}/pages_for_manpath/man1\"\necho \"Copying pages destined for manpath into $manpathdir\"\nrm -Rf \"$manpathdir\"\nmkdir -p \"$manpathdir\"\nfor manpage in fish.1 set_color.1 fish_pager.1 fishd.1 fish_indent.1; do\n manpagepath=\"${BUILT_PRODUCTS_DIR}/man/man1/${manpage}\"\n test -f \"$manpagepath\" && cp \"$manpagepath\" \"${BUILT_PRODUCTS_DIR}/pages_for_manpath/man1/\"\ndone\n\n# Always succeed\ntrue\n";
shellScript = "cd \"${SRCROOT}\" ;\n# Run build_documentation.sh\n# Do this in a subshell so that we keep going even if it calls exit\n( . \"./build_tools/build_documentation.sh\" \"./Doxyfile.help\" \"./doc_src\" \"$BUILT_PRODUCTS_DIR\" )\n\n# Copy certain files into man1, destined for share/man/man1 (instead of share/fish/man/man1)\n# These copies will fail of the documentation did not build; that's OK\n# We want to create the directory even if the documentation did not build, so that the Xcode build can still succeed\nmanpathdir=\"${BUILT_PRODUCTS_DIR}/pages_for_manpath/man1\"\necho \"Copying pages destined for manpath into $manpathdir\"\nrm -Rf \"$manpathdir\"\nmkdir -p \"$manpathdir\"\nfor manpage in fish.1 set_color.1 fishd.1 fish_indent.1; do\n manpagepath=\"${BUILT_PRODUCTS_DIR}/man/man1/${manpage}\"\n test -f \"$manpagepath\" && cp \"$manpagepath\" \"${BUILT_PRODUCTS_DIR}/pages_for_manpath/man1/\"\ndone\n\n# Always succeed\ntrue\n";
};
/* End PBXShellScriptBuildPhase section */
@ -1201,23 +1139,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
D0D02AE015986537008E62BD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D0D1CD6C15B7451900F03988 /* fish_pager.cpp in Sources */,
D0D1CD6D15B7452100F03988 /* output.cpp in Sources */,
D0D1CD6E15B7452600F03988 /* wutil.cpp in Sources */,
D0D1CD6F15B7452D00F03988 /* input_common.cpp in Sources */,
D0D1CD7015B7453300F03988 /* env_universal.cpp in Sources */,
D0D1CD7115B7453700F03988 /* env_universal_common.cpp in Sources */,
D0D1CD7315B7455200F03988 /* color.cpp in Sources */,
D0D1CD7515B7458B00F03988 /* common.cpp in Sources */,
D0D1CD7215B7454A00F03988 /* print_help.cpp in Sources */,
D0D1CD7415B7456000F03988 /* iothread.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
D0D26938159835CA005D9B9C /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -1292,11 +1213,6 @@
target = D0D02ABB15985EF9008E62BD /* fishd */;
targetProxy = D07D265A15E33B86009E43F6 /* PBXContainerItemProxy */;
};
D07D265B15E33B86009E43F6 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D0D02AE315986537008E62BD /* fish_pager */;
targetProxy = D07D265C15E33B86009E43F6 /* PBXContainerItemProxy */;
};
D07D265D15E33B86009E43F6 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D0D02ACF1598642A008E62BD /* fish_indent */;
@ -1327,11 +1243,6 @@
target = D0D02ACF1598642A008E62BD /* fish_indent */;
targetProxy = D0F01A1615AA36300034B3B1 /* PBXContainerItemProxy */;
};
D0F01A1915AA36310034B3B1 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = D0D02AE315986537008E62BD /* fish_pager */;
targetProxy = D0F01A1815AA36310034B3B1 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
@ -1435,18 +1346,6 @@
};
name = "Release_C++11";
};
D007FDE117136EAA00A52BE6 /* Release_C++11 */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = "Release_C++11";
};
D007FDE217136EAA00A52BE6 /* Release_C++11 */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1743,34 +1642,6 @@
};
name = Release;
};
D0D02AE815986537008E62BD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_UNINITIALIZED_AUTOS = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
D0D02AE915986537008E62BD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
D0D26944159835CA005D9B9C /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1898,16 +1769,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D0D02AE715986537008E62BD /* Build configuration list for PBXNativeTarget "fish_pager" */ = {
isa = XCConfigurationList;
buildConfigurations = (
D0D02AE815986537008E62BD /* Debug */,
D0D02AE915986537008E62BD /* Release */,
D007FDE117136EAA00A52BE6 /* Release_C++11 */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
D0D26943159835CA005D9B9C /* Build configuration list for PBXNativeTarget "fish_shell" */ = {
isa = XCConfigurationList;
buildConfigurations = (

File diff suppressed because it is too large Load diff

View file

@ -638,7 +638,7 @@ static int signal_main(test_cancellation_info_t *info)
static void test_1_cancellation(const wchar_t *src)
{
shared_ptr<io_buffer_t> out_buff(io_buffer_t::create(false, STDOUT_FILENO));
shared_ptr<io_buffer_t> out_buff(io_buffer_t::create(STDOUT_FILENO));
const io_chain_t io_chain(out_buff);
test_cancellation_info_t ctx = {pthread_self(), 0.25 /* seconds */ };
iothread_perform(signal_main, (void (*)(test_cancellation_info_t *, int))NULL, &ctx);

9
io.cpp
View file

@ -123,14 +123,11 @@ void io_buffer_t::read()
}
io_buffer_t *io_buffer_t::create(bool is_input, int fd)
io_buffer_t *io_buffer_t::create(int fd)
{
bool success = true;
if (fd == -1)
{
fd = is_input ? STDIN_FILENO : STDOUT_FILENO;
}
io_buffer_t *buffer_redirect = new io_buffer_t(fd, is_input);
assert(fd >= 0);
io_buffer_t *buffer_redirect = new io_buffer_t(fd);
if (exec_pipe(buffer_redirect->pipe_fd) == -1)
{

16
io.h
View file

@ -131,8 +131,8 @@ private:
/** buffer to save output in */
std::vector<char> out_buffer;
io_buffer_t(int f, bool i):
io_pipe_t(IO_BUFFER, f, i),
io_buffer_t(int f):
io_pipe_t(IO_BUFFER, f, false /* not input */),
out_buffer()
{
}
@ -172,16 +172,12 @@ public:
/**
Create a IO_BUFFER type io redirection, complete with a pipe and a
vector<char> for output. The default file descriptor used is 1 for
output buffering and 0 for input buffering.
vector<char> for output. The default file descriptor used is STDOUT_FILENO
for buffering
\param is_input set this parameter to zero if the buffer should be
used to buffer the output of a command, or non-zero to buffer the
input to a command.
\param fd when -1, determined from is_input.
\param fd the fd that will be mapped in the child process, typically STDOUT_FILENO
*/
static io_buffer_t *create(bool is_input, int fd = -1);
static io_buffer_t *create(int fd);
};
class io_chain_t : public std::vector<shared_ptr<io_data_t> >

View file

@ -11,7 +11,7 @@ typedef pager_t::comp_t comp_t;
typedef std::vector<completion_t> completion_list_t;
typedef std::vector<comp_t> comp_info_list_t;
/** The minimum width (in characters) the terminal may have for fish_pager to not refuse showing the completions */
/** The minimum width (in characters) the terminal must to show completions at all */
#define PAGER_MIN_WIDTH 16
/** The maximum number of columns of completion to attempt to fit onto the screen */

View file

@ -178,6 +178,31 @@ typedef unsigned int parser_test_error_bits_t;
/** Error message for Posix-style assignment: foo=bar */
#define COMMAND_ASSIGN_ERR_MSG _( L"Unknown command '%ls'. Did you mean 'set %ls %ls'? See the help section on the set command by typing 'help set'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on $?
*/
#define COMPLETE_YOU_WANT_STATUS _( L"$? is not a valid variable in fish. If you want the exit status of the last command, try $status.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean %ls{$%ls}%ls? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
/**
While block description
*/

View file

@ -207,46 +207,44 @@ wcstring token_type_description(parse_token_type_t type)
return format_string(L"Unknown token type %ld", static_cast<long>(type));
}
#define LONGIFY(x) L ## x
#define KEYWORD_MAP(x) { parse_keyword_ ## x , LONGIFY(#x) }
static const struct
{
const parse_keyword_t keyword;
const wchar_t * const name;
}
keyword_map[] =
{
KEYWORD_MAP(none),
KEYWORD_MAP(if),
KEYWORD_MAP(else),
KEYWORD_MAP(for),
KEYWORD_MAP(in),
KEYWORD_MAP(while),
KEYWORD_MAP(begin),
KEYWORD_MAP(function),
KEYWORD_MAP(switch),
KEYWORD_MAP(case),
KEYWORD_MAP(end),
KEYWORD_MAP(and),
KEYWORD_MAP(or),
KEYWORD_MAP(not),
KEYWORD_MAP(command),
KEYWORD_MAP(builtin),
KEYWORD_MAP(exec)
};
wcstring keyword_description(parse_keyword_t k)
{
switch (k)
if (k >= 0 && k <= LAST_KEYWORD)
{
case parse_keyword_none:
return L"none";
case parse_keyword_if:
return L"if";
case parse_keyword_else:
return L"else";
case parse_keyword_for:
return L"for";
case parse_keyword_in:
return L"in";
case parse_keyword_while:
return L"while";
case parse_keyword_begin:
return L"begin";
case parse_keyword_function:
return L"function";
case parse_keyword_switch:
return L"switch";
case parse_keyword_case:
return L"case";
case parse_keyword_end:
return L"end";
case parse_keyword_and:
return L"and";
case parse_keyword_or:
return L"or";
case parse_keyword_not:
return L"not";
case parse_keyword_command:
return L"command";
case parse_keyword_builtin:
return L"builtin";
case parse_keyword_exec:
return L"exec";
return keyword_map[k].name;
}
else
{
return format_string(L"Unknown keyword type %ld", static_cast<long>(k));
}
return format_string(L"Unknown keyword type %ld", static_cast<long>(k));
}
static wcstring token_type_user_presentable_description(parse_token_type_t type, parse_keyword_t keyword)
@ -1036,36 +1034,11 @@ static parse_keyword_t keyword_for_token(token_type tok, const wchar_t *tok_txt)
parse_keyword_t result = parse_keyword_none;
if (tok == TOK_STRING)
{
const struct
for (size_t i=0; i < sizeof keyword_map / sizeof *keyword_map; i++)
{
const wchar_t *txt;
parse_keyword_t keyword;
} keywords[] =
{
{L"if", parse_keyword_if},
{L"else", parse_keyword_else},
{L"for", parse_keyword_for},
{L"in", parse_keyword_in},
{L"while", parse_keyword_while},
{L"begin", parse_keyword_begin},
{L"function", parse_keyword_function},
{L"switch", parse_keyword_switch},
{L"case", parse_keyword_case},
{L"end", parse_keyword_end},
{L"and", parse_keyword_and},
{L"or", parse_keyword_or},
{L"not", parse_keyword_not},
{L"command", parse_keyword_command},
{L"builtin", parse_keyword_builtin},
{L"exec", parse_keyword_exec}
};
for (size_t i=0; i < sizeof keywords / sizeof *keywords; i++)
{
if (! wcscmp(keywords[i].txt, tok_txt))
if (! wcscmp(keyword_map[i].name, tok_txt))
{
result = keywords[i].keyword;
result = keyword_map[i].keyword;
break;
}
}

View file

@ -1001,11 +1001,205 @@ static bool first_argument_is_help(const parse_node_tree_t &node_tree, const par
return is_help;
}
void parse_util_expand_variable_error(const parse_node_t &node, const wcstring &token, size_t token_pos, size_t error_pos, parse_error_list_t *out_errors)
{
size_t stop_pos = token_pos+1;
switch (token[stop_pos])
{
case BRACKET_BEGIN:
{
wchar_t *cpy = wcsdup(token.c_str());
*(cpy+token_pos)=0;
wchar_t *name = &cpy[stop_pos+1];
wchar_t *end = wcschr(name, BRACKET_END);
wchar_t *post = NULL;
int is_var=0;
if (end)
{
post = end+1;
*end = 0;
if (!wcsvarname(name))
{
is_var = 1;
}
}
if (is_var)
{
append_syntax_error(out_errors,
node,
COMPLETE_VAR_BRACKET_DESC,
cpy,
name,
post);
}
else
{
append_syntax_error(out_errors,
node,
COMPLETE_VAR_BRACKET_DESC,
L"",
L"VARIABLE",
L"");
}
free(cpy);
break;
}
case INTERNAL_SEPARATOR:
{
append_syntax_error(out_errors,
node,
COMPLETE_VAR_PARAN_DESC);
break;
}
case 0:
{
append_syntax_error(out_errors,
node,
COMPLETE_VAR_NULL_DESC);
break;
}
default:
{
wchar_t token_stop_char = token[stop_pos];
// Unescape (see http://github.com/fish-shell/fish-shell/issues/50)
if (token_stop_char == ANY_CHAR)
token_stop_char = L'?';
else if (token_stop_char == ANY_STRING || token_stop_char == ANY_STRING_RECURSIVE)
token_stop_char = L'*';
append_syntax_error(out_errors,
node,
(token_stop_char == L'?' ? COMPLETE_YOU_WANT_STATUS : COMPLETE_VAR_DESC),
token_stop_char);
break;
}
}
}
/**
Test if this argument contains any errors. Detected errors include
syntax errors in command substitutions, improperly escaped
characters and improper use of the variable expansion operator.
*/
parser_test_error_bits_t parse_util_detect_errors_in_argument(const parse_node_t &node, const wcstring &arg_src, parse_error_list_t *out_errors)
{
int err=0;
wchar_t *paran_begin, *paran_end;
wchar_t *arg_cpy;
int do_loop = 1;
arg_cpy = wcsdup(arg_src.c_str());
while (do_loop)
{
switch (parse_util_locate_cmdsubst(arg_cpy,
&paran_begin,
&paran_end,
false))
{
case -1:
{
err=1;
if (out_errors)
{
append_syntax_error(out_errors, node, L"Mismatched parenthesis");
}
free(arg_cpy);
return err;
}
case 0:
{
do_loop = 0;
break;
}
case 1:
{
const wcstring subst(paran_begin + 1, paran_end);
wcstring tmp;
tmp.append(arg_cpy, paran_begin - arg_cpy);
tmp.push_back(INTERNAL_SEPARATOR);
tmp.append(paran_end+1);
parse_error_list_t errors;
err |= parse_util_detect_errors(subst, &errors);
if (out_errors != NULL)
{
/* Todo: have to tweak the offsets of the errors in the command substitution */
out_errors->insert(out_errors->end(), errors.begin(), errors.end());
}
free(arg_cpy);
arg_cpy = wcsdup(tmp.c_str());
break;
}
}
}
wcstring unesc;
if (! unescape_string(arg_cpy, &unesc, UNESCAPE_SPECIAL))
{
if (out_errors)
{
append_syntax_error(out_errors, node, L"Invalid token '%ls'", arg_cpy);
}
return 1;
}
else
{
/* Check for invalid variable expansions */
const size_t unesc_size = unesc.size();
for (size_t idx = 0; idx < unesc_size; idx++)
{
switch (unesc.at(idx))
{
case VARIABLE_EXPAND:
case VARIABLE_EXPAND_SINGLE:
{
wchar_t next_char = (idx + 1 < unesc_size ? unesc.at(idx + 1) : L'\0');
if (next_char != VARIABLE_EXPAND &&
next_char != VARIABLE_EXPAND_SINGLE &&
! wcsvarchr(next_char))
{
err=1;
if (out_errors)
{
parse_util_expand_variable_error(node, unesc, idx, node.source_start, out_errors);
}
}
break;
}
}
}
}
free(arg_cpy);
return err;
}
parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, parse_error_list_t *out_errors)
{
parse_node_tree_t node_tree;
parse_error_list_t parse_errors;
parser_test_error_bits_t res = 0;
// Whether we encountered a parse error
bool errored = false;
@ -1065,6 +1259,11 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, pars
errored = append_syntax_error(&parse_errors, node, EXEC_ERR_MSG, is_and ? L"and" : L"or");
}
}
else if (node.type == symbol_argument)
{
const wcstring arg_src = node.get_source(buff_src);
res |= parse_util_detect_errors_in_argument(node, arg_src, &parse_errors);
}
else if (node.type == symbol_plain_statement)
{
// In a few places below, we want to know if we are in a pipeline
@ -1159,8 +1358,6 @@ parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, pars
}
}
parser_test_error_bits_t res = 0;
if (errored)
res |= PARSER_TEST_ERROR;

View file

@ -171,4 +171,6 @@ std::vector<int> parse_util_compute_indents(const wcstring &src);
parser_test_error_bits_t parse_util_detect_errors(const wcstring &buff_src, parse_error_list_t *out_errors = NULL);
parser_test_error_bits_t parse_util_detect_errors_in_argument(const parse_node_t &node, const wcstring &arg_src, parse_error_list_t *out_errors = NULL);
#endif

View file

@ -1392,17 +1392,18 @@ void parser_t::get_backtrace(const wcstring &src, const parse_error_list_t &erro
if (filename)
{
prefix = format_string(_(L"%ls (line %lu): "), user_presentable_path(filename).c_str(), which_line);
//append_format(*output, _(L"%ls (line %lu):\n"), user_presentable_path(filename).c_str(), which_line);
}
else
{
prefix = L"fish: ";
//output->append(L"fish: ");
}
output->append(err.describe_with_prefix(src, prefix, skip_caret));
output->push_back(L'\n');
const wcstring description = err.describe_with_prefix(src, prefix, skip_caret);
if (! description.empty())
{
output->append(description);
output->push_back(L'\n');
}
this->stack_trace(0, *output);
}
}
@ -1488,16 +1489,3 @@ bool parser_use_ast(void)
return from_string<bool>(var);
}
}
bool pager_use_inline(void)
{
env_var_t var = env_get_string(L"fish_new_pager");
if (var.missing_or_empty())
{
return 1;
}
else
{
return from_string<bool>(var);
}
}

View file

@ -510,7 +510,6 @@ public:
/* Temporary */
bool parser_use_ast(void);
bool pager_use_inline(void);
#endif

17278
po/de.po

File diff suppressed because it is too large Load diff

6866
po/en.po

File diff suppressed because it is too large Load diff

13664
po/fr.po

File diff suppressed because it is too large Load diff

7021
po/sv.po

File diff suppressed because it is too large Load diff

View file

@ -586,15 +586,6 @@ static void reader_repaint()
data->repaint_needed = false;
}
static void reader_repaint_without_autosuggestion()
{
// Swap in an empty autosuggestion, repaint, then swap it out
wcstring saved_autosuggestion;
data->autosuggestion.swap(saved_autosuggestion);
reader_repaint();
data->autosuggestion.swap(saved_autosuggestion);
}
/** Internal helper function for handling killing parts of text. */
static void reader_kill(editable_line_t *el, size_t begin_idx, size_t length, int mode, int newv)
{
@ -1347,144 +1338,6 @@ static void completion_insert(const wchar_t *val, complete_flags_t flags)
data->suppress_autosuggestion = true;
}
/* Return an escaped path to fish_pager */
static wcstring escaped_fish_pager_path(void)
{
wcstring result;
const env_var_t bin_dir = env_get_string(L"__fish_bin_dir");
if (bin_dir.missing_or_empty())
{
/* This isn't good, hope our normal command stuff can find it */
result = L"fish_pager";
}
else
{
result = escape_string(bin_dir + L"/fish_pager", ESCAPE_ALL);
}
return result;
}
/**
Run the fish_pager command to display the completion list. If the
fish_pager outputs any text, it is inserted into the input
backbuffer.
\param prefix the string to display before every completion.
\param is_quoted should be set if the argument is quoted. This will change the display style.
\param comp the list of completions to display
*/
static void run_pager(const wcstring &prefix, int is_quoted, const std::vector<completion_t> &comp)
{
wcstring msg;
wcstring prefix_esc;
char *foo;
shared_ptr<io_buffer_t> in_buff(io_buffer_t::create(true, 3));
shared_ptr<io_buffer_t> out_buff(io_buffer_t::create(false, 4));
// The above may fail e.g. if we have too many open fds
if (in_buff.get() == NULL || out_buff.get() == NULL)
return;
wchar_t *escaped_separator;
if (prefix.empty())
{
prefix_esc = L"\"\"";
}
else
{
prefix_esc = escape_string(prefix, 1);
}
const wcstring pager_path = escaped_fish_pager_path();
const wcstring cmd = format_string(L"%ls -c 3 -r 4 %ls -p %ls",
// L"valgrind --track-fds=yes --log-file=pager.txt --leak-check=full ./%ls %d %ls",
pager_path.c_str(),
is_quoted?L"-q":L"",
prefix_esc.c_str());
escaped_separator = escape(COMPLETE_SEP_STR, 1);
editable_line_t *el = &data->command_line;
for (size_t i=0; i< comp.size(); i++)
{
long base_len=-1;
const completion_t &cmpl = comp.at(i);
wcstring completion_text;
wcstring description_text;
// Note that an empty completion is perfectly sensible here, e.g. tab-completing 'foo' with a file called 'foo' and another called 'foobar'
if ((cmpl.flags & COMPLETE_REPLACES_TOKEN) && match_type_shares_prefix(cmpl.match.type))
{
// Compute base_len if we have not yet
if (base_len == -1)
{
const wchar_t *begin, *buff = el->text.c_str();
parse_util_token_extent(buff, el->position, &begin, 0, 0, 0);
base_len = el->position - (begin-buff);
}
completion_text = escape_string(cmpl.completion.c_str() + base_len, ESCAPE_ALL | ESCAPE_NO_QUOTED);
}
else
{
completion_text = escape_string(cmpl.completion, ESCAPE_ALL | ESCAPE_NO_QUOTED);
}
if (! cmpl.description.empty())
{
description_text = escape_string(cmpl.description, true);
}
/* It's possible (even common) to have an empty completion with no description. An example would be completing 'foo' with extant files 'foo' and 'foobar'. But fish_pager ignores blank lines. So if our completion text is empty, always include a description, even if it's empty.
*/
msg.reserve(msg.size() + completion_text.size() + description_text.size() + 2);
msg.append(completion_text);
if (! description_text.empty() || completion_text.empty())
{
msg.append(escaped_separator);
msg.append(description_text);
}
msg.push_back(L'\n');
}
free(escaped_separator);
foo = wcs2str(msg.c_str());
in_buff->out_buffer_append(foo, strlen(foo));
free(foo);
term_donate();
parser_t &parser = parser_t::principal_parser();
io_chain_t io_chain;
io_chain.push_back(out_buff);
io_chain.push_back(in_buff);
parser.eval(cmd, io_chain, TOP);
term_steal();
out_buff->read();
const char zero = 0;
out_buff->out_buffer_append(&zero, 1);
const char *out_data = out_buff->out_buffer_ptr();
if (out_data)
{
const wcstring str = str2wcstring(out_data);
size_t idx = str.size();
while (idx--)
{
input_unreadch(str.at(idx));
}
}
}
struct autosuggestion_context_t
{
wcstring search_string;
@ -1988,32 +1841,16 @@ static bool handle_completions(const std::vector<completion_t> &comp, bool conti
wchar_t quote;
parse_util_get_parameter_info(el->text, el->position, &quote, NULL, NULL);
bool is_quoted = (quote != L'\0');
if (pager_use_inline())
{
/* Inline pager */
data->pager.set_prefix(prefix);
data->pager.set_completions(surviving_completions);
/* Invalidate our rendering */
data->current_page_rendering = page_rendering_t();
/* Modify the command line to reflect the new pager */
data->pager_selection_changed();
}
else
{
/* Classic pager. Clear the autosuggestion from the old commandline before abandoning it (see #561) */
if (! data->autosuggestion.empty())
reader_repaint_without_autosuggestion();
write_loop(1, "\n", 1);
run_pager(prefix, is_quoted, surviving_completions);
s_reset(&data->screen, screen_reset_abandon_line);
}
/* Update the pager data */
data->pager.set_prefix(prefix);
data->pager.set_completions(surviving_completions);
/* Invalidate our rendering */
data->current_page_rendering = page_rendering_t();
/* Modify the command line to reflect the new pager */
data->pager_selection_changed();
reader_repaint_needed();

View file

@ -1,4 +1,3 @@
#
# This is a neat function, stolen from zsh. It allows you to edit the
# value of a variable interactively.
@ -39,11 +38,11 @@ function vared --description "Edit variable value"
end
else
printf (_ '%s: %s is an array variable. Use %svared%s %s[n] to edit the n:th element of %s\n') vared $argv (set_color $fish_color_command) (set_color $fish_color_normal) $argv $argv
printf (_ '%s: %s is an array variable. Use %svared%s %s[n] to edit the n:th element of %s\n') vared $argv (set_color $fish_color_command; echo) (set_color $fish_color_normal; echo) $argv $argv
end
end
else
printf (_ '%s: Expected exactly one argument, got %s.\n\nSynopsis:\n\t%svared%s VARIABLE\n') vared (count $argv) (set_color $fish_color_command) (set_color $fish_color_normal)
printf (_ '%s: Expected exactly one argument, got %s.\n\nSynopsis:\n\t%svared%s VARIABLE\n') vared (count $argv) (set_color $fish_color_command; echo) (set_color $fish_color_normal; echo)
end
end