mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-09 17:01:16 -03:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02a3288db7 | ||
|
|
b069489792 | ||
|
|
b37eeb92ef | ||
|
|
b6630b5087 | ||
|
|
3a69fc997c | ||
|
|
c216e36a72 | ||
|
|
00778832f1 | ||
|
|
cdbd233e62 | ||
|
|
9ce93164bb | ||
|
|
20b269130c | ||
|
|
891c2fc379 | ||
|
|
00be44a69a | ||
|
|
b8ea709c1e | ||
|
|
7bdcfacee4 | ||
|
|
61706b4490 | ||
|
|
443ddb509e | ||
|
|
e6774cc944 | ||
|
|
78cd8fa089 | ||
|
|
9229041385 | ||
|
|
e6bd3dbc40 | ||
|
|
a91bf6d88a | ||
|
|
fa75fc3901 | ||
|
|
e4a95cb989 | ||
|
|
9cf4a2a0b3 | ||
|
|
0ff374a4a0 | ||
|
|
0817962300 | ||
|
|
8b69c5416d | ||
|
|
1071fedaee | ||
|
|
ab207b64a3 | ||
|
|
418e26c0ac | ||
|
|
de3a28874e | ||
|
|
9dd842ea96 | ||
|
|
5d069de71d | ||
|
|
16333b0c69 | ||
|
|
e4fa0e1000 | ||
|
|
3e52bd0132 | ||
|
|
211663a549 | ||
|
|
659b99ed1a | ||
|
|
86d7e8bb8e | ||
|
|
8bf0a14bd5 | ||
|
|
9c32709fe1 | ||
|
|
00bdd2cb48 | ||
|
|
0a8284c981 | ||
|
|
ddbb50acd7 | ||
|
|
5262f3ce99 | ||
|
|
28dd48a76a | ||
|
|
b1c61bcf1f | ||
|
|
bb591a69c9 | ||
|
|
1d69e70b7a | ||
|
|
2cac04850b | ||
|
|
2619f1752d | ||
|
|
33e2c81748 | ||
|
|
f05da41159 | ||
|
|
780ecc46fc | ||
|
|
9b98df8310 | ||
|
|
5a8205ac2b | ||
|
|
2490da31ce | ||
|
|
092bb90569 | ||
|
|
39ca027706 | ||
|
|
22433f2717 | ||
|
|
f6e194447d | ||
|
|
e2ed5d0977 |
22
Makefile.in
22
Makefile.in
@@ -79,13 +79,13 @@ MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
|
||||
|
||||
BUILTIN_DOC_SRC := doc_src/source.txt doc_src/and.txt \
|
||||
doc_src/begin.txt doc_src/bg.txt doc_src/bind.txt \
|
||||
doc_src/break.txt doc_src/builtin.txt doc_src/case.txt \
|
||||
doc_src/cd.txt doc_src/command.txt doc_src/commandline.txt \
|
||||
doc_src/complete.txt doc_src/continue.txt doc_src/else.txt \
|
||||
doc_src/end.txt doc_src/eval.txt doc_src/exec.txt doc_src/exit.txt \
|
||||
doc_src/fg.txt doc_src/for.txt doc_src/function.txt \
|
||||
doc_src/functions.txt doc_src/if.txt doc_src/jobs.txt \
|
||||
doc_src/not.txt doc_src/or.txt doc_src/random.txt \
|
||||
doc_src/block.txt doc_src/break.txt doc_src/builtin.txt \
|
||||
doc_src/case.txt doc_src/cd.txt doc_src/command.txt \
|
||||
doc_src/commandline.txt doc_src/complete.txt doc_src/continue.txt \
|
||||
doc_src/else.txt doc_src/end.txt doc_src/eval.txt doc_src/exec.txt \
|
||||
doc_src/exit.txt doc_src/fg.txt doc_src/for.txt \
|
||||
doc_src/function.txt doc_src/functions.txt doc_src/if.txt \
|
||||
doc_src/jobs.txt doc_src/not.txt doc_src/or.txt doc_src/random.txt \
|
||||
doc_src/return.txt doc_src/read.txt doc_src/set.txt \
|
||||
doc_src/status.txt doc_src/switch.txt doc_src/ulimit.txt \
|
||||
doc_src/while.txt
|
||||
@@ -105,8 +105,8 @@ CMD_DOC_SRC := doc_src/count.txt doc_src/dirh.txt doc_src/dirs.txt \
|
||||
doc_src/fishd.txt doc_src/help.txt doc_src/mimedb.txt \
|
||||
doc_src/nextd.txt doc_src/open.txt doc_src/popd.txt \
|
||||
doc_src/prevd.txt doc_src/psub.txt doc_src/pushd.txt \
|
||||
doc_src/set_color.txt doc_src/tokenize.txt doc_src/type.txt \
|
||||
doc_src/umask.txt doc_src/vared.txt
|
||||
doc_src/set_color.txt doc_src/tokenize.txt doc_src/trap.txt \
|
||||
doc_src/type.txt doc_src/umask.txt doc_src/vared.txt
|
||||
|
||||
#
|
||||
# Files generated by running doxygen on the files in $(CMD_DOC_SRC)
|
||||
@@ -283,7 +283,9 @@ install: all
|
||||
$(INSTALL) -m 644 init/fish_inputrc $(DESTDIR)$(sysconfdir)$(fishinputfile);
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
|
||||
for i in user_doc/html/* ChangeLog; do \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(docdir); \
|
||||
if test -f $$i; then \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(docdir); \
|
||||
fi; \
|
||||
done;
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(mandir)/man1
|
||||
for i in $(MANUALS); do \
|
||||
|
||||
@@ -28,10 +28,10 @@ Functions used for implementing the commandline builtin.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
STRING_MODE=1, // Operate on entire buffer
|
||||
JOB_MODE, // Operate on job under cursor
|
||||
PROCESS_MODE, // Operate on process under cursor
|
||||
TOKEN_MODE // Operate on token under cursor
|
||||
STRING_MODE=1, /**< Operate on entire buffer */
|
||||
JOB_MODE, /**< Operate on job under cursor */
|
||||
PROCESS_MODE, /**< Operate on process under cursor */
|
||||
TOKEN_MODE /**< Operate on token under cursor */
|
||||
}
|
||||
;
|
||||
|
||||
@@ -40,9 +40,9 @@ enum
|
||||
*/
|
||||
enum
|
||||
{
|
||||
REPLACE_MODE=1, // Replace current text
|
||||
INSERT_MODE, // Insert at cursor position
|
||||
APPEND_MODE // Insert at end of current token/command/buffer
|
||||
REPLACE_MODE=1, /**< Replace current text */
|
||||
INSERT_MODE, /**< Insert at cursor position */
|
||||
APPEND_MODE /**< Insert at end of current token/command/buffer */
|
||||
}
|
||||
;
|
||||
|
||||
@@ -66,10 +66,6 @@ static void replace_part( wchar_t *begin,
|
||||
|
||||
sb_init( &out );
|
||||
|
||||
// wchar_t *tmp = wcsndup( begin, end-begin );
|
||||
|
||||
// fwprintf( stderr, L"Commandline '%ls', current command '%ls'\n", reader_get_buffer(), tmp );
|
||||
|
||||
sb_append_substring( &out, buff, begin-buff );
|
||||
|
||||
switch( append_mode)
|
||||
@@ -253,7 +249,7 @@ int builtin_commandline( wchar_t **argv )
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"aijpctwfo",
|
||||
L"aijpctwfor",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
@@ -282,7 +278,11 @@ int builtin_commandline( wchar_t **argv )
|
||||
case L'i':
|
||||
append_mode = INSERT_MODE;
|
||||
break;
|
||||
|
||||
|
||||
case L'r':
|
||||
append_mode = REPLACE_MODE;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
cut_at_cursor=1;
|
||||
break;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <wchar.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "util.h"
|
||||
|
||||
@@ -290,7 +290,7 @@ int builtin_set( wchar_t **argv )
|
||||
}
|
||||
;
|
||||
|
||||
wchar_t short_options[] = L"xglenuUq";
|
||||
wchar_t short_options[] = L"+xglenuUq";
|
||||
|
||||
int argc = builtin_count_args(argv);
|
||||
|
||||
|
||||
33
common.c
33
common.c
@@ -393,7 +393,7 @@ wchar_t **strv2wcsv( const char **in )
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef HAVE_WCSNDUP
|
||||
wchar_t *wcsndup( const wchar_t *in, int c )
|
||||
{
|
||||
c3++;
|
||||
@@ -407,6 +407,7 @@ wchar_t *wcsndup( const wchar_t *in, int c )
|
||||
res[c] = L'\0';
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
long convert_digit( wchar_t d, int base )
|
||||
{
|
||||
@@ -574,6 +575,7 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
/* count does not include NUL */
|
||||
}
|
||||
|
||||
#ifndef HAVE_WCSDUP
|
||||
wchar_t *wcsdup( const wchar_t *in )
|
||||
{
|
||||
size_t len=wcslen(in);
|
||||
@@ -587,10 +589,20 @@ wchar_t *wcsdup( const wchar_t *in )
|
||||
return out;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Fallback implementation if missing from libc
|
||||
*/
|
||||
#ifndef HAVE_WCSLEN
|
||||
size_t wcslen(const wchar_t *in)
|
||||
{
|
||||
const wchar_t *end=in;
|
||||
while( *end )
|
||||
end++;
|
||||
return end-in;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_WCSCASECMP
|
||||
int wcscasecmp( const wchar_t *a, const wchar_t *b )
|
||||
{
|
||||
if( *a == 0 )
|
||||
@@ -607,10 +619,10 @@ int wcscasecmp( const wchar_t *a, const wchar_t *b )
|
||||
else
|
||||
return wcscasecmp( a+1,b+1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
Fallback implementation if missing from libc
|
||||
*/
|
||||
|
||||
#ifndef HAVE_WCSNCASECMP
|
||||
int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count )
|
||||
{
|
||||
if( count == 0 )
|
||||
@@ -630,6 +642,7 @@ int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count )
|
||||
else
|
||||
return wcsncasecmp( a+1,b+1, count-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
int wcsvarname( wchar_t *str )
|
||||
{
|
||||
@@ -920,9 +933,10 @@ wchar_t *escape( const wchar_t *in,
|
||||
case L'^':
|
||||
case L'<':
|
||||
case L'>':
|
||||
case L'@':
|
||||
case L'(':
|
||||
case L')':
|
||||
case L'[':
|
||||
case L']':
|
||||
case L'{':
|
||||
case L'}':
|
||||
case L'?':
|
||||
@@ -931,8 +945,9 @@ wchar_t *escape( const wchar_t *in,
|
||||
case L';':
|
||||
case L':':
|
||||
case L'\'':
|
||||
case L'\"':
|
||||
case L'"':
|
||||
case L'%':
|
||||
case L'~':
|
||||
if( escape_all )
|
||||
*pos++ = L'\\';
|
||||
*pos++ = *in;
|
||||
|
||||
14
common.h
14
common.h
@@ -134,6 +134,7 @@ wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b );
|
||||
*/
|
||||
wchar_t *wcsdupcat2( const wchar_t *a, ... );
|
||||
|
||||
#ifndef HAVE_WCSNDUP
|
||||
/**
|
||||
Returns a newly allocated wide character string wich is a copy of
|
||||
the string in, but of length c or shorter. The returned string is
|
||||
@@ -141,6 +142,7 @@ wchar_t *wcsdupcat2( const wchar_t *a, ... );
|
||||
length.
|
||||
*/
|
||||
wchar_t *wcsndup( const wchar_t *in, int c );
|
||||
#endif
|
||||
|
||||
/**
|
||||
Converts from wide char to digit in the specified base. If d is not
|
||||
@@ -183,12 +185,19 @@ size_t wcslcat( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
*/
|
||||
size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
#ifndef HAVE_WCSDUP
|
||||
/**
|
||||
Create a dublicate string. Wide string version of strdup. Will
|
||||
Create a duplicate string. Wide string version of strdup. Will
|
||||
automatically exit if out of memory.
|
||||
*/
|
||||
wchar_t *wcsdup(const wchar_t *in);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_WCSLEN
|
||||
size_t wcslen(const wchar_t *in);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_WCSCASECMP
|
||||
/**
|
||||
Case insensitive string compare function. Wide string version of
|
||||
strcasecmp.
|
||||
@@ -201,7 +210,9 @@ wchar_t *wcsdup(const wchar_t *in);
|
||||
a user-supplied string should be considered a bug.
|
||||
*/
|
||||
int wcscasecmp( const wchar_t *a, const wchar_t *b );
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_WCSNCASECMP
|
||||
/**
|
||||
Case insensitive string compare function. Wide string version of
|
||||
strncasecmp.
|
||||
@@ -214,6 +225,7 @@ int wcscasecmp( const wchar_t *a, const wchar_t *b );
|
||||
a user-supplied string should be considered a bug.
|
||||
*/
|
||||
int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count );
|
||||
#endif
|
||||
|
||||
/**
|
||||
Test if the given string is a valid variable name
|
||||
|
||||
@@ -2017,7 +2017,7 @@ void complete( const wchar_t *cmd,
|
||||
|
||||
tok_init( &tok, buff, TOK_ACCEPT_UNFINISHED );
|
||||
|
||||
while( !end_loop )
|
||||
while( tok_has_next( &tok) && !end_loop )
|
||||
{
|
||||
switch( tok_last_type( &tok ) )
|
||||
{
|
||||
@@ -2063,7 +2063,8 @@ void complete( const wchar_t *cmd,
|
||||
reader_current_token_extent( &begin, &end, &prev_begin, &prev_end );
|
||||
|
||||
current_token = wcsndup( begin, reader_get_cursor_pos()-(begin-reader_get_buffer()) );
|
||||
prev_token = wcsndup( prev_begin, prev_end - prev_begin );
|
||||
|
||||
prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L"");
|
||||
|
||||
// fwprintf( stderr, L"on_command: %d, %ls %ls\n", on_command, current_compmand, current_token );
|
||||
|
||||
|
||||
13
configure.ac
13
configure.ac
@@ -1,5 +1,5 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(fish,1.18.0,fish-users@lists.sf.net)
|
||||
AC_INIT(fish,1.19.0,fish-users@lists.sf.net)
|
||||
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
@@ -18,6 +18,15 @@ AC_PROG_INSTALL
|
||||
#AC_ISC_POSIX
|
||||
#AC_PROG_MAKE_SET
|
||||
|
||||
AC_CHECK_PROG( has_doxygen, [doxygen], "true")
|
||||
|
||||
if ! test $has_doxygen = "true"; then
|
||||
echo Could not find the Doxygen program in your path.
|
||||
echo This program is needed to build fish.
|
||||
echo Please install it and try again.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Optionally drop xsel
|
||||
AC_ARG_WITH( xsel,
|
||||
AC_HELP_STRING([--without-xsel],
|
||||
@@ -120,6 +129,8 @@ fi
|
||||
AC_CHECK_LIB(socket, connect)
|
||||
AC_CHECK_LIB(rt, nanosleep)
|
||||
|
||||
AC_CHECK_FUNCS(wcsdup wcsndup wcslen wcscasecmp wcsncasecmp)
|
||||
|
||||
# Check if we have ncurses, and use it rather than curses if possible.
|
||||
AC_CHECK_HEADERS([ncurses.h],[AC_SUBST(CURSESLIB,[ncurses]) AC_DEFINE(HAVE_NCURSES_H)],[AC_SUBST(CURSESLIB,[curses])])
|
||||
|
||||
|
||||
19
doc_src/block.txt
Normal file
19
doc_src/block.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
\section block block - Temporarily block delivery of events
|
||||
|
||||
\subsection block-synopsis Synopsis
|
||||
<tt>block [OPTIONS...]</tt>
|
||||
|
||||
\subsection block-description Description
|
||||
|
||||
- <tt>-l</tt> or <tt>--local</tt> Release the block at the end of the currently innermost block scope
|
||||
- <tt>-g</tt> or <tt>--global</tt> Never automatically release the lock
|
||||
- <tt>-e</tt> or <tt>--erase</tt> Release global block
|
||||
|
||||
\subsection block-example Example
|
||||
|
||||
<pre>block -g
|
||||
\#Do something that should not be interrupted
|
||||
block -e
|
||||
</pre>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
\section introduction The friendly interactive shell
|
||||
|
||||
This is the documentation for \c fish, the friendly interactive
|
||||
shell. \c fish is a user friendly commandline shell shell intended
|
||||
shell. \c fish is a user friendly commandline shell intended
|
||||
mostly for interactive use. A shell is a program used to execute other
|
||||
programs. For the latest information on \c fish, please visit the <a
|
||||
href="http://roo.no-ip.org/fish/"><tt>fish</tt> homepage</a>.
|
||||
@@ -23,7 +23,7 @@ Example:
|
||||
calls the \c echo command. \c echo is a command which will write its
|
||||
arguments to the screen. In the example above, the output will be
|
||||
'hello world'. Everything in fish is done with commands. There are
|
||||
commonds for performing a set of command multiple times, commands for
|
||||
commands for performing a set of command multiple times, commands for
|
||||
assigning variables, commands for treating a group of commands as a
|
||||
single command, etc.. And every single command follows the same simple
|
||||
syntax.
|
||||
@@ -120,11 +120,11 @@ a number called a file descriptor (FD). These are:
|
||||
- Standard output, FD 1, for writing, defaults to writing to the screen.
|
||||
- Standard error, FD 2, for writing errors and warnings, defaults to writing to the screen.
|
||||
|
||||
The reason for providing for two methods of output is so errors and
|
||||
The reason for providing for two methods of output is that errors and
|
||||
warnings can be separated from regular program output.
|
||||
|
||||
Any file descriptor can be directed to a different output than it's
|
||||
default through a simple mechanism called a redirecton.
|
||||
default through a simple mechanism called a redirection.
|
||||
|
||||
An example of a file redirection is <tt> echo hello \>output.txt</tt>,
|
||||
which directs the output of the echo command to the file error.txt.
|
||||
@@ -247,7 +247,7 @@ 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 or the space bar. Press any other key will
|
||||
exit the list and insert the presssed key into the command line.
|
||||
exit the list and insert the pressed key into the command line.
|
||||
|
||||
These are the general purpose tab completions that \c fish provides:
|
||||
|
||||
@@ -326,7 +326,7 @@ parameter to be expanded. These include:
|
||||
\subsection expand-wildcard Wildcards
|
||||
|
||||
If a star (*) or a question mark (?) is present in the parameter, \c
|
||||
fish attempts to mach the given parameter to any files in such a
|
||||
fish attempts to match the given parameter to any files in such a
|
||||
way that '?' can match any character except '/' and '*' can match any
|
||||
string of characters not containing '/'.
|
||||
|
||||
@@ -335,7 +335,7 @@ Example:
|
||||
|
||||
<code>???</code> matches any file in the current directory whose name is exactly three characters long.
|
||||
|
||||
If no matches are founf for a specific wildcard, it will expand intto
|
||||
If no matches are found for a specific wildcard, it will expand into
|
||||
zero arguments, i.e. to nothing. If none of the wildcarded arguments
|
||||
sent to a command result in any matches, the command will not be
|
||||
executed. If this happens when using the shell interactively, a
|
||||
@@ -344,7 +344,7 @@ warning will also be printed.
|
||||
\subsection expand-command-substitution Command substitution
|
||||
|
||||
If a parameter contains a set of parenthesis, the text enclosed by the
|
||||
parentesis will be interpreted as a list of commands. Om expansion,
|
||||
parenthesis will be interpreted as a list of commands. Om expansion,
|
||||
this list is executed, and substituted by the output. If the output is
|
||||
more than one line long, each line will be expanded to a new
|
||||
parameter.
|
||||
@@ -486,7 +486,7 @@ the shell through <a href="expand-variable">variable expansion</a>.
|
||||
|
||||
Example:
|
||||
|
||||
To use the value of a the variable \c smurf, write $ (dollar synbol)
|
||||
To use the value of a the variable \c smurf, write $ (dollar symbol)
|
||||
followed by the name of the variable, like <tt>echo Smurfs are
|
||||
$smurf</tt>, which would print the result 'Smurfs are blue'.
|
||||
|
||||
@@ -496,7 +496,7 @@ There are three kinds of variables in fish, universal, global and
|
||||
local variables. Universal variables are shared between all fish
|
||||
sessions a user is running on one computer. Global variables are
|
||||
specific to the current fish session, but are not associated with any
|
||||
soecific block scope, and will never be erased unless the user
|
||||
specific block scope, and will never be erased unless the user
|
||||
explicitly requests it using <tt>set -e</tt>. Local variables are
|
||||
specific to the current fish session, and associated with a specific
|
||||
block of commands, and is automatically erased when a specific block
|
||||
@@ -513,7 +513,7 @@ creating or updating a variable are:
|
||||
|
||||
-# If a variable is explicitly set to either universal, global or local, that setting will be honored
|
||||
-# If a variable is not explicitly set to be either universal, global or local, but has been previously defined, the variable scope is not changed
|
||||
-# If a variable is not explicitly set to be either universal, global or local and has never befor been defined, the variable will be local to the currently executing functions. If no function is executing, the variable will be global.
|
||||
-# If a variable is not explicitly set to be either universal, global or local and has never before been defined, the variable will be local to the currently executing functions. If no function is executing, the variable will be global.
|
||||
|
||||
There may be many variables with the same name, but different scopes.
|
||||
When using a variable, the variable scope will be searched from the
|
||||
@@ -552,9 +552,9 @@ prompt will instantly change to blue on both terminals.
|
||||
\subsection variables-functions Variable scope for functions
|
||||
|
||||
When calling a function, all non-global variables temporarily
|
||||
dissapear. This shadowing of the local scope is needed since the
|
||||
disappear. This shadowing of the local scope is needed since the
|
||||
variable namespace would become cluttered, making it very easy to
|
||||
accidentaly overwrite variables from another function.
|
||||
accidentally overwrite variables from another function.
|
||||
|
||||
For example, the following code will output 'Avast, mateys':
|
||||
|
||||
@@ -590,7 +590,7 @@ identical to the scoping rules for variables:
|
||||
|
||||
-# If a variable is explicitly set to either be exported or not exported, that setting will be honored
|
||||
-# If a variable is not explicitly set to be exported or not exported, but has been previously defined, the previous exporting rule for the variable is kept
|
||||
-# If a variable is not explicitly set to be either global or local and has never befor been defined, the variable will not be exported
|
||||
-# If a variable is not explicitly set to be either global or local and has never before been defined, the variable will not be exported
|
||||
|
||||
|
||||
\subsection variables-arrays Arrays
|
||||
@@ -643,7 +643,7 @@ certain environment variables.
|
||||
- \c CDPATH, which is an array of directories in which to search for the new directory for the \c cd builtin.
|
||||
- \c fish_color_normal, \c fish_color_command, \c fish_color_substitution, \c fish_color_redirection, \c fish_color_end, \c fish_color_error, \c fish_color_param, \c fish_color_comment, \c fish_color_match, \c fish_color_search_match, \c fish_color_cwd, \c fish_pager_color_prefix, \c fish_pager_color_completion, \c fish_pager_color_description and \c fish_pager_color_progress are used to change the color of various elements in \c fish. These variables are universal, i.e. when changing them, their new value will be used by all running fish sessions. The new value will also be retained when restarting fish.
|
||||
- \c PATH, which is an array of directories in which to search for commands
|
||||
- \c umask, which is the current file creation mask. The prefered way to change the umask variable is through the <a href="commands.html#umask">umask shellscript function</a>. An attempt to set umask to an invalid value will always fail.
|
||||
- \c umask, which is the current file creation mask. The preferred way to change the umask variable is through the <a href="commands.html#umask">umask shellscript function</a>. An attempt to set umask to an invalid value will always fail.
|
||||
|
||||
\c fish also sends additional information to the user through the
|
||||
values of certain environment variables. The user can not change the
|
||||
@@ -657,7 +657,7 @@ values of these variables. They are:
|
||||
- \c USER, which is the username. This variable can only be changed by the root user.
|
||||
|
||||
Variables whose name are in uppercase are exported to the commands
|
||||
started by fish. This rule is not enfored by fish, but it is good
|
||||
started by fish. This rule is not enforced by fish, but it is good
|
||||
coding practice to use casing to distinguish between exported and
|
||||
unexported variables. \c fish also uses several variables
|
||||
internally. Such variables are prefixed with the string __FISH or
|
||||
@@ -682,6 +682,7 @@ builtins or shellscript functions, and can only be used inside fish.
|
||||
- <a href="builtins.html#begin">begin</a>, execute a block of commands
|
||||
- <a href="builtins.html#bind">bind</a>, change keyboard bindings
|
||||
- <a href="builtins.html#break">break</a>, stop the execution of a loop
|
||||
- <a href="builtins.html#block">block</a>, Temporarily block delivery of events
|
||||
- <a href="builtins.html#builtin">builtin</a>, execute a builtin command
|
||||
- <a href="builtins.html#case">case</a>, conditionally execute a block of commands
|
||||
- <a href="builtins.html#cd">cd</a>, change the current directory
|
||||
@@ -737,24 +738,26 @@ Here are some of the commands available in the editor:
|
||||
- End or Ctrl-e moves to the end of line
|
||||
- Left and right moves one character left or right
|
||||
- Alt-left and Alt-right moves one word left or right, or moves forward/backward in the directory history if the commandline is empty
|
||||
- Up and down search the command history for the previous/next command containing the string that was specified on the commandline before the search was started. If the commandline was empty when the search started, all commands match. See the <a href='#history'>history </a>section for more information on history searching.
|
||||
- Alt-up and Alt-down search the command history for the previous/next token containing the token under the cursor before the search was started. If the commandline was not on a token when the search started, all tokens match. See the <a href='#history'>history </a>section for more information on history searching.
|
||||
- Delete and backspace removes one character forwards or backwards
|
||||
- Ctrl-c delete entire line
|
||||
- Ctrl-d delete one character to the right of the cursor, unless the buffer is empty, in which case the shell will exit
|
||||
- Ctrl-k move contents from cursor to end of line to <a href="#killring">killring</a>
|
||||
- Ctrl-u move contents from beginning of line to cursor <a href="#killring">killring</a>
|
||||
- Ctrl-k move contents from the cursor to the end of line to the <a href="#killring">killring</a>
|
||||
- Ctrl-u move contents from the beginning of line to the cursor to the <a href="#killring">killring</a>
|
||||
- Ctrl-l clear and repaint screen
|
||||
- Ctrl-w move previous word to <a href="#killring">killring</a>
|
||||
- Alt-d move next word to <a href="#killring">killring</a>
|
||||
- Ctrl-w move previous word to the <a href="#killring">killring</a>
|
||||
- Alt-d move next word to the <a href="#killring">killring</a>
|
||||
- Alt-w prints a short description of the command under the cursor
|
||||
- Alt-l lists the contents of the current directory, unless the cursor is over a directory argument, in which case the contents of that directory will be listed
|
||||
- Alt-k prints a list of all key bindings
|
||||
- Alt-p adds the string '| less;' to the end of the job under the cursor. The result is that the output of the command will be paged.aadddddssss
|
||||
|
||||
You can change these key bindings by making an inputrc file. To do
|
||||
this, copy the file /etc/fish_inputrc to your home directory and
|
||||
rename it to '.fish_inputrc'. Now you can edit the file .fish_inputrc,
|
||||
to change your key bindings. The fileformat of this file is described
|
||||
in the manual page for readline. Use the command <tt>man readline</tt>
|
||||
to read up on this syntax. Please note thet the list of key binding
|
||||
to read up on this syntax. Please note that the list of key binding
|
||||
functions in fish is different to that offered by readline. Currently,
|
||||
the following functions are available:
|
||||
|
||||
@@ -783,7 +786,11 @@ the following functions are available:
|
||||
- \c yank, insert the latest entry of the killring into the buffer
|
||||
- \c yank-pop, rotate to the previous entry of the killring
|
||||
|
||||
You can also bind a pice of shellscript to a key using the same
|
||||
syntax. For example, the Alt-p functionality described above is
|
||||
implemented using the following keybinding.
|
||||
|
||||
<pre>"\M-p": if commandline -j|grep -v 'less *$' >/dev/null; commandline -aj "|less;"; end</pre>
|
||||
|
||||
\subsection killring Copy and paste (Kill Ring)
|
||||
|
||||
@@ -807,6 +814,14 @@ forwards and backwards in the history. If the current command line is
|
||||
not empty when starting a history search, only the commands containing
|
||||
the string entered into the command line are shown.
|
||||
|
||||
By pressing Alt-up and Alt-down, a history search is also performed,
|
||||
but instead of searching for a complete commandline, each commandline
|
||||
is tokenized into separate elements just like it would be before
|
||||
execution, and each such token is matched agains the token under the
|
||||
cursor when the search began.
|
||||
|
||||
History searches can be aborted by pressing the escape key.
|
||||
|
||||
The history is stored in the file '.fish_history'. It is automatically
|
||||
read on startup and merged on program exit.
|
||||
|
||||
@@ -904,17 +919,11 @@ The default \c fish prompt is
|
||||
<p>
|
||||
<pre>
|
||||
function fish_prompt -d "Write out the prompt"
|
||||
printf '\%s\@\%s\%s\\n\%s\%s\\n> ' (whoami) (hostname|cut -d . -f 1) (set_color \$fish_color_cwd) (prompt_pwd) (set_color normal)
|
||||
printf '\%s\@\%s\%s\%s\%s> ' (whoami) (hostname|cut -d . -f 1) (set_color \$fish_color_cwd) (prompt_pwd) (set_color normal)
|
||||
end
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
If you are using \c set_color or other commands that output escape
|
||||
codes to change the font settings of the terminal, you must always and
|
||||
every such sequence with a newline. This is needed since fish needs to
|
||||
know that exact length of the prompt in order to tetect when the
|
||||
cursor reaches the end of the line. Any newlines in the output of the
|
||||
\c fish_prompt command are ignored.
|
||||
|
||||
\subsection title Programmable title
|
||||
|
||||
@@ -985,7 +994,7 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
|
||||
- Check keybinding commands for output - if non has happened, don't repaint to reduce flicker
|
||||
- The jobs builtin should be able to give information on a specific job, such as the pids of the processes in the job
|
||||
- Syntax highlighting should mark cd to non-existing directories as an error
|
||||
|
||||
- wait shellscript
|
||||
|
||||
\subsection todo-possible Possible features
|
||||
|
||||
@@ -1007,6 +1016,8 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
|
||||
- show the whole list of commands on using tab on an empty commandline
|
||||
- Automatically move cursor to the end of the current token before completing
|
||||
- Map variables. (export only the values. When expanding with no key specified, expand to all values.)
|
||||
- Descriptions for variables using 'set -d'.
|
||||
- Parse errors should when possible honor IO redirections
|
||||
|
||||
\subsection bugs Known bugs
|
||||
|
||||
@@ -1014,13 +1025,13 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
|
||||
- Many completions are made specifically for the GNU
|
||||
version of a POSIX command
|
||||
- Yanking weird characters from clipboard prints Unicode escapes
|
||||
|
||||
- Suspending and then resuming pipelines containing a builtin seems to be broken.
|
||||
|
||||
If you think you have found a bug not described here, please send a
|
||||
report to <a href="mailto:axel@liljencrantz.se"> axel@liljencrantz.se
|
||||
</a>.
|
||||
|
||||
\subsection Known issues
|
||||
\subsection issues Known issues
|
||||
|
||||
Older versions of Doxygen has bugs in the man-page generation which
|
||||
cause the builtin help to render incorrectly. Version 1.2.14 is known
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
\section jobs jobs - print currently running jobs
|
||||
|
||||
\subsection jobs-synopsis
|
||||
<tt>jobs</tt>
|
||||
<tt>jobs [OPTIONS] [PID]</tt>
|
||||
|
||||
\subsection jobs-description Description
|
||||
The <tt>jobs</tt> builtin causes fish to print a list of the currently
|
||||
running jobs and their status.
|
||||
|
||||
On systems that supports this feature, jobs will also print the CPU
|
||||
usage of each job since the last command was executed. The CPU usage
|
||||
is expressed as a percentage of full CPU activity. Note that on
|
||||
jobs accepts the following switches:
|
||||
|
||||
- <tt>-c</tt> or <tt>--command</tt> print the command name for each process in jobs
|
||||
- <tt>-g</tt> or <tt>--group</tt> only print the group id of each job
|
||||
- <tt>-l</tt> or <tt>--last</tt> only the last job to be started is printed
|
||||
- <tt>-p</tt> or <tt>--process</tt> print the procces id for each process in all jobs
|
||||
|
||||
On systems that supports this feature, jobs will print the CPU usage
|
||||
of each job since the last command was executed. The CPU usage is
|
||||
expressed as a percentage of full CPU activity. Note that on
|
||||
multiprocessor systems, the total activity may be more than 100\%.
|
||||
|
||||
37
doc_src/trap.txt
Normal file
37
doc_src/trap.txt
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
\section trap trap - perform an action when the shell recives a signal
|
||||
|
||||
\subsection trap-synopsis Synopsis
|
||||
<tt>trap [OPTIONS] [[ARG] SIGSPEC ... ]</tt>
|
||||
|
||||
\subsection trap-description Description
|
||||
|
||||
Trap is a shellscript wrapper around the fish event delivery
|
||||
framework. IT is defined for backwards compatibility reasons. For
|
||||
other uses, it is recomended to define a <a
|
||||
href='index.html#event'>event handler</a>.
|
||||
|
||||
- ARG is the command to be executed on signal delivary
|
||||
- SIGSPEC is the name of the signal to trap
|
||||
- \c -h or \c --help Display help and exit
|
||||
- \c -l or \c --list-signals print a list of signal names
|
||||
- \c -p or \c --print print all defined signal handlers
|
||||
|
||||
If ARG and SIGSPEC are both specified, ARG is the command to be
|
||||
executed when the signal specified by SIGSPEC is delivered.
|
||||
|
||||
If ARG is absent (and there is a single SIGSPEC) or -, each specified
|
||||
signal is reset to its original disposition (the value it had upon
|
||||
entrance to the shell). If ARG is the null string the signal
|
||||
specified by each SIGSPEC is ignored by the shell and by the commands
|
||||
it invokes.
|
||||
|
||||
If ARG is not present and -p has been supplied, then the trap commands
|
||||
associated with each SIGSPEC are displayed. If no arguments are
|
||||
supplied or if only -p is given, trap prints the list of commands
|
||||
associated with each signal.
|
||||
|
||||
Signal names are case insensitive and the SIG prefix is optional.
|
||||
|
||||
The return status is 1 if any SIGSPEC is invalid; otherwise trap
|
||||
returns 0.
|
||||
24
env.c
24
env.c
@@ -236,7 +236,6 @@ static void universal_callback( int type,
|
||||
|
||||
if( str )
|
||||
{
|
||||
array_list_t arg;
|
||||
event_t ev;
|
||||
|
||||
has_changed=1;
|
||||
@@ -245,12 +244,12 @@ static void universal_callback( int type,
|
||||
ev.param1.variable=name;
|
||||
ev.function_name=0;
|
||||
|
||||
al_init( &arg );
|
||||
al_push( &arg, L"VARIABLE" );
|
||||
al_push( &arg, str );
|
||||
al_push( &arg, name );
|
||||
event_fire( &ev, &arg );
|
||||
al_destroy( &arg );
|
||||
al_init( &ev.arguments );
|
||||
al_push( &ev.arguments, L"VARIABLE" );
|
||||
al_push( &ev.arguments, str );
|
||||
al_push( &ev.arguments, name );
|
||||
event_fire( &ev );
|
||||
al_destroy( &ev.arguments );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +488,6 @@ void env_set( const wchar_t *key,
|
||||
int done=0;
|
||||
|
||||
event_t ev;
|
||||
array_list_t ev_list;
|
||||
int is_universal = 0;
|
||||
|
||||
if( (var_mode & ENV_USER ) &&
|
||||
@@ -669,14 +667,14 @@ void env_set( const wchar_t *key,
|
||||
ev.param1.variable = key;
|
||||
ev.function_name = 0;
|
||||
|
||||
al_init( &ev_list );
|
||||
al_push( &ev_list, L"VARIABLE" );
|
||||
al_push( &ev_list, key );
|
||||
al_init( &ev.arguments );
|
||||
al_push( &ev.arguments, L"VARIABLE" );
|
||||
al_push( &ev.arguments, key );
|
||||
|
||||
// debug( 1, L"env_set: fire events on variable %ls", key );
|
||||
event_fire( &ev, &ev_list );
|
||||
event_fire( &ev );
|
||||
// debug( 1, L"env_set: return from event firing" );
|
||||
al_destroy( &ev_list );
|
||||
al_destroy( &ev.arguments );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
136
event.c
136
event.c
@@ -67,6 +67,12 @@ static array_list_t *events;
|
||||
*/
|
||||
static array_list_t *killme;
|
||||
|
||||
/**
|
||||
List of events that have been sent but have not yet been delivered because they are blocked.
|
||||
*/
|
||||
static array_list_t *blocked;
|
||||
|
||||
|
||||
/**
|
||||
Tests if one event instance matches the definition of a event
|
||||
class. If the class defines a function name, that will also be a
|
||||
@@ -120,7 +126,7 @@ static int event_match( event_t *class, event_t *instance )
|
||||
Create an identical copy of an event. Use deep copying, i.e. make
|
||||
duplicates of any strings used as well.
|
||||
*/
|
||||
static event_t *event_copy( event_t *event )
|
||||
static event_t *event_copy( event_t *event, int copy_arguments )
|
||||
{
|
||||
event_t *e = malloc( sizeof( event_t ) );
|
||||
if( !e )
|
||||
@@ -133,12 +139,55 @@ static event_t *event_copy( event_t *event )
|
||||
if( e->type == EVENT_VARIABLE )
|
||||
e->param1.variable = wcsdup( e->param1.variable );
|
||||
|
||||
al_init( &e->arguments );
|
||||
if( copy_arguments )
|
||||
{
|
||||
int i;
|
||||
for( i=0; i<al_get_count( &event->arguments ); i++ )
|
||||
{
|
||||
al_push( &e->arguments, wcsdup( (wchar_t *)al_get( &event->arguments, i ) ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
static int event_is_blocked( event_t *e )
|
||||
{
|
||||
block_t *block;
|
||||
event_block_t *eb;
|
||||
|
||||
for( block = current_block; block; block = block->outer )
|
||||
{
|
||||
for( eb = block->first_event_block; eb; eb=eb->next )
|
||||
{
|
||||
if( eb->type & (1<<EVENT_ANY ) )
|
||||
return 1;
|
||||
if( eb->type & (1<<e->type) )
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
for( eb = global_event_block; eb; eb=eb->next )
|
||||
{
|
||||
if( eb->type & (1<<EVENT_ANY ) )
|
||||
return 1;
|
||||
if( eb->type & (1<<e->type) )
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void event_add_handler( event_t *event )
|
||||
{
|
||||
event_t *e = event_copy( event );
|
||||
event_t *e;
|
||||
|
||||
e = event_copy( event, 0 );
|
||||
|
||||
if( !events )
|
||||
events = al_new();
|
||||
@@ -268,7 +317,7 @@ static int event_is_killed( event_t *e )
|
||||
matches' path. This means that nothing is allocated/initialized
|
||||
unless that is needed.
|
||||
*/
|
||||
static void event_fire_internal( event_t *event, array_list_t *arguments )
|
||||
static void event_fire_internal( event_t *event )
|
||||
{
|
||||
int i, j;
|
||||
string_buffer_t *b=0;
|
||||
@@ -337,9 +386,9 @@ static void event_fire_internal( event_t *event, array_list_t *arguments )
|
||||
|
||||
sb_append( b, criterion->function_name );
|
||||
|
||||
for( j=0; j<al_get_count(arguments); j++ )
|
||||
for( j=0; j<al_get_count(&event->arguments); j++ )
|
||||
{
|
||||
wchar_t *arg_esc = escape( (wchar_t *)al_get( arguments, j), 0 );
|
||||
wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 0 );
|
||||
sb_append( b, L" " );
|
||||
sb_append( b, arg_esc );
|
||||
free( arg_esc );
|
||||
@@ -385,15 +434,40 @@ static void event_fire_internal( event_t *event, array_list_t *arguments )
|
||||
/**
|
||||
Handle all pending signal events
|
||||
*/
|
||||
static void event_fire_signal_events()
|
||||
static void event_fire_delayed()
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
if( blocked && is_event==1)
|
||||
{
|
||||
array_list_t *new_blocked = 0;
|
||||
|
||||
for( i=0; i<al_get_count( blocked ); i++ )
|
||||
{
|
||||
event_t *e = (event_t *)al_get( blocked, i );
|
||||
if( event_is_blocked( e ) )
|
||||
{
|
||||
if( !new_blocked )
|
||||
new_blocked = al_new();
|
||||
al_push( new_blocked, e );
|
||||
}
|
||||
else
|
||||
{
|
||||
event_fire_internal( e );
|
||||
event_free( e );
|
||||
}
|
||||
}
|
||||
al_destroy( blocked );
|
||||
free( blocked );
|
||||
blocked = new_blocked;
|
||||
}
|
||||
|
||||
while( sig_list[active_list].count > 0 )
|
||||
{
|
||||
int i;
|
||||
signal_list_t *lst;
|
||||
event_t e;
|
||||
array_list_t a;
|
||||
al_init( &a );
|
||||
al_init( &e.arguments );
|
||||
|
||||
/*
|
||||
Switch signal lists
|
||||
@@ -421,19 +495,27 @@ static void event_fire_signal_events()
|
||||
for( i=0; i<lst->count; i++ )
|
||||
{
|
||||
e.param1.signal = lst->signal[i];
|
||||
al_set( &a, 0, sig2wcs( e.param1.signal ) );
|
||||
event_fire_internal( &e, &a );
|
||||
al_set( &e.arguments, 0, sig2wcs( e.param1.signal ) );
|
||||
if( event_is_blocked( &e ) )
|
||||
{
|
||||
if( !blocked )
|
||||
blocked = al_new();
|
||||
al_push( blocked, event_copy(&e, 1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
event_fire_internal( &e );
|
||||
}
|
||||
}
|
||||
|
||||
al_destroy( &a );
|
||||
al_destroy( &e.arguments );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void event_fire( event_t *event, array_list_t *arguments )
|
||||
void event_fire( event_t *event )
|
||||
{
|
||||
//int is_event_old = is_event;
|
||||
is_event++;
|
||||
|
||||
if( event && (event->type == EVENT_SIGNAL) )
|
||||
@@ -452,13 +534,26 @@ void event_fire( event_t *event, array_list_t *arguments )
|
||||
}
|
||||
else
|
||||
{
|
||||
event_fire_signal_events();
|
||||
|
||||
event_fire_delayed();
|
||||
|
||||
if( event )
|
||||
event_fire_internal( event, arguments );
|
||||
{
|
||||
if( event_is_blocked( event ) )
|
||||
{
|
||||
if( !blocked )
|
||||
blocked = al_new();
|
||||
|
||||
al_push( blocked, event_copy(event, 1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
event_fire_internal( event );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
is_event--;// = is_event_old;
|
||||
is_event--;
|
||||
}
|
||||
|
||||
|
||||
@@ -487,9 +582,14 @@ void event_destroy()
|
||||
|
||||
void event_free( event_t *e )
|
||||
{
|
||||
/*
|
||||
When apropriate, we clear the argument vector
|
||||
*/
|
||||
al_foreach( &e->arguments, (void (*)(const void *))&free );
|
||||
al_destroy( &e->arguments );
|
||||
|
||||
free( (void *)e->function_name );
|
||||
if( e->type == EVENT_VARIABLE )
|
||||
free( (void *)e->param1.variable );
|
||||
free( e );
|
||||
}
|
||||
|
||||
|
||||
24
event.h
24
event.h
@@ -17,6 +17,9 @@
|
||||
*/
|
||||
#define EVENT_ANY_PID 0
|
||||
|
||||
/**
|
||||
Enumeration of event types
|
||||
*/
|
||||
enum
|
||||
{
|
||||
EVENT_ANY, /**< Matches any event type (Not always any event, as the function name may limit the choice as well */
|
||||
@@ -40,18 +43,24 @@ typedef struct
|
||||
Type of event
|
||||
*/
|
||||
int type;
|
||||
|
||||
/**
|
||||
The type-specific parameter
|
||||
*/
|
||||
union
|
||||
{
|
||||
/**
|
||||
Signal number for signal-type events.Use EVENT_ANY_SIGNAL to match any signal
|
||||
Signal number for signal-type events.Use EVENT_ANY_SIGNAL
|
||||
to match any signal
|
||||
*/
|
||||
int signal;
|
||||
/**
|
||||
Variable name for variable-type events.
|
||||
Variable name for variable-type events.
|
||||
*/
|
||||
const wchar_t *variable;
|
||||
/**
|
||||
Process id for process-type events. Use EVENT_ANY_PID to match any pid.
|
||||
Process id for process-type events. Use EVENT_ANY_PID to
|
||||
match any pid.
|
||||
*/
|
||||
pid_t pid;
|
||||
/**
|
||||
@@ -65,6 +74,13 @@ typedef struct
|
||||
The name of the event handler function
|
||||
*/
|
||||
const wchar_t *function_name;
|
||||
|
||||
/**
|
||||
The argument list. Only used when sending a new event using
|
||||
event_fire. In all other situations, the value of this variable
|
||||
is ignored.
|
||||
*/
|
||||
array_list_t arguments;
|
||||
}
|
||||
event_t;
|
||||
|
||||
@@ -98,7 +114,7 @@ int event_get( event_t *criterion, array_list_t *out );
|
||||
\param event the specific event whose handlers should fire
|
||||
\param arguments the argument string to send to the event handler function
|
||||
*/
|
||||
void event_fire( event_t *event, array_list_t *arguments );
|
||||
void event_fire( event_t *event );
|
||||
|
||||
/**
|
||||
Initialize the event-handling library
|
||||
|
||||
12
expand.c
12
expand.c
@@ -20,6 +20,8 @@ parameter expansion.
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef SunOS
|
||||
#include <procfs.h>
|
||||
#endif
|
||||
@@ -68,7 +70,7 @@ parameter expansion.
|
||||
#define COMPLETE_LAST_DESC COMPLETE_SEP_STR L"Last background job"
|
||||
|
||||
#define COMPLETE_VAR_DESC L"Variable name is zero characters long."
|
||||
#define COMPLETE_VAR2_DESC L" Did you mean {$VARIABLE}? For information on how variable expansion in fish differs from Posix variable expansion, see the manual section on variable expansion by typing 'help expand-variable'."
|
||||
#define COMPLETE_VAR2_DESC L"Variable name is zero characters long. Did you mean{$VARIABLE}? To learn about variable expansion in fish, type 'help expand-variable'."
|
||||
|
||||
/**
|
||||
String in process expansion denoting ourself
|
||||
@@ -713,7 +715,7 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
wchar_t * new_in;
|
||||
array_list_t l;
|
||||
int is_single = (c==VARIABLE_EXPAND_SINGLE);
|
||||
|
||||
|
||||
stop_pos = start_pos;
|
||||
|
||||
while( 1 )
|
||||
@@ -847,6 +849,7 @@ static int expand_variables( wchar_t *in, array_list_t *out )
|
||||
in[i]=0;
|
||||
|
||||
sb_append( &res, in );
|
||||
sb_append_char( &res, INTERNAL_SEPARATOR );
|
||||
|
||||
for( j=0; j<al_get_count( &l); j++ )
|
||||
{
|
||||
@@ -1173,6 +1176,11 @@ int expand_locate_subshell( wchar_t *in,
|
||||
*begin = paran_begin;
|
||||
*end = paran_count?in+wcslen(in):paran_end;
|
||||
|
||||
/* assert( *begin >= in );
|
||||
assert( *begin < (in+wcslen(in) ) );
|
||||
assert( *end >= *begin );
|
||||
assert( *end < (in+wcslen(in) ) );
|
||||
*/
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -127,8 +127,8 @@ static void history_load( wchar_t *name )
|
||||
|
||||
Use a hashtable to check for duplicates instead.
|
||||
*/
|
||||
if( !hash_get( &used,
|
||||
buff ) )
|
||||
if( wcslen(buff) && !hash_get( &used,
|
||||
buff ) )
|
||||
{
|
||||
history_count++;
|
||||
|
||||
@@ -465,10 +465,7 @@ const wchar_t *history_prev_match( const wchar_t *str )
|
||||
|
||||
if( history_current->prev == 0 )
|
||||
{
|
||||
if( history_test( str, history_current->data ) )
|
||||
return (wchar_t *)history_current->data;
|
||||
else
|
||||
return str;
|
||||
return str;
|
||||
}
|
||||
if( past_end )
|
||||
past_end = 0;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#
|
||||
|
||||
function __fish_use_subcommand
|
||||
set -l cmd -- (commandline -poc)
|
||||
set -l -- cmd (commandline -poc)
|
||||
set -e cmd[1]
|
||||
for i in $cmd
|
||||
switch $i
|
||||
@@ -69,7 +69,7 @@ complete -c darcs -s v -l verbose -d "give verbose output"
|
||||
# Here follows a huge list of subcommand-specific completions
|
||||
#
|
||||
|
||||
set record_opt -- -c darcs -n 'contains record (commandline -poc)'
|
||||
set -- record_opt -c darcs -n 'contains record (commandline -poc)'
|
||||
complete $record_opt -s m -l patch-name -d "Name of patch" -x
|
||||
complete $record_opt -s A -l author -d "Specify author id" -x
|
||||
complete $record_opt -l logfile -d "Give patch name and comment in file" -r
|
||||
@@ -95,7 +95,7 @@ complete $record_opt -l dont-look-for-adds -d "Don"\'"t look for any files or di
|
||||
set -e record_opt
|
||||
|
||||
|
||||
set pull_opt -- -c darcs -n 'contains pull (commandline -poc)'
|
||||
set -- pull_opt -c darcs -n 'contains pull (commandline -poc)'
|
||||
complete $pull_opt -s p -l patches -d "select patches matching REGEXP" -x
|
||||
complete $pull_opt -s t -l tags -d "select tags matching REGEXP" -x
|
||||
complete $pull_opt -s a -l all -d "answer yes to all patches"
|
||||
@@ -120,7 +120,7 @@ complete $pull_opt -l dont-set-scripts-executable -d "don"\'"t make scripts exec
|
||||
set -e pull_opt
|
||||
|
||||
|
||||
set apply_opt -- -c darcs -n 'contains apply (commandline -poc)'
|
||||
set -- apply_opt -c darcs -n 'contains apply (commandline -poc)'
|
||||
complete $apply_opt -s a -l all -d "answer yes to all patches"
|
||||
complete $apply_opt -l verify -d "verify that the patch was signed by a key in PUBRING" -r
|
||||
complete $apply_opt -l verify-ssl -d "verify using openSSL with authorized keys from file "\'"KEYS"\'"" -r
|
||||
@@ -147,7 +147,7 @@ complete $apply_opt -l set-scripts-executable -d "make scripts executable"
|
||||
complete $apply_opt -l dont-set-scripts-executable -d "don"\'"t make scripts executable"
|
||||
set -e apply_opt
|
||||
|
||||
set check_opt -- -c darcs -n 'contains check (commandline -poc)'
|
||||
set -- check_opt -c darcs -n 'contains check (commandline -poc)'
|
||||
complete $check_opt -s v -l verbose -d "give verbose output"
|
||||
complete $check_opt -s q -l quiet -d "suppress informational output"
|
||||
complete $check_opt -l complete -d "check the entire repository"
|
||||
@@ -159,13 +159,13 @@ complete $check_opt -l leave-test-directory -d "don"\'"t remove the test directo
|
||||
complete $check_opt -l remove-test-directory -d "remove the test directory"
|
||||
set -e check_opt
|
||||
|
||||
set mv_opt -- -c darcs -n 'contains mv (commandline -poc)'
|
||||
set -- mv_opt -c darcs -n 'contains mv (commandline -poc)'
|
||||
complete $mv_opt -s v -l verbose -d "give verbose output"
|
||||
complete $mv_opt -l case-ok -d "don"\'"t refuse to add files differing only in case"
|
||||
complete $mv_opt -l standard-verbosity -d "don"\'"t give verbose output"
|
||||
set -e mv_opt
|
||||
|
||||
set send_opt -- -c darcs -n 'contains send (commandline -poc)'
|
||||
set -- send_opt -c darcs -n 'contains send (commandline -poc)'
|
||||
complete $send_opt -s v -l verbose -d "give verbose output"
|
||||
complete $send_opt -s q -l quiet -d "suppress informational output"
|
||||
complete $send_opt -xs p -l patches -d "select patches matching REGEXP"
|
||||
@@ -194,7 +194,7 @@ complete $send_opt -l no-set-default -d "don"\'"t set default repository"
|
||||
complete $send_opt -rl sendmail-command -d "specify sendmail command"
|
||||
set -e send_opt
|
||||
|
||||
set init_opt -- -c darcs -n 'contains initialize (commandline -poc)'
|
||||
set -- init_opt -c darcs -n 'contains initialize (commandline -poc)'
|
||||
complete $init_opt -l plain-pristine-tree -d "Use a plain pristine tree [DEFAULT]"
|
||||
complete $init_opt -l no-pristine-tree -d "Use no pristine tree"
|
||||
set -e init_opt
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
complete -c fish -s c -l "command" -d "Run fish with this command"
|
||||
complete -c fish -s h -l help -d "Display help and exit"
|
||||
complete -c fish -l version -d "Display version and exit"
|
||||
complete -c fish -s v -l version -d "Display version and exit"
|
||||
complete -c fish -s i -l interactive -d "Run in interactive mode"
|
||||
complete -c fish -s p -l profile -d "Output profiling information to specified file" -f
|
||||
|
||||
6
init/completions/jobs.fish
Normal file
6
init/completions/jobs.fish
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
complete -c jobs -s p -l pid -d 'Show the process id of each process in the job'
|
||||
complete -c jobs -s g -l group -d 'Show group id of job'
|
||||
complete -c jobs -s c -l command -d 'Show commandname of each job'
|
||||
complete -c jobs -s l -l last -d 'Show status for last be started'
|
||||
@@ -7,7 +7,7 @@ if kill -L ^/dev/null >/dev/null
|
||||
|
||||
complete -c kill -s L -d "List codes and names of available signals"
|
||||
|
||||
set -- signals (kill -L | sed -r 's/([0-9]+) +([A-Z,0-9]+)/\1 \2\n/g;s/ +/ /g' | sed 's/^ //' | grep -E '^[^ ]+')
|
||||
set -- signals (kill -L | sed -e 's/\([0-9][0-9]*\) *([A-Z,0-9][A-Z,0-9]*\)/\1 \2\n/g;s/ +/ /g' | sed -e 's/^ //' | grep -E '^[^ ]+')
|
||||
for i in $signals
|
||||
set -- number (echo $i | cut -d " " -f 1)
|
||||
set -- name (echo $i | cut -d " " -f 2)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
function __fish_print_make_targets
|
||||
set files Makefile makefile GNUmakefile
|
||||
grep -h -E '^[^#%=$[:space:]][^#%=$]*:([^=]|$)' $files | cut -d ":" -f 1 | sed -r 's/^ *//;s/ *$//;s/ +/\n/g' ^/dev/null
|
||||
grep -h -E '^[^#%=$[:space:]][^#%=$]*:([^=]|$)' $files | cut -d ":" -f 1 | sed -e 's/^ *//;s/ *$//;s/ */\n/g' ^/dev/null
|
||||
end
|
||||
|
||||
complete -x -c make -a "(__fish_print_make_targets)" -d "Target"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Completions for the modprobe command
|
||||
#
|
||||
|
||||
complete -c modprobe -d Module -a "(/sbin/modprobe -l | sed -re 's/\/.*\/([^\/.]*).*/\1/')"
|
||||
complete -c modprobe -d Module -a "(/sbin/modprobe -l | sed -e 's/\/.*\/\([^\/.]*\).*/\1/')"
|
||||
complete -c modprobe -s v -l verbose -d "Print messages about what the program is doing"
|
||||
complete -c modprobe -s C -l config -d "Configuration file" -r
|
||||
complete -c modprobe -s c -l showconfig -d "Dump configuration file"
|
||||
|
||||
@@ -17,7 +17,7 @@ complete -c scp -d Hostname -a "
|
||||
|
||||
(
|
||||
#Prepend any username specified in the completion to the hostname
|
||||
echo (commandline -ct)|grep -o '.*@'
|
||||
echo (commandline -ct)|sed -ne 's/\(.*@\).*/\1/p'
|
||||
)(
|
||||
cat ~/.ssh/known_hosts{,2} ^/dev/null|cut -d ' ' -f 1| cut -d , -f 1
|
||||
):
|
||||
|
||||
@@ -71,7 +71,7 @@ complete -x -c ssh -d Hostname -a "
|
||||
|
||||
(
|
||||
#Prepend any username specified in the completion to the hostname
|
||||
echo (commandline -ct)|grep -o '.*@'
|
||||
echo (commandline -ct)|sed -ne 's/\(.*@\).*/\1/p'
|
||||
)(__fish_print_hostnames)
|
||||
|
||||
(__fish_print_users)@
|
||||
|
||||
4
init/completions/trap.fish
Normal file
4
init/completions/trap.fish
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
complete -c trap -s l -l list-signals -d 'Display names of all signals'
|
||||
complete -c trap -s p -l print -d 'Display all currently defined trap handlers'
|
||||
complete -c trap -s h -l help -d 'Display help and exit'
|
||||
@@ -10,7 +10,7 @@ complete -y mount
|
||||
#
|
||||
# Find all mountpoints
|
||||
#
|
||||
complete -c umount -d "Mount point" -x -a '(cat /etc/mtab | cut -d " " -f 1-2|tr " " \n|sed -re "s/[0-9\.]*:\//\//"|grep "^/")'
|
||||
complete -c umount -d "Mount point" -x -a '(cat /etc/mtab | cut -d " " -f 1-2|tr " " \n|sed -e "s/[0-9\.]*:\//\//"|grep "^/")'
|
||||
|
||||
complete -c umount -s V -d "Display version and exit"
|
||||
complete -c umount -s h -d "Display help and exit"
|
||||
|
||||
@@ -75,4 +75,4 @@ complete -c yum -n 'contains clean (commandline -poc)' -x -a "
|
||||
packages\t'Delete cached package files'
|
||||
headers\t'Delete cached header files'
|
||||
all\t'Delete all cache contents'
|
||||
"
|
||||
"
|
||||
|
||||
11
init/fish.in
11
init/fish.in
@@ -15,7 +15,14 @@ set -g IFS \ \t\n
|
||||
# want this even for text-only terminals.
|
||||
#
|
||||
|
||||
for i in /bin /usr/bin /usr/X11R6/bin @PREFIX@/bin
|
||||
set -l path_list /bin /usr/bin /usr/X11R6/bin @PREFIX@/bin
|
||||
|
||||
set -l uid (id -u 2>/dev/null)
|
||||
if test "$uid" = 0
|
||||
set path_list $path_list /sbin /usr/sbin /usr/local/sbin
|
||||
end
|
||||
|
||||
for i in $path_list
|
||||
if not expr "$PATH" : .\*$i.\* >/dev/null
|
||||
if test -d $i
|
||||
set PATH $PATH $i
|
||||
@@ -24,6 +31,8 @@ for i in /bin /usr/bin /usr/X11R6/bin @PREFIX@/bin
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Set some value for LANG if nothing was set before
|
||||
#
|
||||
|
||||
@@ -115,7 +115,7 @@ function help -d "Show help for the fish shell"
|
||||
|
||||
# If we are in a graphical environment, we check if there is a
|
||||
# graphical browser to use instead.
|
||||
if test (echo $DISPLAY)
|
||||
if test (echo $DISPLAY) -a \( "$XAUTHORITY" = "$HOME/.Xauthority" -o "$XAUTHORITY" = "" \)
|
||||
for i in $graphical_browsers
|
||||
if which $i 2>/dev/null >/dev/null
|
||||
set fish_browser $i
|
||||
@@ -216,20 +216,11 @@ end
|
||||
# ellipsised. This function is used by the default prompt command.
|
||||
#
|
||||
|
||||
function prompt_pwd -d "Print the current working directory, ellipsise it if it is longer than 1/4 of the terminal width"
|
||||
set wd (pwd)
|
||||
set len (echo $wd|wc -c)
|
||||
set max_width (echo $COLUMNS/4|bc)
|
||||
if test $len -gt $max_width
|
||||
#Write ellipsis character if known to be using UTF
|
||||
#else use $
|
||||
set -l ellipsis '$' #default
|
||||
if expr match "$LANG" ".*UTF" >/dev/null
|
||||
set ellipsis \u2026
|
||||
end
|
||||
printf %s%s $ellipsis (echo $wd|cut -c (echo $len-$max_width-1|bc)- ^/dev/null )
|
||||
else
|
||||
echo $wd
|
||||
function prompt_pwd -d "Print the current working directory, shortend to fit the prompt"
|
||||
set -l wd (pwd)
|
||||
printf "%s" $wd|sed -e 's-/\([^/]\)\([^/]*\)-/\1-g'
|
||||
if test $wd != '~'
|
||||
printf "%s\n" $wd|sed -e 's-.*/[^/]\([^/]*$\)-\1-'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -238,13 +229,7 @@ end
|
||||
#
|
||||
|
||||
function pwd -d "Print working directory"
|
||||
set out (command pwd $argv)
|
||||
if echo $out| grep \^$HOME >/dev/null
|
||||
printf \~
|
||||
echo $out |cut -b (echo $HOME|wc -c)- ^/dev/null
|
||||
else
|
||||
printf "%s\n" $out
|
||||
end
|
||||
command pwd | sed -e "s|^$HOME|~|"
|
||||
end
|
||||
|
||||
#
|
||||
@@ -266,7 +251,7 @@ function vared -d "Edit variable value"
|
||||
if test (count $$argv ) -lt 2
|
||||
set init ''
|
||||
if test $$argv
|
||||
set init -- $$argv
|
||||
set -- init $$argv
|
||||
end
|
||||
set prompt 'set_color green; echo '$argv'; set_color normal; echo "> "'
|
||||
read -p $prompt -c $init tmp
|
||||
@@ -376,7 +361,7 @@ function cd -d "Change directory"
|
||||
end
|
||||
|
||||
# Avoid set completions
|
||||
set -- previous (command pwd)
|
||||
set previous (command pwd)
|
||||
|
||||
if test $argv[1] = - ^/dev/null
|
||||
if test $__fish_cd_direction = next ^/dev/null
|
||||
@@ -560,6 +545,144 @@ function __bold -d "Print argument in bold"
|
||||
set_color normal
|
||||
end
|
||||
|
||||
|
||||
function __trap_translate_signal
|
||||
set upper (echo $argv[1]|tr a-z A-Z)
|
||||
if expr $upper : 'SIG.*' >/dev/null
|
||||
echo $upper | cut -c 4-
|
||||
else
|
||||
echo $upper
|
||||
end
|
||||
end
|
||||
|
||||
function __trap_switch
|
||||
|
||||
switch $argv[1]
|
||||
case EXIT
|
||||
echo --on-exit %self
|
||||
|
||||
case '*'
|
||||
echo --on-signal $argv[1]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function trap -d 'Perform an action when the shell recives a signal'
|
||||
|
||||
set -l mode
|
||||
set -l cmd
|
||||
set -l sig
|
||||
set -l shortopt
|
||||
set -l longopt
|
||||
|
||||
set shortopt -o lph
|
||||
if getopt -T >/dev/null
|
||||
set longopt
|
||||
else
|
||||
set longopt -l print,help,list-signals
|
||||
end
|
||||
|
||||
if not getopt -n type -Q $shortopt $longopt -- $argv
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l tmp (getopt $shortopt $longopt -- $argv)
|
||||
|
||||
eval set opt $tmp
|
||||
|
||||
while count $opt >/dev/null
|
||||
switch $opt[1]
|
||||
case -h --help
|
||||
help trap
|
||||
return 0
|
||||
|
||||
case -p --print
|
||||
set mode print
|
||||
|
||||
case -l --list-signals
|
||||
set mode list
|
||||
|
||||
case --
|
||||
set -e opt[1]
|
||||
break
|
||||
|
||||
end
|
||||
set -e opt[1]
|
||||
end
|
||||
|
||||
if not count $mode >/dev/null
|
||||
|
||||
switch (count $opt)
|
||||
|
||||
case 0
|
||||
set mode print
|
||||
|
||||
case 1
|
||||
set mode clear
|
||||
|
||||
case '*'
|
||||
if test opt[1] = -
|
||||
set -e opt[1]
|
||||
set mode clear
|
||||
else
|
||||
set mode set
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
switch $mode
|
||||
case clear
|
||||
for i in $opt
|
||||
set -- sig (__trap_translate_signal $i)
|
||||
if test $sig
|
||||
functions -e __trap_handler_$sig
|
||||
end
|
||||
end
|
||||
|
||||
case set
|
||||
set -l cmd $opt[1]
|
||||
set -e opt[1]
|
||||
|
||||
for i in $opt
|
||||
|
||||
set -l -- sig (__trap_translate_signal $i)
|
||||
set -- sw (__trap_switch $sig)
|
||||
|
||||
if test $sig
|
||||
eval "function __trap_handler_$sig $sw; $cmd; end"
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
case print
|
||||
set -l names
|
||||
|
||||
if count $opt >/dev/null
|
||||
set -- names $opt
|
||||
else
|
||||
set -- names (functions -na|grep "^__trap_handler_"|sed -e 's/__trap_handler_//' )
|
||||
end
|
||||
|
||||
for i in $names
|
||||
|
||||
set -- sig (__trap_translate_signal $i)
|
||||
|
||||
if test sig
|
||||
functions __trap_handler_$i
|
||||
else
|
||||
return 1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
case list
|
||||
kill -l
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function __fish_type_help -d "Help for the type shellscript function"
|
||||
|
||||
set bullet \*
|
||||
@@ -609,7 +732,7 @@ function type -d "Print the type of a command"
|
||||
return 1
|
||||
end
|
||||
|
||||
set tmp -- (getopt $shortopt $longopt -- $argv)
|
||||
set -- tmp (getopt $shortopt $longopt -- $argv)
|
||||
|
||||
eval set opt -- $tmp
|
||||
|
||||
@@ -653,7 +776,7 @@ function type -d "Print the type of a command"
|
||||
|
||||
if test $selection != files
|
||||
|
||||
if contains -- $i (functions -n)
|
||||
if contains -- $i (functions -na)
|
||||
set status 0
|
||||
set found 1
|
||||
switch $mode
|
||||
@@ -858,7 +981,7 @@ function umask -d "Set default file permission mask"
|
||||
if getopt -T >/dev/null
|
||||
set longopt
|
||||
else
|
||||
set longopt -- -l as-command,symbolic,help
|
||||
set -- longopt -l as-command,symbolic,help
|
||||
end
|
||||
|
||||
if not getopt -n umask -Q $shortopt $longopt -- $argv
|
||||
@@ -867,7 +990,7 @@ function umask -d "Set default file permission mask"
|
||||
|
||||
set tmp -- (getopt $shortopt $longopt -- $argv)
|
||||
|
||||
eval set opt -- $tmp
|
||||
eval set -- opt $tmp
|
||||
|
||||
while count $opt >/dev/null
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ $if fish
|
||||
"\M-d": if test -z (commandline); dirh; else; commandline -f kill-word; end
|
||||
"\C-d": delete-or-exit
|
||||
# This will make sure the output of the current command is paged using the less pager when you press Meta-p
|
||||
"\M-p": if commandline -j|grep -v "less *$" >/dev/null; commandline -aj "|less;"; end
|
||||
"\M-p": if commandline -j|grep -v 'less *$' >/dev/null; commandline -aj "|less;"; end
|
||||
$endif
|
||||
|
||||
# Include user-specific inputrc file after including fish-specific
|
||||
|
||||
@@ -10,11 +10,8 @@ end
|
||||
# Print a greeting
|
||||
#
|
||||
|
||||
printf 'Welcome to fish, the friendly interactive shell\nType '
|
||||
set_color green
|
||||
printf 'help '
|
||||
set_color normal
|
||||
printf 'for instructions on how to use fish\n'
|
||||
printf 'Welcome to fish, the friendly interactive shell\n'
|
||||
printf 'Type %shelp%s for instructions on how to use fish\n' (set_color green) (set_color normal)
|
||||
|
||||
#
|
||||
# Set exit message
|
||||
@@ -29,7 +26,7 @@ end
|
||||
# long it is.
|
||||
|
||||
function fish_prompt -d "Write out the prompt"
|
||||
printf '%s@%s \n%s\n%s\n%s\n> ' (whoami) (hostname|cut -d . -f 1) (set_color $fish_color_cwd) (prompt_pwd) (set_color normal)
|
||||
printf '%s@%s %s%s%s> \n' (whoami) (hostname|cut -d . -f 1) (set_color $fish_color_cwd) (prompt_pwd) (set_color normal)
|
||||
end
|
||||
|
||||
#
|
||||
|
||||
4
input.c
4
input.c
@@ -698,7 +698,7 @@ static wchar_t *input_expand_sequence( const wchar_t *in )
|
||||
}
|
||||
debug( 1, L"Invalid sequence - Control-nothing?\n" );
|
||||
error = 1;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1270,7 +1270,7 @@ static int interrupt_handler()
|
||||
/*
|
||||
Fire any pending events
|
||||
*/
|
||||
event_fire( 0, 0 );
|
||||
event_fire( 0 );
|
||||
if( job_reap( 1 ) )
|
||||
repaint();
|
||||
if( reader_interupted() )
|
||||
|
||||
8
io.c
8
io.c
@@ -42,12 +42,12 @@ void io_buffer_read( io_data_t *d )
|
||||
|
||||
if( d->io_mode == IO_BUFFER )
|
||||
{
|
||||
if( fcntl( d->param1.pipe_fd[0], F_SETFL, 0 ) )
|
||||
/* if( fcntl( d->param1.pipe_fd[0], F_SETFL, 0 ) )
|
||||
{
|
||||
wperror( L"fcntl" );
|
||||
return;
|
||||
}
|
||||
debug( 4, L"exec_read_io_buffer: blocking read on fd %d", d->param1.pipe_fd[0] );
|
||||
} */
|
||||
debug( 4, L"io_buffer_read: blocking read on fd %d", d->param1.pipe_fd[0] );
|
||||
while(1)
|
||||
{
|
||||
char b[4096];
|
||||
@@ -71,7 +71,7 @@ void io_buffer_read( io_data_t *d )
|
||||
debug( 1,
|
||||
L"An error occured while reading output from code block on fd %d",
|
||||
d->param1.pipe_fd[0] );
|
||||
wperror( L"exec_read_io_buffer" );
|
||||
wperror( L"io_buffer_read" );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
2
output.c
2
output.c
@@ -128,7 +128,7 @@ void set_color( int c, int c2 )
|
||||
{
|
||||
c = c2 = FISH_COLOR_NORMAL;
|
||||
if( fg )
|
||||
writembs( tparm( set_a_foreground, 0 ) );
|
||||
writembs( tparm( fg, 0 ) );
|
||||
writembs( exit_attribute_mode );
|
||||
return;
|
||||
}
|
||||
|
||||
290
parser.c
290
parser.c
@@ -66,7 +66,7 @@ The fish parser. Contains functions for parsing code.
|
||||
Error message for tokenizer error. The tokenizer message is
|
||||
appended to this message.
|
||||
*/
|
||||
#define TOK_ERR_MSG L"Tokenizer error: %ls"
|
||||
#define TOK_ERR_MSG L"Tokenizer error: '%ls'"
|
||||
|
||||
/**
|
||||
Error message for short circut command error.
|
||||
@@ -89,28 +89,65 @@ The fish parser. Contains functions for parsing code.
|
||||
#define BLOCK_ERR_MSG L"Maximum number of nested blocks reached."
|
||||
|
||||
/**
|
||||
Error message on missing 'end'
|
||||
Error message when a non-string token is found when expecting a command name
|
||||
*/
|
||||
#define END_ERR_MSG L"Block missing 'end'"
|
||||
#define CMD_ERR_MSG L"Expected a command string, got token of type '%ls'"
|
||||
|
||||
/**
|
||||
Error message on pipe/bg character without command
|
||||
Error message when encountering an illegal command name
|
||||
*/
|
||||
#define CMD_ERR_MSG L"Expected command"
|
||||
#define ILLEGAL_CMD_ERR_MSG L"Illegal command name '%ls'"
|
||||
|
||||
/**
|
||||
Error message for wildcards with no matches
|
||||
*/
|
||||
#define WILDCARD_ERR_MSG L"Warning: No match for wildcard %ls"
|
||||
#define WILDCARD_ERR_MSG L"Warning: No match for wildcard '%ls'"
|
||||
|
||||
/**
|
||||
Error when using case builtin outside of switch block
|
||||
*/
|
||||
#define INVALID_CASE_ERR_MSG L"'case' builtin not inside of switch block"
|
||||
|
||||
/**
|
||||
Error when using loop control builtins (break or continue) outside of loop
|
||||
*/
|
||||
#define INVALID_LOOP_ERR_MSG L"Loop control command while not inside of loop"
|
||||
|
||||
/**
|
||||
Error when using else builtin outside of if block
|
||||
*/
|
||||
#define INVALID_ELSE_ERR_MSG L"'else' builtin not inside of if block"
|
||||
|
||||
/**
|
||||
Error when using end builtin outside of block
|
||||
*/
|
||||
#define INVALID_END_ERR_MSG L"'end' command outside of block"
|
||||
|
||||
/**
|
||||
Error message for Posix-style assignment
|
||||
*/
|
||||
#define COMMAND_ASSIGN_ERR_MSG L"Unknown command %ls. Did you mean 'set VARIABLE VALUE'? For information on setting variable values, see the manual section on the set command by typing 'help set'."
|
||||
#define COMMAND_ASSIGN_ERR_MSG L"Unknown command '%ls'. Did you mean 'set VARIABLE VALUE'? For information on setting variable values, see the manual section on the set command by typing 'help set'."
|
||||
|
||||
/**
|
||||
Error for invalid redirection token
|
||||
*/
|
||||
#define REDIRECT_TOKEN_ERR_MSG L"Expected redirection specification, got token of type '%ls'"
|
||||
|
||||
/**
|
||||
Error when encountering redirection without a command
|
||||
*/
|
||||
#define INVALID_REDIRECTION_ERR_MSG L"Encountered redirection when expecting a command name. Fish does not allow a redirection operation before a command."
|
||||
|
||||
/**
|
||||
Error for wrong token type
|
||||
*/
|
||||
#define UNEXPECTED_TOKEN_ERR_MSG L"Unexpected token of type '%ls'"
|
||||
|
||||
/** Last error code */
|
||||
int error_code;
|
||||
|
||||
event_block_t *global_event_block=0;
|
||||
|
||||
/** Position of last error */
|
||||
|
||||
static int err_pos;
|
||||
@@ -194,19 +231,23 @@ int block_count( block_t *b )
|
||||
|
||||
void parser_push_block( int type )
|
||||
{
|
||||
block_t *new = malloc( sizeof( block_t ));
|
||||
block_t *new = calloc( 1, sizeof( block_t ));
|
||||
|
||||
debug( 3, L"Block push %ls %d\n", parser_get_block_desc(type), block_count( current_block)+1 );
|
||||
|
||||
// debug( 2, L"Block push %ls %d\n", bl[type], block_count( current_block)+1 );
|
||||
new->outer = current_block;
|
||||
new->type = (current_block && current_block->skip)?FAKE:type;
|
||||
|
||||
/*
|
||||
New blocks should be skipped if the outer block is skipped,
|
||||
except TOP ans SUBST block, which open up new environments
|
||||
except TOP ans SUBST block, which open up new environments. Fake
|
||||
blocks should always be skipped. Rather complicated... :-(
|
||||
*/
|
||||
new->skip=current_block?current_block->skip:0;
|
||||
if( type == TOP || type == SUBST )
|
||||
new->skip = 0;
|
||||
if( type == FAKE )
|
||||
new->skip = 1;
|
||||
|
||||
new->job = 0;
|
||||
|
||||
@@ -226,7 +267,9 @@ void parser_push_block( int type )
|
||||
|
||||
void parser_pop_block()
|
||||
{
|
||||
// debug( 2, L"Block pop %ls %d\n", bl[current_block->type], block_count(current_block)-1 );
|
||||
|
||||
debug( 3, L"Block pop %ls %d\n", parser_get_block_desc(current_block->type), block_count(current_block)-1 );
|
||||
event_block_t *eb, *eb_next;
|
||||
|
||||
if( (current_block->type != FUNCTION_DEF ) &&
|
||||
(current_block->type != FAKE) &&
|
||||
@@ -267,6 +310,12 @@ void parser_pop_block()
|
||||
|
||||
}
|
||||
|
||||
for( eb=current_block->first_event_block; eb; eb=eb_next )
|
||||
{
|
||||
eb_next = eb->next;
|
||||
free(eb);
|
||||
}
|
||||
|
||||
block_t *old = current_block;
|
||||
current_block = current_block->outer;
|
||||
free( old );
|
||||
@@ -289,7 +338,7 @@ wchar_t *parser_get_block_desc( int block )
|
||||
return L"function definition block";
|
||||
|
||||
case FUNCTION_CALL:
|
||||
return L"fuction invocation block";
|
||||
return L"function invocation block";
|
||||
|
||||
case SWITCH:
|
||||
return L"switch block";
|
||||
@@ -322,7 +371,7 @@ wchar_t *parser_get_block_desc( int block )
|
||||
int parser_skip_arguments( const wchar_t *cmd )
|
||||
{
|
||||
|
||||
return contains_str( cmd,
|
||||
return contains_str( cmd,
|
||||
L"else",
|
||||
L"begin",
|
||||
(void *)0 );
|
||||
@@ -494,19 +543,23 @@ wchar_t *parser_cdpath_get( wchar_t *dir )
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *path = env_get(L"CDPATH");
|
||||
wchar_t *path;
|
||||
wchar_t *path_cpy;
|
||||
wchar_t *nxt_path;
|
||||
wchar_t *state;
|
||||
wchar_t *whole_path;
|
||||
|
||||
if( path == 0 )
|
||||
path = env_get(L"CDPATH");
|
||||
|
||||
if( !path || !wcslen(path) )
|
||||
{
|
||||
path = L".";
|
||||
}
|
||||
|
||||
wchar_t *path_cpy = wcsdup( path );
|
||||
wchar_t *nxt_path = path;
|
||||
wchar_t *state;
|
||||
wchar_t *whole_path;
|
||||
|
||||
if( (path_cpy==0) )
|
||||
nxt_path = path;
|
||||
path_cpy = wcsdup( path );
|
||||
|
||||
if( !path_cpy )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
@@ -586,6 +639,8 @@ wchar_t *get_filename( const wchar_t *cmd )
|
||||
{
|
||||
wchar_t *path;
|
||||
|
||||
debug( 2, L"get_filename( '%ls' )", cmd );
|
||||
|
||||
if(wcschr( cmd, '/' ) != 0 )
|
||||
{
|
||||
if( waccess( cmd, X_OK )==0 )
|
||||
@@ -658,7 +713,7 @@ wchar_t *get_filename( const wchar_t *cmd )
|
||||
break;
|
||||
default:
|
||||
debug( 1,
|
||||
L"Error while searching for command %d",
|
||||
L"Error while searching for command %ls",
|
||||
new_cmd );
|
||||
wperror( L"access" );
|
||||
}
|
||||
@@ -763,13 +818,6 @@ static void print_errors()
|
||||
{
|
||||
int tmp;
|
||||
|
||||
/*
|
||||
Wildcard warnings are only printed in interactive mode
|
||||
*/
|
||||
if( ( error_code == WILDCARD_ERROR ) && !is_interactive )
|
||||
return;
|
||||
|
||||
|
||||
debug( 0, L"%ls", err_str );
|
||||
|
||||
tmp = current_tokenizer_pos;
|
||||
@@ -837,7 +885,7 @@ int eval_args( const wchar_t *line, array_list_t *args )
|
||||
default:
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
L"Unexpected token of type %ls",
|
||||
UNEXPECTED_TOKEN_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(&tok)) );
|
||||
|
||||
do_loop=0;
|
||||
@@ -894,7 +942,7 @@ wchar_t *parser_current_line()
|
||||
|
||||
line = wcsndup( line, line_end-line );
|
||||
|
||||
// debug( 2, L"Current pos %d, line pos %d, file_length %d\n", current_tokenizer_pos, current_line_pos, wcslen(whole_str));
|
||||
debug( 4, L"Current pos %d, line pos %d, file_length %d\n", current_tokenizer_pos, current_line_pos, wcslen(whole_str));
|
||||
|
||||
if( !is_interactive )
|
||||
{
|
||||
@@ -910,7 +958,10 @@ wchar_t *parser_current_line()
|
||||
offset=0;
|
||||
}
|
||||
|
||||
/* Skip printing if we are in interactive mode and the error was on the first character of the line */
|
||||
/*
|
||||
Skip printing character position if we are in interactive mode
|
||||
and the error was on the first character of the line
|
||||
*/
|
||||
if( offset+current_line_pos )
|
||||
swprintf( lineinfo+offset,
|
||||
LINEINFO_SIZE-offset,
|
||||
@@ -1083,7 +1134,7 @@ static void parse_job_main_loop( process_t *p,
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Could not expand string",
|
||||
L"Could not expand string '%ls'",
|
||||
tok_last(tok) );
|
||||
|
||||
}
|
||||
@@ -1129,16 +1180,23 @@ static void parse_job_main_loop( process_t *p,
|
||||
io_data_t *new_io;
|
||||
wchar_t *target = 0;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Don't check redirections in skipped part
|
||||
|
||||
Otherwise, bogus errors may be the result
|
||||
Otherwise, bogus errors may be the result. (Do check
|
||||
that token is string, though)
|
||||
*/
|
||||
if( current_block->skip )
|
||||
{
|
||||
tok_next( tok );
|
||||
if( tok_last_type( tok ) != TOK_STRING )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
REDIRECT_TOKEN_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(tok)) );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1160,7 +1218,7 @@ static void parse_job_main_loop( process_t *p,
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Could not expand string %ls",
|
||||
REDIRECT_TOKEN_ERR_MSG,
|
||||
tok_last( tok ) );
|
||||
|
||||
}
|
||||
@@ -1169,7 +1227,7 @@ static void parse_job_main_loop( process_t *p,
|
||||
default:
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Expected redirection, got token of type %ls",
|
||||
REDIRECT_TOKEN_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(tok)) );
|
||||
}
|
||||
|
||||
@@ -1214,8 +1272,8 @@ static void parse_job_main_loop( process_t *p,
|
||||
{
|
||||
new_io->io_mode = IO_FD;
|
||||
new_io->param1.old_fd = wcstol( target,
|
||||
0,
|
||||
10 );
|
||||
0,
|
||||
10 );
|
||||
if( ( new_io->param1.old_fd < 0 ) ||
|
||||
( new_io->param1.old_fd > 10 ) )
|
||||
{
|
||||
@@ -1251,7 +1309,7 @@ static void parse_job_main_loop( process_t *p,
|
||||
default:
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Unexpected token of type %ls",
|
||||
UNEXPECTED_TOKEN_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(tok)) );
|
||||
|
||||
tok_next(tok);
|
||||
@@ -1268,11 +1326,21 @@ static void parse_job_main_loop( process_t *p,
|
||||
{
|
||||
if( unmatched_wildcard && !matched_wildcard )
|
||||
{
|
||||
error( WILDCARD_ERROR,
|
||||
unmatched_pos,
|
||||
WILDCARD_ERR_MSG,
|
||||
unmatched );
|
||||
|
||||
j->wildcard_error = 1;
|
||||
proc_set_last_status( 1 );
|
||||
if( is_interactive && !is_block )
|
||||
{
|
||||
int tmp;
|
||||
|
||||
debug( 1, WILDCARD_ERR_MSG, unmatched );
|
||||
tmp = current_tokenizer_pos;
|
||||
current_tokenizer_pos = unmatched_pos;
|
||||
|
||||
fwprintf( stderr, L"%ls", parser_current_line() );
|
||||
|
||||
current_tokenizer_pos=tmp;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
free( unmatched );
|
||||
@@ -1301,7 +1369,7 @@ static int parse_job( process_t *p,
|
||||
|
||||
block_t *prev_block = current_block;
|
||||
|
||||
// debug( 2, L"begin parse_job()\n" );
|
||||
debug( 2, L"begin parse_job()\n" );
|
||||
al_init( &args );
|
||||
|
||||
current_tokenizer_pos = tok_get_pos( tok );
|
||||
@@ -1315,11 +1383,13 @@ static int parse_job( process_t *p,
|
||||
{
|
||||
nxt = expand_one( wcsdup(tok_last( tok )),
|
||||
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
|
||||
debug( 2, L"command '%ls' -> '%ls'", tok_last( tok ), nxt?nxt:L"0" );
|
||||
|
||||
if( nxt == 0 )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Illegal command name %ls",
|
||||
ILLEGAL_CMD_ERR_MSG,
|
||||
tok_last( tok ) );
|
||||
|
||||
al_destroy( &args );
|
||||
@@ -1343,7 +1413,7 @@ static int parse_job( process_t *p,
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Expected a command name, got token of type %ls",
|
||||
CMD_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(tok) ) );
|
||||
|
||||
al_destroy( &args );
|
||||
@@ -1552,6 +1622,9 @@ static int parse_job( process_t *p,
|
||||
{
|
||||
|
||||
p->actual_cmd = get_filename( (wchar_t *)al_get( &args, 0 ) );
|
||||
|
||||
debug( 2, L"filename '%ls' -> '%ls'", (wchar_t *)al_get( &args, 0 ), p->actual_cmd?p->actual_cmd:L"0" );
|
||||
|
||||
/*
|
||||
Check if the specified command exists
|
||||
*/
|
||||
@@ -1598,7 +1671,7 @@ static int parse_job( process_t *p,
|
||||
{
|
||||
error( EVAL_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Unknown command %ls",
|
||||
L"Unknown command '%ls'",
|
||||
(wchar_t *)al_get( &args, 0 ) );
|
||||
|
||||
}
|
||||
@@ -1619,7 +1692,7 @@ static int parse_job( process_t *p,
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Could not find end of block" );
|
||||
BLOCK_END_ERR_MSG );
|
||||
}
|
||||
|
||||
if( !make_sub_block )
|
||||
@@ -1665,7 +1738,10 @@ static int parse_job( process_t *p,
|
||||
end_pos );
|
||||
|
||||
while( prev_block != current_block )
|
||||
{
|
||||
parser_pop_block();
|
||||
}
|
||||
|
||||
}
|
||||
else tok_next( tok );
|
||||
|
||||
@@ -1699,8 +1775,10 @@ static int parse_job( process_t *p,
|
||||
Make sure the block stack is consistent
|
||||
*/
|
||||
while( prev_block != current_block )
|
||||
{
|
||||
parser_pop_block();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
al_destroy( &args );
|
||||
|
||||
@@ -1719,12 +1797,14 @@ static int parse_job( process_t *p,
|
||||
static void skipped_exec( job_t * j )
|
||||
{
|
||||
process_t *p;
|
||||
|
||||
for( p = j->first_process; p; p=p->next )
|
||||
{
|
||||
if( p->type )
|
||||
if( p->type == INTERNAL_BUILTIN )
|
||||
{
|
||||
if(( wcscmp( p->argv[0], L"for" )==0) ||
|
||||
( wcscmp( p->argv[0], L"switch" )==0) ||
|
||||
( wcscmp( p->argv[0], L"begin" )==0) ||
|
||||
( wcscmp( p->argv[0], L"function" )==0))
|
||||
{
|
||||
parser_push_block( FAKE );
|
||||
@@ -1850,6 +1930,7 @@ static void eval_job( tokenizer *tok )
|
||||
}
|
||||
|
||||
skip |= current_block->skip;
|
||||
skip |= j->wildcard_error;
|
||||
|
||||
if(!skip )
|
||||
{
|
||||
@@ -1935,7 +2016,7 @@ static void eval_job( tokenizer *tok )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( tok ),
|
||||
L"Expected a command string, got token of type %ls",
|
||||
CMD_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(tok)) );
|
||||
|
||||
return;
|
||||
@@ -1956,9 +2037,10 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||
io_data_t *prev_io = block_io;
|
||||
block_io = io;
|
||||
|
||||
debug( 2, L"Eval command %ls", cmd );
|
||||
|
||||
job_reap( 0 );
|
||||
|
||||
debug( 4, L"eval: %ls", cmd );
|
||||
|
||||
|
||||
if( !cmd )
|
||||
{
|
||||
@@ -1976,8 +2058,8 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||
L"Tried to evaluate buffer using invalid block scope of type '%ls'. " BUGREPORT_MSG,
|
||||
parser_get_block_desc( block_type ),
|
||||
PACKAGE_BUGREPORT );
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
eval_level++;
|
||||
current_tokenizer = malloc( sizeof(tokenizer));
|
||||
@@ -1989,7 +2071,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||
tok_init( current_tokenizer, cmd, 0 );
|
||||
error_code = 0;
|
||||
|
||||
event_fire( 0, 0 );
|
||||
event_fire( 0 );
|
||||
|
||||
while( tok_has_next( current_tokenizer ) &&
|
||||
!error_code &&
|
||||
@@ -1997,10 +2079,11 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||
!exit_status() )
|
||||
{
|
||||
eval_job( current_tokenizer );
|
||||
event_fire( 0, 0 );
|
||||
event_fire( 0 );
|
||||
}
|
||||
|
||||
int prev_block_type = current_block->type;
|
||||
|
||||
parser_pop_block();
|
||||
|
||||
while( start_current_block != current_block )
|
||||
@@ -2039,7 +2122,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
|
||||
debug( 1,
|
||||
L"%ls", parser_get_block_desc( current_block->type ) );
|
||||
debug( 1,
|
||||
END_ERR_MSG );
|
||||
BLOCK_END_ERR_MSG );
|
||||
fwprintf( stderr, L"%ls", parser_current_line() );
|
||||
|
||||
h = builtin_help_get( L"end" );
|
||||
@@ -2250,15 +2333,15 @@ int parser_test( wchar_t * buff,
|
||||
// debug( 2, L"Error on block type %d\n", block_type[count-1] );
|
||||
|
||||
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
L"'case' builtin not inside of switch block" );
|
||||
|
||||
print_errors();
|
||||
}
|
||||
}
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
INVALID_CASE_ERR_MSG );
|
||||
|
||||
print_errors();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2283,14 +2366,14 @@ int parser_test( wchar_t * buff,
|
||||
{
|
||||
err=1;
|
||||
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
L"Loop control command while not inside of loop" );
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
INVALID_LOOP_ERR_MSG );
|
||||
print_errors();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2299,16 +2382,17 @@ int parser_test( wchar_t * buff,
|
||||
if( wcscmp( L"else", tok_last( &tok ) )==0 )
|
||||
{
|
||||
if( !count || block_type[count-1]!=IF )
|
||||
{
|
||||
err=1;
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
L"'else' builtin not inside of if block" );
|
||||
{
|
||||
err=1;
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
INVALID_ELSE_ERR_MSG );
|
||||
|
||||
print_errors();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2322,7 +2406,7 @@ int parser_test( wchar_t * buff,
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
L"'end' command outside of block" );
|
||||
INVALID_END_ERR_MSG );
|
||||
print_errors();
|
||||
}
|
||||
}
|
||||
@@ -2342,7 +2426,7 @@ int parser_test( wchar_t * buff,
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
L"Redirection error" );
|
||||
INVALID_REDIRECTION_ERR_MSG );
|
||||
print_errors();
|
||||
}
|
||||
}
|
||||
@@ -2354,13 +2438,14 @@ int parser_test( wchar_t * buff,
|
||||
if( needs_cmd && !had_cmd )
|
||||
{
|
||||
err = 1;
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
CMD_ERR_MSG );
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
CMD_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(&tok)));
|
||||
print_errors();
|
||||
}
|
||||
}
|
||||
}
|
||||
needs_cmd=0;
|
||||
had_cmd = 0;
|
||||
@@ -2393,14 +2478,15 @@ int parser_test( wchar_t * buff,
|
||||
if( needs_cmd && !had_cmd )
|
||||
{
|
||||
err = 1;
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
CMD_ERR_MSG );
|
||||
if( babble )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
tok_get_pos( &tok ),
|
||||
CMD_ERR_MSG,
|
||||
tok_get_desc( tok_last_type(&tok)));
|
||||
|
||||
print_errors();
|
||||
}
|
||||
print_errors();
|
||||
}
|
||||
}
|
||||
|
||||
if( had_cmd )
|
||||
@@ -2446,7 +2532,7 @@ int parser_test( wchar_t * buff,
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
block_pos[count-1],
|
||||
END_ERR_MSG );
|
||||
BLOCK_END_ERR_MSG );
|
||||
print_errors();
|
||||
}
|
||||
|
||||
|
||||
52
parser.h
52
parser.h
@@ -11,6 +11,27 @@
|
||||
#include "util.h"
|
||||
#include "parser.h"
|
||||
|
||||
typedef struct event_block
|
||||
{
|
||||
/**
|
||||
The types of events to block. This is interpreted as a bitset
|
||||
whete the value is 1 for every bit corresponding to a blocked
|
||||
event type. For example, if EVENT_VARIABLE type events should
|
||||
be blocked, (type & 1<<EVENT_BLOCKED) should be set.
|
||||
|
||||
Note that EVENT_ANY can be used to specify any event.
|
||||
*/
|
||||
int type;
|
||||
|
||||
/**
|
||||
The next event_block struct
|
||||
*/
|
||||
struct event_block *next;
|
||||
}
|
||||
event_block_t;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
block_t represents a block of commands.
|
||||
*/
|
||||
@@ -21,12 +42,12 @@ typedef struct block
|
||||
int tok_pos; /**< The start index of the block */
|
||||
|
||||
/**
|
||||
Status for the current loop block. Can be anu of the values from the loop_status enum.
|
||||
Status for the current loop block. Can be any of the values from the loop_status enum.
|
||||
*/
|
||||
int loop_status;
|
||||
|
||||
/**
|
||||
The log that is currently evaluated in the specified block.
|
||||
The job that is currently evaluated in the specified block.
|
||||
*/
|
||||
job_t *job;
|
||||
|
||||
@@ -68,8 +89,11 @@ typedef struct block
|
||||
array_list_t *function_events;
|
||||
} param4;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Some naming confusion. This is a pointer to the first element in the list of all event blocks.
|
||||
*/
|
||||
event_block_t *first_event_block;
|
||||
|
||||
/**
|
||||
Next outer block
|
||||
*/
|
||||
@@ -137,28 +161,20 @@ enum parser_error
|
||||
Error occured while evaluating commands
|
||||
*/
|
||||
EVAL_ERROR,
|
||||
/**
|
||||
Out of memory error
|
||||
*/
|
||||
OOM,
|
||||
/**
|
||||
Stack inconsistency error
|
||||
*/
|
||||
STACK_ERROR,
|
||||
/**
|
||||
Error while evaluating subshell
|
||||
*/
|
||||
SUBSHELL_ERROR,
|
||||
/**
|
||||
No files matching wildcards where found
|
||||
*/
|
||||
WILDCARD_ERROR
|
||||
}
|
||||
;
|
||||
|
||||
/** The current innermost block */
|
||||
extern block_t *current_block;
|
||||
|
||||
/** Global event blocks */
|
||||
extern event_block_t *global_event_block;
|
||||
|
||||
|
||||
/** The current error code */
|
||||
extern int error_code;
|
||||
|
||||
@@ -297,12 +313,12 @@ void parser_forbid_function( wchar_t *function );
|
||||
void parser_allow_function();
|
||||
|
||||
/**
|
||||
Initialize the parser
|
||||
Initialize static parser data
|
||||
*/
|
||||
void parser_init();
|
||||
|
||||
/**
|
||||
Destroy the parser
|
||||
Destroy static parser data
|
||||
*/
|
||||
void parser_destroy();
|
||||
|
||||
|
||||
25
proc.c
25
proc.c
@@ -76,9 +76,10 @@ int proc_had_barrier;
|
||||
pid_t proc_last_bg_pid = 0;
|
||||
|
||||
/**
|
||||
List used to store arguments when firing events
|
||||
The event variable used to send all process event
|
||||
*/
|
||||
static array_list_t event_arg;
|
||||
static event_t event;
|
||||
|
||||
/**
|
||||
Stringbuffer used to create arguments when firing events
|
||||
*/
|
||||
@@ -91,7 +92,7 @@ static string_buffer_t event_status;
|
||||
|
||||
void proc_init()
|
||||
{
|
||||
al_init( &event_arg );
|
||||
al_init( &event.arguments );
|
||||
sb_init( &event_pid );
|
||||
sb_init( &event_status );
|
||||
}
|
||||
@@ -185,7 +186,7 @@ void job_free( job_t * j )
|
||||
|
||||
void proc_destroy()
|
||||
{
|
||||
al_destroy( &event_arg );
|
||||
al_destroy( &event.arguments );
|
||||
sb_destroy( &event_pid );
|
||||
sb_destroy( &event_status );
|
||||
while( first_job )
|
||||
@@ -484,21 +485,21 @@ static void format_job_info( const job_t *j, const wchar_t *status )
|
||||
|
||||
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status )
|
||||
{
|
||||
static event_t ev;
|
||||
|
||||
ev.type=type;
|
||||
ev.param1.pid = pid;
|
||||
event.type=type;
|
||||
event.param1.pid = pid;
|
||||
|
||||
al_push( &event_arg, msg );
|
||||
al_push( &event.arguments, msg );
|
||||
|
||||
sb_printf( &event_pid, L"%d", pid );
|
||||
al_push( &event_arg, event_pid.buff );
|
||||
al_push( &event.arguments, event_pid.buff );
|
||||
|
||||
sb_printf( &event_status, L"%d", status );
|
||||
al_push( &event_arg, event_status.buff );
|
||||
al_push( &event.arguments, event_status.buff );
|
||||
|
||||
event_fire( &ev, &event_arg );
|
||||
al_truncate( &event_arg, 0 );
|
||||
event_fire( &event );
|
||||
|
||||
al_truncate( &event.arguments, 0 );
|
||||
sb_clear( &event_pid );
|
||||
sb_clear( &event_status );
|
||||
}
|
||||
|
||||
61
proc.h
61
proc.h
@@ -20,15 +20,30 @@
|
||||
|
||||
|
||||
/**
|
||||
Types of internal processes
|
||||
Types of processes
|
||||
*/
|
||||
enum
|
||||
{
|
||||
/**
|
||||
A regular external command
|
||||
*/
|
||||
EXTERNAL,
|
||||
/**
|
||||
A builtin command
|
||||
*/
|
||||
INTERNAL_BUILTIN,
|
||||
/**
|
||||
A shellscript function
|
||||
*/
|
||||
INTERNAL_FUNCTION,
|
||||
/**
|
||||
A block of commands
|
||||
*/
|
||||
INTERNAL_BLOCK,
|
||||
INTERNAL_EXEC
|
||||
/**
|
||||
The exec builtin
|
||||
*/
|
||||
INTERNAL_EXEC,
|
||||
}
|
||||
;
|
||||
|
||||
@@ -134,24 +149,47 @@ typedef struct job
|
||||
/** Should the exit status be negated? This flag can only be set by the not builtin. */
|
||||
int negate;
|
||||
|
||||
/** This flag is set to one on wildcard expansion errors. It means that the current command should not be executed */
|
||||
int wildcard_error;
|
||||
|
||||
/** Pointer to the next job */
|
||||
struct job *next;
|
||||
}
|
||||
job_t;
|
||||
|
||||
/** Whether we are running a subshell command */
|
||||
/**
|
||||
Whether we are running a subshell command
|
||||
*/
|
||||
extern int is_subshell;
|
||||
/** Whether we are running a block of commands */
|
||||
|
||||
/**
|
||||
Whether we are running a block of commands
|
||||
*/
|
||||
extern int is_block;
|
||||
/** Whether we are reading from the keyboard right now*/
|
||||
|
||||
/**
|
||||
Whether we are reading from the keyboard right now
|
||||
*/
|
||||
extern int is_interactive;
|
||||
/** Whether this shell is attached to the keyboard at all*/
|
||||
|
||||
/**
|
||||
Whether this shell is attached to the keyboard at all
|
||||
*/
|
||||
extern int is_interactive_session;
|
||||
/** Whether we are a login shell*/
|
||||
|
||||
/**
|
||||
Whether we are a login shell
|
||||
*/
|
||||
extern int is_login;
|
||||
/** Whether we are a event handler*/
|
||||
|
||||
/**
|
||||
Whether we are a event handler
|
||||
*/
|
||||
extern int is_event;
|
||||
/** Linked list of all jobs */
|
||||
|
||||
/**
|
||||
Linked list of all jobs
|
||||
*/
|
||||
extern job_t *first_job;
|
||||
|
||||
/**
|
||||
@@ -172,6 +210,7 @@ extern pid_t proc_last_bg_pid;
|
||||
Sets the status of the last process to exit
|
||||
*/
|
||||
void proc_set_last_status( int s );
|
||||
|
||||
/**
|
||||
Returns the status of the last process to exit
|
||||
*/
|
||||
@@ -181,6 +220,7 @@ int proc_get_last_status();
|
||||
Remove the specified job
|
||||
*/
|
||||
void job_free( job_t* j );
|
||||
|
||||
/**
|
||||
Create a new job
|
||||
*/
|
||||
@@ -216,6 +256,7 @@ int job_is_completed( const job_t *j );
|
||||
\param cont Whether the function should wait for the job to complete before returning
|
||||
*/
|
||||
void job_continue( job_t *j, int cont );
|
||||
|
||||
/**
|
||||
Notify user of nog events. Notify the user about stopped or
|
||||
terminated jobs. Delete terminated jobs from the active job list.
|
||||
@@ -223,10 +264,10 @@ void job_continue( job_t *j, int cont );
|
||||
\param interactive whether interactive jobs should be reaped as well
|
||||
*/
|
||||
int job_reap( int interactive );
|
||||
|
||||
/**
|
||||
Signal handler for SIGCHLD. Mark any processes with relevant
|
||||
information.
|
||||
|
||||
*/
|
||||
void job_handle_signal( int signal, siginfo_t *info, void *con );
|
||||
|
||||
|
||||
220
reader.c
220
reader.c
@@ -52,6 +52,8 @@ commence.
|
||||
#include <time.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "wutil.h"
|
||||
#include "highlight.h"
|
||||
@@ -620,6 +622,129 @@ void reader_write_title()
|
||||
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
|
||||
}
|
||||
|
||||
/**
|
||||
Tests if the specified narrow character sequence is present at the
|
||||
specified position of the specified wide character string. All of
|
||||
\c seq must match, but str may be longer than seq.
|
||||
*/
|
||||
static int try_sequence( char *seq, wchar_t *str )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0;; i++ )
|
||||
{
|
||||
if( !seq[i] )
|
||||
return i;
|
||||
|
||||
if( seq[i] != str[i] )
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Calculate the width of the specified prompt. Does some clever magic
|
||||
to detect common escape sequences that may be embeded in a prompt,
|
||||
such as color codes.
|
||||
*/
|
||||
static int calc_prompt_width( array_list_t *arr )
|
||||
{
|
||||
int res = 0;
|
||||
int i, j, k;
|
||||
|
||||
for( i=0; i<al_get_count( arr ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( arr, i );
|
||||
|
||||
for( j=0; next[j]; j++ )
|
||||
{
|
||||
if( next[j] == L'\e' )
|
||||
{
|
||||
/*
|
||||
This is the start of an escape code. Try to guess it's width.
|
||||
*/
|
||||
int l;
|
||||
int len=0;
|
||||
int found = 0;
|
||||
|
||||
/*
|
||||
Test these color escapes with parameter value 0..7
|
||||
*/
|
||||
char * esc[] =
|
||||
{
|
||||
set_a_foreground,
|
||||
set_a_background,
|
||||
set_foreground,
|
||||
set_background,
|
||||
}
|
||||
;
|
||||
|
||||
/*
|
||||
Test these regular escapes without any parameter values
|
||||
*/
|
||||
char *esc2[] =
|
||||
{
|
||||
enter_bold_mode,
|
||||
exit_attribute_mode,
|
||||
enter_underline_mode,
|
||||
exit_underline_mode,
|
||||
enter_standout_mode,
|
||||
exit_standout_mode,
|
||||
flash_screen
|
||||
}
|
||||
;
|
||||
|
||||
for( l=0; l < (sizeof(esc)/sizeof(char *)) && !found; l++ )
|
||||
{
|
||||
if( !esc[l] )
|
||||
continue;
|
||||
|
||||
for( k=0; k<8; k++ )
|
||||
{
|
||||
len = try_sequence( tparm(esc[l],k), &next[j] );
|
||||
if( len )
|
||||
{
|
||||
j += (len-1);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for( l=0; l < (sizeof(esc2)/sizeof(char *)) && !found; l++ )
|
||||
{
|
||||
if( !esc2[l] )
|
||||
continue;
|
||||
/*
|
||||
Test both padded and unpadded version, just to
|
||||
be safe. Most versions of tparm don't actually
|
||||
seem to do anything these days.
|
||||
*/
|
||||
len = maxi( try_sequence( tparm(esc2[l]), &next[j] ),
|
||||
try_sequence( esc2[l], &next[j] ));
|
||||
|
||||
if( len )
|
||||
{
|
||||
j += (len-1);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Ordinary decent character. Just add width.
|
||||
*/
|
||||
res += wcwidth( next[j] );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Write the prompt to screen. If data->exec_prompt is set, the prompt
|
||||
command is first evaluated, and the title will be reexecuted as
|
||||
@@ -649,14 +774,8 @@ static void write_prompt()
|
||||
al_init( &prompt_list );
|
||||
}
|
||||
}
|
||||
data->prompt_width=0;
|
||||
for( i=0; i<al_get_count( &prompt_list ); i++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &prompt_list, i );
|
||||
if( *next == L'\e' )
|
||||
continue;
|
||||
data->prompt_width += my_wcswidth( next );
|
||||
}
|
||||
|
||||
data->prompt_width=calc_prompt_width( &prompt_list );
|
||||
|
||||
data->exec_prompt = 0;
|
||||
reader_write_title();
|
||||
@@ -1382,8 +1501,8 @@ static int handle_completions( array_list_t *comp )
|
||||
0,
|
||||
0 );
|
||||
|
||||
len = &data->buff[data->buff_pos]-prefix_start;
|
||||
|
||||
len = &data->buff[data->buff_pos]-prefix_start+1;
|
||||
|
||||
if( len <= PREFIX_MAX_LEN )
|
||||
{
|
||||
prefix = malloc( sizeof(wchar_t)*(len+1) );
|
||||
@@ -1400,7 +1519,7 @@ static int handle_completions( array_list_t *comp )
|
||||
;
|
||||
|
||||
prefix = wcsdupcat( tmp,
|
||||
prefix_start + (len - PREFIX_MAX_LEN+1) );
|
||||
prefix_start + (len - PREFIX_MAX_LEN) );
|
||||
prefix[PREFIX_MAX_LEN] = 0;
|
||||
|
||||
}
|
||||
@@ -1712,8 +1831,6 @@ void reader_current_token_extent( wchar_t **tok_begin,
|
||||
|
||||
reader_current_subshell_extent( &begin, &end );
|
||||
|
||||
// fwprintf( stderr, L"Lalala: %d %d %d\n", begin-data->buff, end-data->buff, pos );
|
||||
|
||||
if( !end || !begin )
|
||||
return;
|
||||
|
||||
@@ -1724,6 +1841,11 @@ void reader_current_token_extent( wchar_t **tok_begin,
|
||||
pa = data->buff + pos;
|
||||
pb = pa;
|
||||
|
||||
assert( begin >= data->buff );
|
||||
assert( begin <= (data->buff+wcslen(data->buff) ) );
|
||||
assert( end >= begin );
|
||||
assert( end <= (data->buff+wcslen(data->buff) ) );
|
||||
|
||||
buffcpy = wcsndup( begin, end-begin );
|
||||
|
||||
if( !buffcpy )
|
||||
@@ -1738,15 +1860,27 @@ void reader_current_token_extent( wchar_t **tok_begin,
|
||||
int tok_begin = tok_get_pos( &tok );
|
||||
int tok_end=tok_begin;
|
||||
|
||||
/*
|
||||
Calculate end of token
|
||||
*/
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
tok_end +=wcslen(tok_last(&tok));
|
||||
|
||||
|
||||
/*
|
||||
Cursor was before beginning of this token, means that the
|
||||
cursor is between two tokens, so we set it to a zero element
|
||||
string and break
|
||||
*/
|
||||
if( tok_begin > pos )
|
||||
{
|
||||
a = b = data->buff + pos;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
If cursor is inside the token, this is the token we are
|
||||
looking for. If so, set a and b and break
|
||||
*/
|
||||
if( tok_end >= pos )
|
||||
{
|
||||
a = begin + tok_get_pos( &tok );
|
||||
@@ -1756,11 +1890,17 @@ void reader_current_token_extent( wchar_t **tok_begin,
|
||||
|
||||
break;
|
||||
}
|
||||
pa = begin + tok_get_pos( &tok );
|
||||
pb = pa + wcslen(tok_last(&tok));
|
||||
|
||||
/*
|
||||
Remember previous string token
|
||||
*/
|
||||
if( tok_last_type( &tok ) == TOK_STRING )
|
||||
{
|
||||
pa = begin + tok_get_pos( &tok );
|
||||
pb = pa + wcslen(tok_last(&tok));
|
||||
}
|
||||
}
|
||||
|
||||
// fwprintf( stderr, L"Res: %d %d\n", *a-data->buff, *b-data->buff );
|
||||
free( buffcpy);
|
||||
|
||||
tok_destroy( &tok );
|
||||
@@ -1774,7 +1914,10 @@ void reader_current_token_extent( wchar_t **tok_begin,
|
||||
if( prev_end )
|
||||
*prev_end = pb;
|
||||
|
||||
// fwprintf( stderr, L"w00t\n" );
|
||||
assert( pa >= data->buff );
|
||||
assert( pa <= (data->buff+wcslen(data->buff) ) );
|
||||
assert( pb >= pa );
|
||||
assert( pb <= (data->buff+wcslen(data->buff) ) );
|
||||
|
||||
}
|
||||
|
||||
@@ -1876,7 +2019,7 @@ static void handle_token_history( int forward, int reset )
|
||||
int current_pos;
|
||||
tokenizer tok;
|
||||
|
||||
if(reset )
|
||||
if( reset )
|
||||
{
|
||||
/*
|
||||
Start a new token search using the current token
|
||||
@@ -1885,6 +2028,7 @@ static void handle_token_history( int forward, int reset )
|
||||
|
||||
}
|
||||
|
||||
|
||||
current_pos = data->token_history_pos;
|
||||
|
||||
if( forward || data->search_pos < (al_get_count( &data->search_prev )-1) )
|
||||
@@ -1926,6 +2070,7 @@ static void handle_token_history( int forward, int reset )
|
||||
history already contains the search string itself, if so
|
||||
return, otherwise add it.
|
||||
*/
|
||||
|
||||
const wchar_t *last = al_get( &data->search_prev, al_get_count( &data->search_prev ) -1 );
|
||||
if( wcscmp( last, data->search_buff ) )
|
||||
{
|
||||
@@ -1938,6 +2083,9 @@ static void handle_token_history( int forward, int reset )
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
debug( 3, L"new '%ls'", data->token_history_buff );
|
||||
|
||||
for( tok_init( &tok, data->token_history_buff, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok);
|
||||
tok_next( &tok ))
|
||||
@@ -1948,11 +2096,12 @@ static void handle_token_history( int forward, int reset )
|
||||
{
|
||||
if( wcsstr( tok_last( &tok ), data->search_buff ) )
|
||||
{
|
||||
// fwprintf( stderr, L"Found token at pos %d\n", tok_get_pos( &tok ) );
|
||||
debug( 3, L"Found token at pos %d\n", tok_get_pos( &tok ) );
|
||||
if( tok_get_pos( &tok ) >= current_pos )
|
||||
{
|
||||
break;
|
||||
}
|
||||
debug( 3, L"ok pos" );
|
||||
|
||||
if( !contains( tok_last( &tok ), &data->search_prev ) )
|
||||
{
|
||||
@@ -2499,9 +2648,7 @@ wchar_t *reader_readline()
|
||||
if( last_char != R_YANK && last_char != R_YANK_POP )
|
||||
yank=0;
|
||||
|
||||
|
||||
|
||||
switch (c)
|
||||
switch( c )
|
||||
{
|
||||
|
||||
/* go to beginning of line*/
|
||||
@@ -2586,10 +2733,13 @@ wchar_t *reader_readline()
|
||||
|
||||
case R_BACKWARD_KILL_LINE:
|
||||
{
|
||||
wchar_t prev = data->buff[data->buff_pos];
|
||||
data->buff[data->buff_pos]=0;
|
||||
kill_add( data->buff );
|
||||
data->buff[data->buff_pos]=prev;
|
||||
wchar_t *str = wcsndup( data->buff, data->buff_pos );
|
||||
if( !str )
|
||||
die_mem();
|
||||
|
||||
kill_add( str );
|
||||
free( str );
|
||||
|
||||
data->buff_len = wcslen(data->buff +data->buff_pos);
|
||||
memmove( data->buff, data->buff +data->buff_pos, sizeof(wchar_t)*data->buff_len );
|
||||
data->buff[data->buff_len]=L'\0';
|
||||
@@ -2909,7 +3059,21 @@ static int read_ni( int fd )
|
||||
while(!feof( in_stream ))
|
||||
{
|
||||
char buff[4096];
|
||||
int c = fread(buff, 1, 4096, in_stream);
|
||||
int c;
|
||||
|
||||
c = fread(buff, 1, 4096, in_stream);
|
||||
if( ferror( in_stream ) )
|
||||
{
|
||||
debug( 1,
|
||||
L"Error while reading commands" );
|
||||
|
||||
/*
|
||||
Reset buffer. We won't evaluate incomplete files.
|
||||
*/
|
||||
acc.used=0;
|
||||
break;
|
||||
}
|
||||
|
||||
b_append( &acc, buff, c );
|
||||
}
|
||||
b_append( &acc, "\0", 1 );
|
||||
|
||||
2
signal.c
2
signal.c
@@ -305,7 +305,7 @@ static void default_handler(int signal, siginfo_t *info, void *context)
|
||||
e.param1.signal = signal;
|
||||
e.function_name=0;
|
||||
|
||||
event_fire( &e, 0 );
|
||||
event_fire( &e );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
26
tokenizer.c
26
tokenizer.c
@@ -119,12 +119,9 @@ void tok_init( tokenizer *tok, const wchar_t *b, int flags )
|
||||
|
||||
memset( tok, 0, sizeof( tokenizer) );
|
||||
|
||||
tok ->last = 0;
|
||||
tok ->last_len = 0;
|
||||
tok->accept_unfinished = flags & TOK_ACCEPT_UNFINISHED;
|
||||
tok->show_comments = flags & TOK_SHOW_COMMENTS;
|
||||
tok->has_next=1;
|
||||
|
||||
tok->has_next=1;
|
||||
|
||||
/*
|
||||
Before we copy the buffer we need to check that it is not
|
||||
@@ -138,13 +135,7 @@ void tok_init( tokenizer *tok, const wchar_t *b, int flags )
|
||||
}
|
||||
|
||||
tok->has_next = (*b != L'\0');
|
||||
tok->orig_buff = tok->buff = /*wcsdup*/(b);
|
||||
|
||||
if( !tok->orig_buff )
|
||||
{
|
||||
die_mem();
|
||||
|
||||
}
|
||||
tok->orig_buff = tok->buff = (wchar_t *)(b);
|
||||
|
||||
if( tok->accept_unfinished )
|
||||
{
|
||||
@@ -152,7 +143,15 @@ void tok_init( tokenizer *tok, const wchar_t *b, int flags )
|
||||
if( l != 0 )
|
||||
{
|
||||
if( tok->orig_buff[l-1] == L'\\' )
|
||||
{
|
||||
tok->free_orig = 1;
|
||||
tok->orig_buff = tok->buff = wcsdup( tok->orig_buff );
|
||||
if( !tok->orig_buff )
|
||||
{
|
||||
die_mem();
|
||||
}
|
||||
tok->orig_buff[l-1] = L'\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +162,8 @@ void tok_init( tokenizer *tok, const wchar_t *b, int flags )
|
||||
void tok_destroy( tokenizer *tok )
|
||||
{
|
||||
free( tok->last );
|
||||
// free( tok->orig_buff );
|
||||
if( tok->free_orig )
|
||||
free( tok->orig_buff );
|
||||
}
|
||||
|
||||
int tok_last_type( tokenizer *tok )
|
||||
@@ -619,7 +619,7 @@ wchar_t *tok_first( const wchar_t *str )
|
||||
|
||||
int tok_get_pos( tokenizer *tok )
|
||||
{
|
||||
return tok->last_pos;
|
||||
return tok->last_pos + (tok->free_orig?1:0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@ typedef struct
|
||||
int accept_unfinished;
|
||||
/** Whether commants should be returned*/
|
||||
int show_comments;
|
||||
/** Flag set to true of the orig_buff points to an internal string that needs to be free()d when deallocating the tokenizer. */
|
||||
int free_orig;
|
||||
/** Type of last quote, can be either ' or ".*/
|
||||
wchar_t last_quote;
|
||||
}
|
||||
|
||||
@@ -317,8 +317,11 @@ static int test_flags( wchar_t *filename,
|
||||
return 1;
|
||||
|
||||
struct stat buf;
|
||||
wstat( filename, &buf );
|
||||
|
||||
if( wstat( filename, &buf ) == -1 )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( S_IFDIR & buf.st_mode )
|
||||
return 1;
|
||||
|
||||
@@ -671,7 +674,7 @@ void al_push_check( array_list_t *l, const wchar_t *new )
|
||||
{
|
||||
if( !wcscmp( al_get(l, i), new ) )
|
||||
{
|
||||
free( new );
|
||||
free( (void *)new );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#define TRUE (!FALSE)
|
||||
#endif
|
||||
|
||||
static const unsigned char _xdg_utf8_skip_data[256] = {
|
||||
static const char _xdg_utf8_skip_data[256] = {
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
|
||||
@@ -156,11 +156,11 @@ _xdg_mime_magic_match_free (XdgMimeMagicMatch *mime_magic_match)
|
||||
/* Reads in a hunk of data until a newline character or a '\000' is hit. The
|
||||
* returned string is null terminated, and doesn't include the newline.
|
||||
*/
|
||||
static unsigned char *
|
||||
static char *
|
||||
_xdg_mime_magic_read_to_newline (FILE *magic_file,
|
||||
int *end_of_file)
|
||||
{
|
||||
unsigned char *retval;
|
||||
char *retval;
|
||||
int c;
|
||||
int len, pos;
|
||||
|
||||
@@ -179,7 +179,7 @@ _xdg_mime_magic_read_to_newline (FILE *magic_file,
|
||||
}
|
||||
if (c == '\n' || c == '\000')
|
||||
break;
|
||||
retval[pos++] = (unsigned char) c;
|
||||
retval[pos++] = (char) c;
|
||||
if (pos % 128 == 127)
|
||||
{
|
||||
len = len + 128;
|
||||
|
||||
Reference in New Issue
Block a user