Compare commits

..

62 Commits

Author SHA1 Message Date
axel
02a3288db7 1.19.0
darcs-hash:20051225220442-ac50b-79b8685cf6939c74a171f6cba227b703a1c02d60.gz
2005-12-26 08:04:42 +10:00
axel
b069489792 Only use internal wcsndup implementation of no external one exists
darcs-hash:20051225220329-ac50b-8ab5165f227112bb28406168d6c88e45a74fc7bc.gz
2005-12-26 08:03:29 +10:00
axel
b37eeb92ef Fisx crash buh when completing string ending in backslash
darcs-hash:20051225220044-ac50b-b880ffe649d04ed1e5ec6786d0b59eed8068d182.gz
2005-12-26 08:00:44 +10:00
axel
b6630b5087 Check for presense of doxygen using autoconf
darcs-hash:20051225115940-ac50b-a8bc63a835c041f6648381934396392fc277cc49.gz
2005-12-25 21:59:40 +10:00
axel
3a69fc997c Check Xautority before trying to use X-based browser in help shellscript
darcs-hash:20051221135353-ac50b-9b8b37d7465d64a209e34ed047bd6e055a4fc179.gz
2005-12-21 23:53:53 +10:00
axel
c216e36a72 Add notice about bug when suspending builtins
darcs-hash:20051221135157-ac50b-a85102e103d27b5eccf51806871b3a49befa6a10.gz
2005-12-21 23:51:57 +10:00
axel
00778832f1 Add sbin directories to PATH when root
darcs-hash:20051220090155-ac50b-2a0a54dda98086cae3329dc31a71f28774bddf46.gz
2005-12-20 19:01:55 +10:00
axel
cdbd233e62 Do not use GNU -r switch for sed
darcs-hash:20051220085820-ac50b-c46216c3eff88eab9776e5505de1f25e0e046cfc.gz
2005-12-20 18:58:20 +10:00
axel
9ce93164bb Add missing include in builtin_help.hdr
darcs-hash:20051220085746-ac50b-fb788faca5ee99e85074343ba30ee6de7fb13857.gz
2005-12-20 18:57:46 +10:00
axel
20b269130c Yet another attempt to avoid gnuisms in sed/grep for ssh completions
darcs-hash:20051218225150-ac50b-d2ec7c6b5c715a68dcc4f2d9d67636c70868da7d.gz
2005-12-19 08:51:50 +10:00
axel
891c2fc379 Use sed instead of grep, since grep -o isn't supported on OS X
darcs-hash:20051217221513-ac50b-1166a7d4814ee9e2cd960308fae4999431ebc3c1.gz
2005-12-18 08:15:13 +10:00
axel
00be44a69a Add completions for trap and jobs
darcs-hash:20051217215926-ac50b-3078bbc64adfe19d17579a886a9e2ae7b0c594dd.gz
2005-12-18 07:59:26 +10:00
axel
b8ea709c1e Add autoconf checks for wide character string functions
darcs-hash:20051217213205-ac50b-df9ea4cbc1a7e4235578bd4fc542ddb7788d41cc.gz
2005-12-18 07:32:05 +10:00
axel
7bdcfacee4 Add trap shellscript function
darcs-hash:20051217213052-ac50b-fdab838ea9595fac7572068ea3a1f12b8bb0ea68.gz
2005-12-18 07:30:52 +10:00
axel
61706b4490 Adjust fish init files to new set syntax
darcs-hash:20051217122710-ac50b-718f131091f262514686b73a1f827086fc678a08.gz
2005-12-17 22:27:10 +10:00
axel
443ddb509e make the functions builtin output descriptions and event handlers for functions
darcs-hash:20051217122546-ac50b-2bf9b1118fcbf9079398e113fb201ddde813e40a.gz
2005-12-17 22:25:46 +10:00
axel
e6774cc944 Make the set builtin only parse switches given after non-switches
darcs-hash:20051217012130-ac50b-201dd8301496b800e0382ac238ee7e164b9345e3.gz
2005-12-17 11:21:30 +10:00
axel
78cd8fa089 Tweak a few error messages for builtin commands
darcs-hash:20051216155116-ac50b-d31da6fc28ef9140f24fb0d95397daaffb3ff6ab.gz
2005-12-17 01:51:16 +10:00
axel
9229041385 Make non-interactive reading more robust.
darcs-hash:20051216155010-ac50b-8237935c6e95c296fd67280b1879267f9e7a949b.gz
2005-12-17 01:50:10 +10:00
axel
e6bd3dbc40 Make the source builtin bail out at once if stat fails. Makes sure no illegal memory acces takes place
darcs-hash:20051216125437-ac50b-150f5404037186c5380884416b696d5869704a60.gz
2005-12-16 22:54:37 +10:00
James Vega
a91bf6d88a builtin.c: builtin_source now checks that its argument is a file.
Without this check, it would be possible to attempt to source a directory and get stuck in an infinite loop.

darcs-hash:20051215172122-35ec8-b3ce05d8d7ee9534edf92b74ca842d034b894e8a.gz
2005-12-16 03:21:22 +10:00
axel
fa75fc3901 Code cleanup
darcs-hash:20051215135902-ac50b-e9fc18bca34459ddb56e970a16c05e9b3cc54848.gz
2005-12-15 23:59:02 +10:00
axel
e4a95cb989 Add missing -r/--replace switch to commandline builtin
darcs-hash:20051215101901-ac50b-721c6a3afc426b110506b5101a25c54205767dc5.gz
2005-12-15 20:19:01 +10:00
axel
9cf4a2a0b3 Add extra step in instructions on creating a builtin
darcs-hash:20051214234808-ac50b-14d032091b843c4692f4548c9763b65c46b2fc92.gz
2005-12-15 09:48:08 +10:00
axel
0ff374a4a0 Add missing newline at end of yum completion file
darcs-hash:20051214234650-ac50b-0002f137022144e2fc55b233df1f32157e8b77f8.gz
2005-12-15 09:46:50 +10:00
axel
0817962300 Add missing documentation file
darcs-hash:20051214180744-ac50b-9394e5a12ca3eb98a9333a666748d16277cc2d7b.gz
2005-12-15 04:07:44 +10:00
axel
8b69c5416d Minor documentation edits
darcs-hash:20051214164116-ac50b-c95a5dcb71d39c29b69010e879c96fc66ff1271e.gz
2005-12-15 02:41:16 +10:00
axel
1071fedaee Fix Alt-p shortcut
darcs-hash:20051214140906-ac50b-73f73a4dd9f2d77f5cb70a742aa0331cbedc11ba.gz
2005-12-15 00:09:06 +10:00
axel
ab207b64a3 Add separator characters to make quoted variable expantion works properly
darcs-hash:20051214135336-ac50b-ebd834e2bc52324ae4926efc270508648d8cb280.gz
2005-12-14 23:53:36 +10:00
axel
418e26c0ac Fix crash bug from calling eval builtin with no arguments
darcs-hash:20051214134644-ac50b-5872ff628bf4f5d4f22f912d7ce7e9ed25d48b58.gz
2005-12-14 23:46:44 +10:00
axel
de3a28874e Code tweaks
darcs-hash:20051214033939-ac50b-321171b5a7a59ca6856ce1b1a09126614154544a.gz
2005-12-14 13:39:39 +10:00
axel
9dd842ea96 Code tweaks
darcs-hash:20051214010712-ac50b-4053d2c3b97a1ea6168f113e91d3e4915915ea9a.gz
2005-12-14 11:07:12 +10:00
axel
5d069de71d Use different abbrevation for prompt_pwd
darcs-hash:20051214003427-ac50b-1227b7a0795e2fe3adf4f37c2594033f673b7a5e.gz
2005-12-14 10:34:27 +10:00
axel
16333b0c69 Simplify pwd function
darcs-hash:20051214003313-ac50b-697691ebc5cedddde35307bee465b3083b91c00e.gz
2005-12-14 10:33:13 +10:00
axel
e4fa0e1000 Simplify greeting code
darcs-hash:20051214000613-ac50b-18e45081adfe96ecbf4439f39e6df3784941952e.gz
2005-12-14 10:06:13 +10:00
axel
3e52bd0132 More tweaks
darcs-hash:20051213201121-ac50b-cdb07b1535b7a7f521d5a4360d09a449315a65a3.gz
2005-12-14 06:11:21 +10:00
axel
211663a549 Use . as CDPATH if CDPATH is zero length
darcs-hash:20051213201036-ac50b-7567b40f37b409a1bc0ec7b1dc83724057e7e5d2.gz
2005-12-14 06:10:36 +10:00
axel
659b99ed1a Lots of fixed typos. Thanks, Harshad!
darcs-hash:20051213183257-ac50b-65c01704388f0fa94a7fbc62ba4d22ec1e6397d2.gz
2005-12-14 04:32:57 +10:00
axel
86d7e8bb8e Minor tweaks
darcs-hash:20051213182803-ac50b-859b5bd4274e24dfd462cdf4585f0a05b751f737.gz
2005-12-14 04:28:03 +10:00
axel
8bf0a14bd5 Autodetect common escape codes in fish_prompt output
darcs-hash:20051213101859-ac50b-0ff01bb168d894d401d3d93cc11740789bac0d62.gz
2005-12-13 20:18:59 +10:00
axel
9c32709fe1 Fix infinite loop in token search
darcs-hash:20051212183055-ac50b-a40c21f801978094e4ae5b3f6f5d84276eb956e7.gz
2005-12-13 04:30:55 +10:00
axel
00bdd2cb48 Fix bug causing inconsistent state and shutdown when the begin command was used in a function definition
darcs-hash:20051212155104-ac50b-bb942f22d1eaef8cdc07ddf04fb9230bbfb165f6.gz
2005-12-13 01:51:04 +10:00
axel
0a8284c981 Further tweaks to jobs builtin
darcs-hash:20051212155001-ac50b-bb6d180d8e0ca5150173a3dc3aa6cd7e021fa770.gz
2005-12-13 01:50:01 +10:00
axel
ddbb50acd7 Minor edits
darcs-hash:20051211233939-ac50b-e01a4024f70355f2b7f1b5377c6e0853997d9860.gz
2005-12-12 09:39:39 +10:00
axel
5262f3ce99 Revamp the jobs builtin
darcs-hash:20051211233001-ac50b-24547ca41d4db05f87d59dd3e396c3190a66ef89.gz
2005-12-12 09:30:01 +10:00
axel
28dd48a76a Use char instead of unsigned char in xdgmime files. Avoids a few warnings.
darcs-hash:20051211222833-ac50b-3fd68bb7000660172027c8991c68448ddb36e27d.gz
2005-12-12 08:28:33 +10:00
axel
b1c61bcf1f Do not call fcntl before fully reading block.Escalates bug severity without any practical benefit.
darcs-hash:20051211222730-ac50b-bdb2e1dc612ba6a9dd425f514baa2423f8b0d4e5.gz
2005-12-12 08:27:30 +10:00
axel
bb591a69c9 Make type fuction handle hidden functions
darcs-hash:20051211222603-ac50b-e846b05b27d2e2c072c760baa1e067f9484636e3.gz
2005-12-12 08:26:03 +10:00
axel
1d69e70b7a Initial blocking implementation
darcs-hash:20051211222101-ac50b-6e11220bd608187fbb32a0313b5b73dbdc8354fc.gz
2005-12-12 08:21:01 +10:00
axel
2cac04850b Fix crash bug in token search
darcs-hash:20051211043017-ac50b-137695bd9bb9c523d5b5288a5d4263e4c4242edf.gz
2005-12-11 14:30:17 +10:00
axel
2619f1752d Remove compiler warning
darcs-hash:20051210003607-ac50b-3c9aab83ec7c5f184c1cd01f6cdd11c711725584.gz
2005-12-10 10:36:07 +10:00
axel
33e2c81748 Make sure tokenizer never changes input string
darcs-hash:20051210003335-ac50b-2d1b9125186b1d3f68138c2c49559d077fa5d326.gz
2005-12-10 10:33:35 +10:00
axel
f05da41159 Escape the ~ character
darcs-hash:20051209121954-ac50b-347571c227de795661694f31ff4ab9eafdda0e39.gz
2005-12-09 22:19:54 +10:00
axel
780ecc46fc 1.18.1
darcs-hash:20051209040512-ac50b-9c39e3e1b1345caa1167a8d09e79c569d3600a7a.gz
2005-12-09 14:05:12 +10:00
axel
9b98df8310 Add history search information to documentation
darcs-hash:20051209040443-ac50b-ac75d7308947d00867950f6df74cc68907045a3b.gz
2005-12-09 14:04:43 +10:00
axel
5a8205ac2b Shorten ${foo} error message a bit
darcs-hash:20051209035042-ac50b-b71d3e2b326cf18c4520c86d6587d432230d7ac9.gz
2005-12-09 13:50:42 +10:00
axel
2490da31ce Fix missing escapes for the [] characters
darcs-hash:20051209033225-ac50b-713c8d82887fb6de4de84c980f23a19039df0cb7.gz
2005-12-09 13:32:25 +10:00
axel
092bb90569 Add minor missing completion for fish itself
darcs-hash:20051209025651-ac50b-7fce573294ed888c59c7fc6ce2bd6e4d2f822e0f.gz
2005-12-09 12:56:51 +10:00
axel
39ca027706 Do not fail make install on missing ChangeLog
darcs-hash:20051209024923-ac50b-9a998c9e221c1a2d5613498e78614fafc5c6a347.gz
2005-12-09 12:49:23 +10:00
axel
22433f2717 Completion prefix was missing one character
darcs-hash:20051209024718-ac50b-91cd117f5950726ecbf5451b415cf2f8041f689a.gz
2005-12-09 12:47:18 +10:00
axel
f6e194447d Do not stop evaluation on wildcard error
darcs-hash:20051209024116-ac50b-4053af9c2800565b752476a6cdb31d3a5c43b113.gz
2005-12-09 12:41:16 +10:00
axel
e2ed5d0977 Fix buffer inconsistency un ^U
darcs-hash:20051209024034-ac50b-a06c78f8f238f61c99ddcd4bee02f8b41af26c6c.gz
2005-12-09 12:40:34 +10:00
47 changed files with 1633 additions and 608 deletions

View File

@@ -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 \

822
builtin.c

File diff suppressed because it is too large Load Diff

View File

@@ -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;

View File

@@ -9,6 +9,7 @@
#include <stdio.h>
#include <strings.h>
#include <wchar.h>
#include <sys/types.h>
#include "config.h"
#include "util.h"

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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 );

View File

@@ -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
View 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>

View File

@@ -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 *$' &gt;/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

View File

@@ -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
View 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
View File

@@ -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
View File

@@ -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
View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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

View 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'

View File

@@ -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)

View File

@@ -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"

View File

@@ -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"

View 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
):

View File

@@ -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)@

View 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'

View File

@@ -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"

View File

@@ -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'
"
"

View File

@@ -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
#

View File

@@ -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

View File

@@ -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

View File

@@ -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
#

View File

@@ -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
View File

@@ -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;

View File

@@ -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
View File

@@ -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();
}

View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -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 );

View File

@@ -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 );
}
/**

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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,

View File

@@ -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;