Compare commits

...

41 Commits

Author SHA1 Message Date
axel
ec58ffa641 Bump version number
darcs-hash:20060531154529-ac50b-92c8377b8b3164fa280c02b4752243295c4b7c40.gz
2006-06-01 01:45:29 +10:00
axel
2c44ecb4a3 Drop debug message
darcs-hash:20060531154456-ac50b-2367291f440bff21b3029829ff7dff86be5b5ec1.gz
2006-06-01 01:44:56 +10:00
axel
2eebb6e7ed Revert addition of the seq file to repo - only seq.in should be there. Also apply earlier fix to seq.in
darcs-hash:20060531154428-ac50b-7ddeef083d3d965eb484cb11a71c1291660fee89.gz
2006-06-01 01:44:28 +10:00
axel
1a3ab8a189 Make validation code show offening parameter on perameter expansion problems
darcs-hash:20060531154147-ac50b-dd9b9a3e000352b045a4a9c3122a45a312c43f19.gz
2006-06-01 01:41:47 +10:00
axel
4722ddc373 Increase size of buffer for parser error string. Should change this to a dynamically allocated string.
darcs-hash:20060531154028-ac50b-ada120ecfe65bcf1ad1b3d1a5fad41ae9dec133c.gz
2006-06-01 01:40:28 +10:00
axel
25365dbc54 Minor change to the strings to a printf comman, since it seems to work differently under different platforms
darcs-hash:20060530091417-ac50b-4eead9f39433b54ab66dea1c336b533689d85c46.gz
2006-05-30 19:14:17 +10:00
axel
6a5f11879b Minor code simplifications in highlighting code
darcs-hash:20060530003535-ac50b-6babcc9880a018a669e123c2acdb548adb4406ce.gz
2006-05-30 10:35:35 +10:00
axel
b028e41f7f Slightly updated fusermount completions - Thanks to Sean Higgins
darcs-hash:20060529135227-ac50b-ffce282fc850a895da75f64cd8a151277f42a937.gz
2006-05-29 23:52:27 +10:00
axel
86593cd6a2 Add highlighting to a few missing escape sequences
darcs-hash:20060529134659-ac50b-48de59c1c84e4e3d3a6cf6283ec8a652986c380d.gz
2006-05-29 23:46:59 +10:00
axel
6cae5c8b0a Minor rewordings and additions to the manual
darcs-hash:20060529134607-ac50b-097cf23e8009b13afa456cf3946cc0799b0fd471.gz
2006-05-29 23:46:07 +10:00
axel
29cd62ab6e Check documentation for listing of external commands instead of relying on out of date static lists in various places
darcs-hash:20060529133239-ac50b-48392cfa1e5817ed8df452f0632658af7fe47a28.gz
2006-05-29 23:32:39 +10:00
axel
4c7e06e752 Add missing event trigger when non-universal variable is erased
darcs-hash:20060529131217-ac50b-feb2034230297d9edc120369d8f3c1cfff6acfcd.gz
2006-05-29 23:12:17 +10:00
axel
433169dca4 Avoid using the pwd command in favour of the $PWD variable, since the pwd command does not seem to work well with fuse
darcs-hash:20060529130753-ac50b-0d32fe0924dbf9e83520d26402e9daae77789419.gz
2006-05-29 23:07:53 +10:00
axel
d46dade284 Rename function expand_variable_array to tokenize_variable_array and move it from expand.c to common.c, since it is used by fish_pager, which should not depend on expand.o
darcs-hash:20060529111342-ac50b-315d7dcf04e05fa8f32e16801e6793ac4e4e022e.gz
2006-05-29 21:13:42 +10:00
axel
79b466441b Fix major memory leak in highlighting code and a minor leak in the parser
darcs-hash:20060528110630-ac50b-94a83ec6731b39ebcf864b7491ec3c372e28a135.gz
2006-05-28 21:06:30 +10:00
axel
9f14d50974 Extend manual section on highlighting colors
darcs-hash:20060528105437-ac50b-c1c703206e855e5a4b5d7cf48bc19c48e12d2833.gz
2006-05-28 20:54:37 +10:00
axel
990803009e Minor edits
darcs-hash:20060527134918-ac50b-b244916fc6649e1abb4832bdaa3fff81fcbe3937.gz
2006-05-27 23:49:18 +10:00
axel
6dfd629fc5 Update todo list
darcs-hash:20060527134859-ac50b-3890023bb4003bbf773bf68dbcb9588c6ec55600.gz
2006-05-27 23:48:59 +10:00
axel
d97f8f3fde Add missing completion for complete builtin
darcs-hash:20060527134741-ac50b-dd50e408384d48b4b859240ac4fb6ad1ea8d25a5.gz
2006-05-27 23:47:41 +10:00
axel
95ca3d1c69 Minor clarifications for documentation for the set builtin
darcs-hash:20060527134723-ac50b-8ad44bf44a8537f12b45281950fcaf85abbdd8f4.gz
2006-05-27 23:47:23 +10:00
axel
c8b04f70cf Add highlighting of a few missing escapes
darcs-hash:20060527134026-ac50b-3ff05d1fe0246d37c1be6e4a6d4492bf411808b7.gz
2006-05-27 23:40:26 +10:00
axel
bffff77d17 Add support for bold highligting
darcs-hash:20060527133930-ac50b-515d0887567c0e89fdfe10fe8310d6ebb4485974.gz
2006-05-27 23:39:30 +10:00
axel
6bdb0cde8b Add support for highligting qutes in a special color - defaults to blue
darcs-hash:20060527123516-ac50b-d6e0cf08bd9dfe8514e64004d93dc4035e73fad8.gz
2006-05-27 22:35:16 +10:00
axel
42a260f1e6 Use ahead of time validator to make sure that commands entered on the command line are valid
darcs-hash:20060527111456-ac50b-1bc070467029b851d34a1b99457415e3f0b24429.gz
2006-05-27 21:14:56 +10:00
axel
148cb68700 Add Parenthesis and braces to list of highlighted operators, and do minor code cleanup
darcs-hash:20060527005618-ac50b-272d096796b732b7d6c000c30be1a9ca1e1995a6.gz
2006-05-27 10:56:18 +10:00
axel
18c185c256 Add support for highlighting operators and escaped sequences
darcs-hash:20060526164638-ac50b-2259579e0460df0641683ce6127bb8516fca8c7e.gz
2006-05-27 02:46:38 +10:00
axel
b5b49e7a4d Make sure that getopt flags are only written down once
darcs-hash:20060526145551-ac50b-5411809433e277cd0bdebc34907ee3312a8a0263.gz
2006-05-27 00:55:51 +10:00
axel
28ea5ce732 Add missing N_.fish file to repo
darcs-hash:20060526120906-ac50b-5c903a99dfcb176c454bec2abc25360e8a7bf79a.gz
2006-05-26 22:09:06 +10:00
axel
eccba7626d Properly exit ca_mode terminal mode on exit
darcs-hash:20060526120331-ac50b-bbddd181b0784072a47e0f852012b9588c4fc3d6.gz
2006-05-26 22:03:31 +10:00
axel
79d3207d51 The fallback seq implementation was missing in the darcs repo, add it and fix a bug in it
darcs-hash:20060526114722-ac50b-4b75ac32c6490b358bb1003736fdc47198f37030.gz
2006-05-26 21:47:22 +10:00
axel
d6bf879675 Move jobs builtin to its own file
darcs-hash:20060526113811-ac50b-9c0ed1aa26cd2f247978e406bea86e8c36d73710.gz
2006-05-26 21:38:11 +10:00
axel
051f557e8f Minor code polish for the validation code
darcs-hash:20060526112525-ac50b-d15f974d7abc5ffdc61273c1642c1cb711bc23fd.gz
2006-05-26 21:25:25 +10:00
axel
17171c3277 If a help page for a builtin is showed in response to an error, make sure it fits on screen, or only print the synopsis - this patch also contains a huge number of tweaks to where and when the help pages are printed
darcs-hash:20060526112402-ac50b-88993e45f411b2f1c45b3202c393c5328f1c7429.gz
2006-05-26 21:24:02 +10:00
axel
18a59291ed Bugfix for previous patch to simplify configuration checks for ulimit builtin
darcs-hash:20060526111934-ac50b-ae9e85cd3e18994d2c56c2f6c69df6a1d93f9ea6.gz
2006-05-26 21:19:34 +10:00
axel
29e86254d0 Allow tab completion of empty command names
darcs-hash:20060521223213-ac50b-5201b7f0dfe5227f93aae6db94450e165c9a5a34.gz
2006-05-22 08:32:13 +10:00
axel
b746a803a9 Add validator check to make sure the second argument to 'for' is 'in'
darcs-hash:20060521221604-ac50b-5bc4ce217a08304f68b97b20e908ea1279fe26e9.gz
2006-05-22 08:16:04 +10:00
axel
07e14ed7a8 Rewrite small amount of code in parameter expansion to use wide character strings, not narrow
darcs-hash:20060521214601-ac50b-bb3937f5abd2780a7ecf8ab13975a0f6b622323f.gz
2006-05-22 07:46:01 +10:00
axel
df5cc6f858 Fix bugs detected by the ahead-of-time syntax checking in the complete builtin
darcs-hash:20060521192705-ac50b-b4304328fb4b9cce853055a2f231c48050a17471.gz
2006-05-22 05:27:05 +10:00
axel
409a407ca0 Use ahead-of-time syntax checker to validate input for complete builtin
darcs-hash:20060521192630-ac50b-c469f5bb3bd2afddce3ffa80adba0589d515b938.gz
2006-05-22 05:26:30 +10:00
axel
1c2cbb00bc Major update to the ahead-of-time syntax checker
darcs-hash:20060521192524-ac50b-48713f826558e66ef21046d1bb779623cc2fd97a.gz
2006-05-22 05:25:24 +10:00
axel
bbf2a3836f Simplify code for detecting which macros are defined in sys/resource.h, no configure-time tests are needed
darcs-hash:20060519151443-ac50b-c87dba2175f5bf8d652c783559c3a9992247aa01.gz
2006-05-20 01:14:43 +10:00
44 changed files with 1689 additions and 716 deletions

View File

@@ -72,7 +72,7 @@ COMMON_OBJS_WITH_HEADER := builtin_help.o
# main.c exists, but main.h does not, etc.
COMMON_OBJS_WITH_CODE := builtin_set.o builtin_commandline.o \
builtin_ulimit.o builtin_complete.o
builtin_ulimit.o builtin_complete.o builtin_jobs.o
# All objects that the system needs to build fish
FISH_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \

429
builtin.c
View File

@@ -92,18 +92,6 @@ typedef struct builtin_data
builtin_data_t;
/**
Print modes for the jobs builtin
*/
enum
{
JOBS_DEFAULT, /**< Print lots of general info */
JOBS_PRINT_PID, /**< Print pid of each process in job */
JOBS_PRINT_COMMAND, /**< Print command name of each process in job */
JOBS_PRINT_GROUP, /**< Print group id of job */
}
;
/**
Table of all builtins
*/
@@ -159,6 +147,15 @@ void builtin_wperror( const wchar_t *s)
}
}
static int count_char( const wchar_t *str, wchar_t c )
{
int res = 0;
for( ; *str; str++ )
{
res += (*str==c);
}
return res;
}
/*
Here follows the definition of all builtin commands. The function
@@ -170,10 +167,12 @@ void builtin_wperror( const wchar_t *s)
are part of the parser. (They are not parsed as commands, instead
they only slightly alter the parser state)
If \c b is the buffer representing standard error, and the help
message is about to be printed to an interactive screen, it may be
shortened to fit the screen.
*/
void builtin_print_help( wchar_t *cmd, string_buffer_t *b )
{
const char *h;
@@ -189,11 +188,50 @@ void builtin_print_help( wchar_t *cmd, string_buffer_t *b )
if( !h )
return;
wchar_t *str = str2wcs(builtin_help_get( cmd ));
wchar_t *str = str2wcs( h );
if( str )
{
if( is_interactive && !builtin_out_redirect && b==sb_err)
{
/* Interactive mode help to screen - only print synopsis if the rest won't fit */
int screen_height, lines;
screen_height = common_get_height();
lines = count_char( str, L'\n' );
if( lines > 2*screen_height/3 )
{
wchar_t *pos;
/* Find first empty line */
for( pos=str; *pos; pos++ )
{
if( *pos == L'\n' )
{
wchar_t *pos2;
int is_empty = 1;
for( pos2 = pos+1; *pos2; pos2++ )
{
if( *pos2 == L'\n' )
break;
if( *pos2 != L'\t' && *pos2 !=L' ' )
{
is_empty = 0;
break;
}
}
if( is_empty )
{
*(pos+1)=L'\0';
}
}
}
}
}
sb_append( b, str );
free( str );
}
@@ -215,6 +253,10 @@ static int builtin_bind( wchar_t **argv )
L"set-mode", required_argument, 0, 'M'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
@@ -227,7 +269,7 @@ static int builtin_bind( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"M:",
L"M:h",
long_options,
&opt_index );
if( opt == -1 )
@@ -250,6 +292,10 @@ static int builtin_bind( wchar_t **argv )
input_set_mode( woptarg );
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case '?':
builtin_print_help( argv[0], sb_err );
@@ -337,7 +383,7 @@ static int builtin_block( wchar_t **argv )
return 1;
case 'h':
builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_out );
return 0;
case 'g':
@@ -478,7 +524,7 @@ static int builtin_builtin( wchar_t **argv )
return 1;
case 'h':
builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_out );
return 0;
case 'n':
@@ -701,6 +747,10 @@ static int builtin_functions( wchar_t **argv )
L"all", no_argument, 0, 'a'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
@@ -713,7 +763,7 @@ static int builtin_functions( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"ed:na",
L"ed:nah",
long_options,
&opt_index );
if( opt == -1 )
@@ -749,6 +799,10 @@ static int builtin_functions( wchar_t **argv )
show_hidden=1;
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case '?':
builtin_print_help( argv[0], sb_err );
@@ -948,6 +1002,10 @@ static int builtin_function( wchar_t **argv )
L"on-variable", required_argument, 0, 'v'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
@@ -960,7 +1018,7 @@ static int builtin_function( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"bd:s:j:p:v:",
L"bd:s:j:p:v:h",
long_options,
&opt_index );
if( opt == -1 )
@@ -1114,6 +1172,10 @@ static int builtin_function( wchar_t **argv )
break;
}
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case '?':
builtin_print_help( argv[0], sb_err );
res = 1;
@@ -1160,7 +1222,7 @@ static int builtin_function( wchar_t **argv )
array_list_t names;
int chars=0;
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
const wchar_t *cfa = _( L"Current functions are: " );
sb_append( sb_err, cfa );
chars += wcslen( cfa );
@@ -1258,7 +1320,7 @@ static int builtin_random( wchar_t **argv )
return 1;
case 'h':
builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_out );
break;
case '?':
@@ -1368,6 +1430,10 @@ static int builtin_read( wchar_t **argv )
L"command", required_argument, 0, 'c'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
@@ -1378,7 +1444,7 @@ static int builtin_read( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"xglUup:c:",
L"xglUup:c:h",
long_options,
&opt_index );
if( opt == -1 )
@@ -1419,6 +1485,10 @@ static int builtin_read( wchar_t **argv )
commandline = woptarg;
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case L'?':
builtin_print_help( argv[0], sb_err );
@@ -1695,7 +1765,7 @@ static int builtin_status( wchar_t **argv )
return 1;
case 'h':
builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_out );
return 0;
case 'j':
@@ -1849,7 +1919,7 @@ static int builtin_exit( wchar_t **argv )
default:
sb_printf( sb_err,
_( L"%ls: Too many arguments\n" ),
BUILTIN_ERR_TOO_MANY_ARGUMENTS,
argv[0] );
builtin_print_help( argv[0], sb_err );
@@ -2259,309 +2329,6 @@ static int builtin_bg( wchar_t **argv )
}
#ifdef HAVE__PROC_SELF_STAT
/**
Calculates the cpu usage (in percent) of the specified job.
*/
static int cpu_use( job_t *j )
{
double u=0;
process_t *p;
for( p=j->first_process; p; p=p->next )
{
struct timeval t;
int jiffies;
gettimeofday( &t, 0 );
jiffies = proc_get_jiffies( p );
double t1 = 1000000.0*p->last_time.tv_sec+p->last_time.tv_usec;
double t2 = 1000000.0*t.tv_sec+t.tv_usec;
/* fwprintf( stderr, L"t1 %f t2 %f p1 %d p2 %d\n",
t1, t2, jiffies, p->last_jiffies );
*/
u += ((double)(jiffies-p->last_jiffies))/(t2-t1);
}
return u*1000000;
}
#endif
/**
Print information about the specified job
*/
static void builtin_jobs_print( job_t *j, int mode, int header )
{
process_t *p;
switch( mode )
{
case JOBS_DEFAULT:
{
if( header )
{
/*
Print table header before first job
*/
sb_append( sb_out, _( L"Job\tGroup\t" ));
#ifdef HAVE__PROC_SELF_STAT
sb_append( sb_out, _( L"CPU\t" ) );
#endif
sb_append( sb_out, _( L"State\tCommand\n" ) );
}
sb_printf( sb_out, L"%d\t%d\t", j->job_id, j->pgid );
#ifdef HAVE__PROC_SELF_STAT
sb_printf( sb_out, L"%d%%\t", cpu_use(j) );
#endif
sb_append2( sb_out,
job_is_stopped(j)?_(L"stopped"):_(L"running"),
L"\t",
j->command,
L"\n",
(void *)0 );
break;
}
case JOBS_PRINT_GROUP:
{
if( header )
{
/*
Print table header before first job
*/
sb_append( sb_out, _( L"Group\n" ));
}
sb_printf( sb_out, L"%d\n", j->pgid );
break;
}
case JOBS_PRINT_PID:
{
if( header )
{
/*
Print table header before first job
*/
sb_append( sb_out, _( L"Procces\n" ));
}
for( p=j->first_process; p; p=p->next )
{
sb_printf( sb_out, L"%d\n", p->pid );
}
break;
}
case JOBS_PRINT_COMMAND:
{
if( header )
{
/*
Print table header before first job
*/
sb_append( sb_out, _( L"Command\n" ));
}
for( p=j->first_process; p; p=p->next )
{
sb_printf( sb_out, L"%ls\n", p->argv[0] );
}
break;
}
}
}
/**
Builtin for printing running jobs
*/
static int builtin_jobs( wchar_t **argv )
{
int argc=0;
int found=0;
int mode=JOBS_DEFAULT;
int print_last = 0;
job_t *j;
argc = builtin_count_args( argv );
woptind=0;
while( 1 )
{
const static struct woption
long_options[] =
{
{
L"pid", no_argument, 0, 'p'
}
,
{
L"command", no_argument, 0, 'c'
}
,
{
L"group", no_argument, 0, 'g'
}
,
{
L"last", no_argument, 0, 'l'
}
,
{
0, 0, 0, 0
}
}
;
int opt_index = 0;
int opt = wgetopt_long( argc,
argv,
L"pclg",
long_options,
&opt_index );
if( opt == -1 )
break;
switch( opt )
{
case 0:
if(long_options[opt_index].flag != 0)
break;
sb_printf( sb_err,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
return 1;
case 'p':
mode=JOBS_PRINT_PID;
break;
case 'c':
mode=JOBS_PRINT_COMMAND;
break;
case 'g':
mode=JOBS_PRINT_GROUP;
break;
case 'l':
{
print_last = 1;
break;
}
case '?':
// builtin_print_help( argv[0], sb_err );
return 1;
}
}
/*
Do not babble if not interactive
*/
if( builtin_out_redirect )
{
found=1;
}
if( print_last )
{
/*
Ignore unconstructed jobs, i.e. ourself.
*/
for( j=first_job; j; j=j->next )
{
if( j->constructed && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
return 0;
}
}
}
else
{
if( woptind < argc )
{
int i;
found = 1;
for( i=woptind; i<argc; i++ )
{
long pid;
wchar_t *end;
errno=0;
pid=wcstol( argv[i], &end, 10 );
if( errno || *end )
{
sb_printf( sb_err,
_( L"%ls: '%ls' is not a job\n" ),
argv[0],
argv[i] );
return 1;
}
j = job_get_from_pid( pid );
if( j && !job_is_completed( j ) )
{
builtin_jobs_print( j, mode, !found );
}
else
{
sb_printf( sb_err,
_( L"%ls: No suitable job: %d\n" ),
argv[0],
pid );
return 1;
}
}
}
else
{
for( j= first_job; j; j=j->next )
{
/*
Ignore unconstructed jobs, i.e. ourself.
*/
if( j->constructed && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
found = 1;
}
}
}
}
if( !found )
{
sb_printf( sb_out,
_( L"%ls: There are no jobs\n" ),
argv[0] );
}
return 0;
}
/**
Builtin for looping over a list
*/
@@ -2590,7 +2357,7 @@ static int builtin_for( wchar_t **argv )
else if (wcscmp( argv[2], L"in") != 0 )
{
sb_printf( sb_err,
_( L"%ls: Second argument must be 'in'\n" ),
BUILTIN_FOR_ERR_IN,
argv[0] );
builtin_print_help( argv[0], sb_err );
}

View File

@@ -57,6 +57,13 @@ enum
*/
#define BUILTIN_ERR_VARNAME_ZERO _( L"%ls: Variable name can not be the empty string\n" )
/**
Error message when second argument to for isn't 'in'
*/
#define BUILTIN_FOR_ERR_IN _( L"%ls: Second argument must be 'in'\n" )
#define BUILTIN_ERR_TOO_MANY_ARGUMENTS _( L"%ls: Too many arguments\n" )
/**
Stringbuffer used to represent standard output
*/
@@ -132,33 +139,42 @@ const wchar_t *builtin_get_desc( const wchar_t *b );
int builtin_count_args( wchar_t **argv );
/**
Print help for the specified builtin. If \c b is sb_err, also print the line information
Print help for the specified builtin. If \c b is sb_err, also print
the line information
*/
void builtin_print_help( wchar_t *cmd, string_buffer_t *b );
/**
The set builtin, used for setting variables. Defined in builtin_set.c.
The set builtin, used for setting variables. Defined in
builtin_set.c.
*/
int builtin_set(wchar_t **argv);
/**
The commandline builtin, used for setting and getting the contents of the commandline. Defined in builtin_commandline.c.
The commandline builtin, used for setting and getting the contents
of the commandline. Defined in builtin_commandline.c.
*/
int builtin_commandline(wchar_t **argv);
/**
The ulimit builtin, used for setting resource limits. Defined in builtin_ulimit.c.
The ulimit builtin, used for setting resource limits. Defined in
builtin_ulimit.c.
*/
int builtin_ulimit(wchar_t **argv);
/**
The complete builtin. Used for specifying programmable
tab-completions. Calls the functions in complete.c for any heavy
lifting.
lifting. Defined in builtin_complete.c
*/
int builtin_complete(wchar_t **argv);
/**
The jobs builtin. Used fopr printing running jobs. Defined in builtin_jobs.c.
*/
int builtin_jobs(wchar_t **argv);
const wchar_t *builtin_complete_get_temporary_buffer();
/**

View File

@@ -265,6 +265,10 @@ int builtin_commandline( wchar_t **argv )
L"tokenize", no_argument, 0, 'o'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
@@ -275,7 +279,7 @@ int builtin_commandline( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"aijpctwfor",
L"aijpctwforh",
long_options,
&opt_index );
if( opt == -1 )
@@ -330,6 +334,10 @@ int builtin_commandline( wchar_t **argv )
tokenize=1;
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case L'?':
builtin_print_help( argv[0], sb_err );
return 1;

View File

@@ -341,6 +341,10 @@ int builtin_complete( wchar_t **argv )
L"do-complete", required_argument, 0, 'C'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
@@ -351,7 +355,7 @@ int builtin_complete( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"a:c:p:s:l:o:d:frxeun:C:",
L"a:c:p:s:l:o:d:frxeun:C:h",
long_options,
&opt_index );
if( opt == -1 )
@@ -369,7 +373,7 @@ int builtin_complete( wchar_t **argv )
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
res = 1;
@@ -431,10 +435,14 @@ int builtin_complete( wchar_t **argv )
do_complete = woptarg?woptarg:reader_get_buffer();
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case '?':
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
res = 1;
break;
@@ -443,6 +451,42 @@ int builtin_complete( wchar_t **argv )
}
if( !res )
{
if( condition && wcslen( condition ) )
{
if( parser_test( condition, 0 ) )
{
sb_printf( sb_err,
L"%ls: Condition '%ls' contained a syntax error\n",
argv[0],
condition );
parser_test( condition, 1 );
res = 1;
}
}
}
if( !res )
{
if( comp && wcslen( comp ) )
{
if( parser_test_args( comp, 0 ) )
{
sb_printf( sb_err,
L"%ls: Completion '%ls' contained a syntax error\n",
argv[0],
comp );
parser_test_args( comp, 1 );
res = 1;
}
}
}
if( !res )
{
if( do_complete )
@@ -485,7 +529,7 @@ int builtin_complete( wchar_t **argv )
argv[0] );
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
res = 1;
}

349
builtin_jobs.c Normal file
View File

@@ -0,0 +1,349 @@
/** \file builtin_jobs.c
Functions for executing the jobs builtin.
*/
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <wctype.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
#include "wutil.h"
#include "builtin.h"
#include "proc.h"
#include "parser.h"
#include "common.h"
#include "wgetopt.h"
#include "translate.h"
/**
Print modes for the jobs builtin
*/
enum
{
JOBS_DEFAULT, /**< Print lots of general info */
JOBS_PRINT_PID, /**< Print pid of each process in job */
JOBS_PRINT_COMMAND, /**< Print command name of each process in job */
JOBS_PRINT_GROUP, /**< Print group id of job */
}
;
#ifdef HAVE__PROC_SELF_STAT
/**
Calculates the cpu usage (in percent) of the specified job.
*/
static int cpu_use( job_t *j )
{
double u=0;
process_t *p;
for( p=j->first_process; p; p=p->next )
{
struct timeval t;
int jiffies;
gettimeofday( &t, 0 );
jiffies = proc_get_jiffies( p );
double t1 = 1000000.0*p->last_time.tv_sec+p->last_time.tv_usec;
double t2 = 1000000.0*t.tv_sec+t.tv_usec;
/* fwprintf( stderr, L"t1 %f t2 %f p1 %d p2 %d\n",
t1, t2, jiffies, p->last_jiffies );
*/
u += ((double)(jiffies-p->last_jiffies))/(t2-t1);
}
return u*1000000;
}
#endif
/**
Print information about the specified job
*/
static void builtin_jobs_print( job_t *j, int mode, int header )
{
process_t *p;
switch( mode )
{
case JOBS_DEFAULT:
{
if( header )
{
/*
Print table header before first job
*/
sb_append( sb_out, _( L"Job\tGroup\t" ));
#ifdef HAVE__PROC_SELF_STAT
sb_append( sb_out, _( L"CPU\t" ) );
#endif
sb_append( sb_out, _( L"State\tCommand\n" ) );
}
sb_printf( sb_out, L"%d\t%d\t", j->job_id, j->pgid );
#ifdef HAVE__PROC_SELF_STAT
sb_printf( sb_out, L"%d%%\t", cpu_use(j) );
#endif
sb_append2( sb_out,
job_is_stopped(j)?_(L"stopped"):_(L"running"),
L"\t",
j->command,
L"\n",
(void *)0 );
break;
}
case JOBS_PRINT_GROUP:
{
if( header )
{
/*
Print table header before first job
*/
sb_append( sb_out, _( L"Group\n" ));
}
sb_printf( sb_out, L"%d\n", j->pgid );
break;
}
case JOBS_PRINT_PID:
{
if( header )
{
/*
Print table header before first job
*/
sb_append( sb_out, _( L"Procces\n" ));
}
for( p=j->first_process; p; p=p->next )
{
sb_printf( sb_out, L"%d\n", p->pid );
}
break;
}
case JOBS_PRINT_COMMAND:
{
if( header )
{
/*
Print table header before first job
*/
sb_append( sb_out, _( L"Command\n" ));
}
for( p=j->first_process; p; p=p->next )
{
sb_printf( sb_out, L"%ls\n", p->argv[0] );
}
break;
}
}
}
int builtin_jobs( wchar_t **argv )
{
int argc=0;
int found=0;
int mode=JOBS_DEFAULT;
int print_last = 0;
job_t *j;
argc = builtin_count_args( argv );
woptind=0;
while( 1 )
{
const static struct woption
long_options[] =
{
{
L"pid", no_argument, 0, 'p'
}
,
{
L"command", no_argument, 0, 'c'
}
,
{
L"group", no_argument, 0, 'g'
}
,
{
L"last", no_argument, 0, 'l'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
}
;
int opt_index = 0;
int opt = wgetopt_long( argc,
argv,
L"pclgh",
long_options,
&opt_index );
if( opt == -1 )
break;
switch( opt )
{
case 0:
if(long_options[opt_index].flag != 0)
break;
sb_printf( sb_err,
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
sb_append( sb_err,
parser_current_line() );
builtin_print_help( argv[0], sb_err );
return 1;
case 'p':
mode=JOBS_PRINT_PID;
break;
case 'c':
mode=JOBS_PRINT_COMMAND;
break;
case 'g':
mode=JOBS_PRINT_GROUP;
break;
case 'l':
{
print_last = 1;
break;
}
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
}
}
/*
Do not babble if not interactive
*/
if( builtin_out_redirect )
{
found=1;
}
if( print_last )
{
/*
Ignore unconstructed jobs, i.e. ourself.
*/
for( j=first_job; j; j=j->next )
{
if( j->constructed && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
return 0;
}
}
}
else
{
if( woptind < argc )
{
int i;
found = 1;
for( i=woptind; i<argc; i++ )
{
long pid;
wchar_t *end;
errno=0;
pid=wcstol( argv[i], &end, 10 );
if( errno || *end )
{
sb_printf( sb_err,
_( L"%ls: '%ls' is not a job\n" ),
argv[0],
argv[i] );
return 1;
}
j = job_get_from_pid( pid );
if( j && !job_is_completed( j ) )
{
builtin_jobs_print( j, mode, !found );
}
else
{
sb_printf( sb_err,
_( L"%ls: No suitable job: %d\n" ),
argv[0],
pid );
return 1;
}
}
}
else
{
for( j= first_job; j; j=j->next )
{
/*
Ignore unconstructed jobs, i.e. ourself.
*/
if( j->constructed && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
found = 1;
}
}
}
}
if( !found )
{
sb_printf( sb_out,
_( L"%ls: There are no jobs\n" ),
argv[0] );
}
return 0;
}

View File

@@ -373,35 +373,47 @@ int builtin_set( wchar_t **argv )
{
{
L"export", no_argument, 0, 'x'
},
}
,
{
L"global", no_argument, 0, 'g'
},
}
,
{
L"local", no_argument, 0, 'l'
},
}
,
{
L"erase", no_argument, 0, 'e'
},
}
,
{
L"names", no_argument, 0, 'n'
} ,
}
,
{
L"unexport", no_argument, 0, 'u'
} ,
}
,
{
L"universal", no_argument, 0, 'U'
} ,
}
,
{
L"query", no_argument, 0, 'q'
} ,
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
}
;
const wchar_t *short_options = L"+xglenuUq";
const wchar_t *short_options = L"+xglenuUqh";
int argc = builtin_count_args(argv);
@@ -438,32 +450,47 @@ int builtin_set( wchar_t **argv )
{
case 0:
break;
case 'e':
erase = 1;
break;
case 'n':
list = 1;
break;
case 'x':
export = 1;
break;
case 'l':
local = 1;
break;
case 'g':
global = 1;
break;
case 'u':
unexport = 1;
break;
case 'U':
universal = 1;
break;
case 'q':
query = 1;
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
default:
break;
}
@@ -485,7 +512,7 @@ int builtin_set( wchar_t **argv )
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -498,7 +525,7 @@ int builtin_set( wchar_t **argv )
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -511,7 +538,7 @@ int builtin_set( wchar_t **argv )
BUILTIN_ERR_GLOCAL,
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -524,7 +551,7 @@ int builtin_set( wchar_t **argv )
BUILTIN_ERR_EXPUNEXP,
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -564,7 +591,7 @@ int builtin_set( wchar_t **argv )
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
retcode = 1;
}
else
@@ -655,7 +682,7 @@ int builtin_set( wchar_t **argv )
array_list_t result;
al_init(&result);
expand_variable_array( env_get(dest), &result );
tokenize_variable_array( env_get(dest), &result );
if( erase )
{
erase_values(&result, &indexes);

View File

@@ -63,13 +63,13 @@ const static struct resource_t resource_arr[] =
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024
}
,
#if HAVE_RLIMIT_MEMLOCK
#ifdef RLIMIT_MEMLOCK
{
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024
}
,
#endif
#if HAVE_RLIMIT_RSS
#ifdef RLIMIT_RSS
{
RLIMIT_RSS, L"Maximum resident set size", L'm', 1024
}
@@ -87,13 +87,13 @@ const static struct resource_t resource_arr[] =
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1
}
,
#if HAVE_RLIMIT_NPROC
#ifdef RLIMIT_NPROC
{
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1
}
,
#endif
#if HAVE_RLIMIT_AS
#ifdef RLIMIT_AS
{
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
}
@@ -326,6 +326,10 @@ int builtin_ulimit( wchar_t ** argv )
L"virtual-memory-size", no_argument, 0, 'v'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
@@ -337,7 +341,7 @@ int builtin_ulimit( wchar_t ** argv )
int opt = wgetopt_long( argc,
argv,
L"aHScdflmnptuv",
L"aHScdflmnptuvh",
long_options,
&opt_index );
if( opt == -1 )
@@ -379,13 +383,13 @@ int builtin_ulimit( wchar_t ** argv )
case L'f':
what=RLIMIT_FSIZE;
break;
#if HAVE_RLIMIT_MEMLOCK
#ifdef RLIMIT_MEMLOCK
case L'l':
what=RLIMIT_MEMLOCK;
break;
#endif
#if HAVE_RLIMIT_RSS
#ifdef RLIMIT_RSS
case L'm':
what=RLIMIT_RSS;
break;
@@ -403,18 +407,22 @@ int builtin_ulimit( wchar_t ** argv )
what=RLIMIT_CPU;
break;
#if HAVE_RLIMIT_NPROC
#ifdef RLIMIT_NPROC
case L'u':
what=RLIMIT_NPROC;
break;
#endif
#if HAVE_RLIMIT_AS
#ifdef RLIMIT_AS
case L'v':
what=RLIMIT_AS;
break;
#endif
case L'h':
builtin_print_help( argv[0], sb_out );
return 0;
case L'?':
builtin_print_help( argv[0], sb_err );
return 1;

View File

@@ -67,21 +67,6 @@ parts of fish.
*/
#define LOCKPOLLINTERVAL 10
/**
Highest legal ascii value
*/
#define ASCII_MAX 127u
/**
Highest legal 16-bit unicode value
*/
#define UCS2_MAX 0xffffu
/**
Highest legal byte value
*/
#define BYTE_MAX 0xffu
struct termios shell_modes;
int error_max=1;
@@ -562,9 +547,10 @@ void debug( int level, const wchar_t *msg, ... )
sb_init( &sb );
sb_init( &sb2 );
va_start( va, msg );
sb_printf( &sb, L"%ls: ", program_name );
va_start( va, msg );
sb_vprintf( &sb, msg, va );
va_end( va );
@@ -596,7 +582,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
*/
while( *pos && ( !wcschr( L" \n\r\t", *pos ) ) )
{
/*
Check is token is wider than one line.
If so we mark it as an overflow and break the token.
@@ -621,7 +607,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
else if( overflow )
{
/*
In case of overflow, we print a newline, except if we alreade are at position 0
In case of overflow, we print a newline, except if we already are at position 0
*/
wchar_t *token = wcsndup( start, pos-start );
if( line_width != 0 )
@@ -645,6 +631,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
free( token );
line_width += (line_width!=0?1:0) + tok_width;
}
/*
Break on end of string
*/
@@ -1418,3 +1405,29 @@ int common_get_height()
return termsize.ws_row;
}
void tokenize_variable_array( const wchar_t *val, array_list_t *out )
{
if( val )
{
wchar_t *cpy = wcsdup( val );
wchar_t *pos, *start;
if( !cpy )
{
die_mem();
}
for( start=pos=cpy; *pos; pos++ )
{
if( *pos == ARRAY_SEP )
{
*pos=0;
al_push( out, start==cpy?cpy:wcsdup(start) );
start=pos+1;
}
}
al_push( out, start==cpy?cpy:wcsdup(start) );
}
}

View File

@@ -20,22 +20,26 @@
*/
#define MAX_UTF8_BYTES 6
/**
Color code for set_color. Does not update the color.
*/
#define FISH_COLOR_IGNORE -1
/**
Color code for set_color. Sets the default color.
*/
#define FISH_COLOR_RESET -2
/**
This is in the unicode private use area.
*/
#define ENCODE_DIRECT_BASE 0xf100
/**
Highest legal ascii value
*/
#define ASCII_MAX 127u
/**
Highest legal 16-bit unicode value
*/
#define UCS2_MAX 0xffffu
/**
Highest legal byte value
*/
#define BYTE_MAX 0xffu
/**
Save the shell mode on startup so we can restore them on exit
*/
@@ -292,6 +296,16 @@ void common_handle_winch( int signal );
*/
void write_screen( const wchar_t *msg, string_buffer_t *buff );
/**
Tokenize the specified string into the specified array_list_t.
Each new element is allocated using malloc and must be freed by the
caller.
\param val the input string. The contents of this string is not changed.
\param out the list in which to place the elements.
*/
void tokenize_variable_array( const wchar_t *val, array_list_t *out );
#endif

View File

@@ -2023,9 +2023,28 @@ void complete( const wchar_t *cmd,
current_token = wcsndup( begin, cursor_pos-(begin-cmd) );
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 );
if( !had_cmd )
{
on_command=1;
}
if( !current_token )
{
current_token = wcsdup(L"");
}
if( !current_command )
{
current_command = wcsdup(L"");
}
if( !prev_token )
{
prev_token = wcsdup(L"");
}
if( current_token && current_command && prev_token )
{
if( on_command )
@@ -2045,14 +2064,14 @@ void complete( const wchar_t *cmd,
*/
int do_file;
do_file = complete_param( current_command, prev_token, current_token, comp );
complete_param_expand( current_token, comp, do_file );
}
}
}
free( current_token );
free( current_command );
free( prev_token );

View File

@@ -1,5 +1,5 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(fish,1.21.7,fish-users@lists.sf.net)
AC_INIT(fish,1.21.8,fish-users@lists.sf.net)
# If needed, run autoconf to regenerate the configure file
AC_MSG_CHECKING([if autoconf needs to be run])
@@ -326,53 +326,6 @@ if test "$ac_cv_func_fwprintf" = yes; then
fi
# Check for RLIMIT_NPROC in sys/resource.h.
AC_MSG_CHECKING([for RLIMIT_NPROC in sys/resource.h])
AC_TRY_COMPILE([#include <sys/resource.h>],
[int tmp; tmp=RLIMIT_NPROC;], have_rlimit_as=yes, have_rlimit_as=no)
if test "$have_rlimit_as" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RLIMIT_NPROC], [1],
[Define to 1 if HAVE_RLIMIT_NPROC is defined in <sys/resource.h>.])
else
AC_MSG_RESULT(no)
fi
# Check for RLIMIT_AS in sys/resource.h.
AC_MSG_CHECKING([for RLIMIT_AS in sys/resource.h])
AC_TRY_COMPILE([#include <sys/resource.h>],
[int tmp; tmp=RLIMIT_AS;], have_rlimit_as=yes, have_rlimit_as=no)
if test "$have_rlimit_as" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RLIMIT_AS], [1],
[Define to 1 if HAVE_RLIMIT_AS is defined in <sys/resource.h>.])
else
AC_MSG_RESULT(no)
fi
# Check for RLIMIT_MEMLOCK in sys/resource.h.
AC_MSG_CHECKING([for RLIMIT_MEMLOCK in sys/resource.h])
AC_TRY_COMPILE([#include <sys/resource.h>],
[int tmp; tmp=RLIMIT_MEMLOCK;], have_rlimit_as=yes, have_rlimit_as=no)
if test "$have_rlimit_as" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RLIMIT_MEMLOCK], [1],
[Define to 1 if HAVE_RLIMIT_MEMLOCK is defined in <sys/resource.h>.])
else
AC_MSG_RESULT(no)
fi
# Check for RLIMIT_RSS in sys/resource.h.
AC_MSG_CHECKING([for RLIMIT_RSS in sys/resource.h])
AC_TRY_COMPILE([#include <sys/resource.h>],
[int tmp; tmp=RLIMIT_RSS;], have_rlimit_as=yes, have_rlimit_as=no)
if test "$have_rlimit_as" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RLIMIT_RSS], [1],
[Define to 1 if HAVE_RLIMIT_RSS is defined in <sys/resource.h>.])
else
AC_MSG_RESULT(no)
fi
# Check for _nl_msg_cat_cntr symbol
AC_MSG_CHECKING([for _nl_msg_cat_cntr symbol])

View File

@@ -49,12 +49,12 @@ has to be used.
Here is a list of some useful commands:
- \c cd, change the current directory
- \c ls, list the contents of a directory
- \c man, print a manual page
- \c mv, move files
- \c ls, list files and directories
- \c man, display a manual page on the screen
- \c mv, move (rename) files
- \c cp, copy files
- \c open, open files with the default application associated with each filetype
- \c less, read the contents of files
- \c less, list the contents of files
Commands and parameters are separated by the space character
(&nbsp;). Every command ends with either a newline (i.e. by pressing
@@ -68,10 +68,10 @@ and directories in the current working directory, but by using the \c
-l switch, the behaviour of ls is changed to not only display the
filename, but also the size, permissions, owner and modification time
of each file. Switches differ between commands and are documented in
the manual page for each command. Some switches are very common
though, for example '--help' will usually display a help text, '-i'
will often turn on interactive prompting before taking action, while
'-f' will turn it off.
the manual page for each command. Some switches are common to most
command though, for example '--help' will usually display a help text,
'-i' will often turn on interactive prompting before taking action,
while '-f' will turn it off.
\subsection quotes Quotes
@@ -116,6 +116,7 @@ these characters, so called escape sequences are provided. These are:
- <code>'\\*'</code>, escapes the star character
- <code>'\\?'</code>, escapes the question mark character
- <code>'\\~'</code>, escapes the tilde character
- <code>'\\%'</code>, escapes the percent character
- <code>'\\#'</code>, escapes the hash character
- <code>'\\('</code>, escapes the left parenthesis character
- <code>'\\)'</code>, escapes the right parenthesis character
@@ -540,6 +541,7 @@ a string is expanded into a process id. The following expansions are
performed:
- If the string is the entire word \c self, the shells pid is the result
- When inside a command substitution, if the string is the entire word \c caller, the job number (not the pid) of the job the created the command substitution is the result
- Otherwise, if the string is the id of a job, the result is the process
group id of the job.
- Otherwise, if any child processes match the specified string, their
@@ -752,7 +754,8 @@ certain environment variables.
- \c BROWSER, which is the users preferred web browser. If this variable is set, fish will use the specified browser instead of the system default browser to display the fish documentation.
- \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.
- A large number of variable starting with the prefixes \c fish_color and \c fish_pager_color. See <a href='#variables-color'>Variables for changing highlighting colors</a> for more information.
- \c LANG, \c LC_ALL, \c LC_COLLATE, \c LC_CTYPE, \c LC_MESSAGES, \c LC_MONETARY, \c LC_NUMERIC and \c LC_TIME set the language option for the shell and subprograms. See the section <a href='#variables-locale'>Locale variables</a> for more information.
- \c PATH, which is an array of directories in which to search for commands
- \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.
@@ -767,7 +770,6 @@ values of most of these variables.
- \c PWD, which is the current working directory.
- \c status, which is the exit status of the last foreground job to exit. If a job contains pipelines, the status of the last command in the pipeline is the status for the job.
- \c USER, which is the username. This variable can only be changed by the root user.
- \c LANG, \c LC_ALL, \c LC_COLLATE, \c LC_CTYPE, \c LC_MESSAGES, \c LC_MONETARY, \c LC_NUMERIC and \c LC_TIME set the language option for the shell and subprograms. See the section <a href='#variables-locale'>Locale variables</a> for more information.
Variables whose name are in uppercase are exported to the commands
started by fish, those in lowercase are not exported. This rule is not
@@ -776,6 +778,45 @@ distinguish between exported and unexported variables. \c fish also
uses several variables internally. Such variables are prefixed with
the string __FISH or __fish. These should be ignored by the user.
\subsection variables-color Variables for changing highlighting colors
The colors used by fish for syntax highlighting can be configured by
changing the values of a various variables. The value of these
variables can be one of the colors accepted by the <a
href='commands.html#set_color'>\c set_color</a> command. The \c --bold
or \c -b switches accepted by \c set_color are also accepted.
The following variables are available to change the highligting colors
in fish:
- \c fish_color_normal, the default color
- \c fish_color_command, the color for commands
- \c fish_color_quote, the color for quoted blocks of text
- \c fish_color_redirection, the color for IO redirections
- \c fish_color_end, the color for process separators like ';' and '&'
- \c fish_color_error, the color used to highlight potential errors
- \c fish_color_param, the color for regular command parameters
- \c fish_color_comment, the color used for code comments
- \c fish_color_match, the color used to highlight matching parenthesis
- \c fish_color_search_match, the color used to highlight history search matches
- \c fish_color_operator, the color for parameter expansion operators like '*' and '~'
- \c fish_color_escape, the color used to highlight character escapes like '\\n' and '\\x70'
- \c fish_color_cwd, the color used for the current working directory in the default prompt
Additionally, the following variables are available to change the
highlighting in the completion pager:
- \c fish_pager_color_prefix, the color of the prefix string, i.e. the string that is to be completed
- \c fish_pager_color_completion, the color of the completion itself
- \c fish_pager_color_description, the color of the completion description
- \c fish_pager_color_progress, the color of the progress bar at the bottom left corner
Example:
To make errors highlighted and red, use:
<code>set fish_color_error red --bold</code>D
\subsection variables-locale Locale variables
The most common way to set the locale to use a command like 'set -x
@@ -1197,12 +1238,9 @@ compress, wine, xmms, dig, wine, batch, cron,
g++, javac, java, gcj, lpr, doxygen, whois, find)
- Undo support
- Check keybinding commands for output - if nothing 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
- Support for the screen clipboard
- The -a string sent to complete should be validated
- Fish should detect improper variable expansion when validating, e.g. strings such as 'foo$' and 'a${}' should be detected as invalid
\subsection todo-possible Possible features
@@ -1220,7 +1258,6 @@ g++, javac, java, gcj, lpr, doxygen, whois, find)
- Inclusion guards for the init files to make them evaluate only once, even if the user has installed fish both in /etc and in $HOME
- Do not actually load/parse .fish_history, only mmap it and use some clever string handling. Should save ~150 kB of memory permanently, but is very hard to implement.
- command specific wildcarding (use case * instead of case '*', etc.)
- show the whole list of commands on using tab on an empty commandline
- 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

View File

@@ -3,6 +3,10 @@
\subsection set-synopsis Synopsis
<code>set [OPTIONS] [VARIABLE_NAME [VALUES...]]</code>
or
<code>set [OPTIONS] [VARIABLE_NAME[INDICES]... [VALUES...]]</code>
The <code>set</code> builtin causes fish to assign the variable <code>VARIABLE_NAME</code> the values <code>VALUES...</code>.
\subsection set-description Description
@@ -29,7 +33,9 @@ elements, it will become an array with zero elements.
If the variable name is one or more array elements, such as
<code>PATH[1 3 7]</code>, only those array elements specified will be
changed.
changed. When array indices are specified to set, multiple arguments
may be used to specify additional indexes, e.g. <code>set PATH[1]
PATH[4] /bin /sbin</code>.
The set command requires all switch arguments to come before any
non-switch arguments. For example, <code>set flags -l</code> will have

24
env.c
View File

@@ -396,7 +396,7 @@ static void setup_path()
al_init( &l );
if( path )
expand_variable_array( path, &l );
tokenize_variable_array( path, &l );
for( j=0; path_el[j]; j++ )
{
@@ -438,7 +438,7 @@ static void setup_path()
al_foreach( &l, (void (*)(const void *))&free );
path = env_get( L"PATH" );
al_truncate( &l, 0 );
expand_variable_array( path, &l );
tokenize_variable_array( path, &l );
}
}
@@ -797,6 +797,7 @@ int env_set( const wchar_t *key,
al_init( &ev.arguments );
al_push( &ev.arguments, L"VARIABLE" );
al_push( &ev.arguments, L"SET" );
al_push( &ev.arguments, key );
// debug( 1, L"env_set: fire events on variable %ls", key );
@@ -817,6 +818,8 @@ int env_set( const wchar_t *key,
/**
Attempt to remove/free the specified key/value pair from the
specified hash table.
\return zero if the variable was not found, non-zero otherwise
*/
static int try_remove( env_node_t *n,
const wchar_t *key )
@@ -862,7 +865,22 @@ void env_remove( const wchar_t *key, int var_mode )
return;
}
if( !try_remove( top, key ) )
if( try_remove( top, key ) )
{
event_t ev;
ev.type=EVENT_VARIABLE;
ev.param1.variable=key;
ev.function_name=0;
al_init( &ev.arguments );
al_push( &ev.arguments, L"VARIABLE" );
al_push( &ev.arguments, L"ERASE" );
al_push( &ev.arguments, key );
event_fire( &ev );
al_destroy( &ev.arguments );
}
else
{
env_universal_remove( key );
}

View File

@@ -68,8 +68,11 @@ end
set_default fish_color_normal normal
set_default fish_color_command green
set_default fish_color_redirection normal
set_default fish_color_comment brown
set_default fish_color_error red
set_default fish_color_comment red
set_default fish_color_error red --bold
set_default fish_color_escape cyan
set_default fish_color_operator cyan
set_default fish_color_quote brown
set_default fish_color_cwd green

142
expand.c
View File

@@ -76,27 +76,6 @@ parameter expansion.
*/
#define COMPLETE_LAST_DESC _( L"Last background job")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean {$VARIABLE}? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
/**
String in process expansion denoting ourself
*/
@@ -117,15 +96,7 @@ parameter expansion.
*/
#define UNCLEAN L"$*?\\\"'({})"
/**
Test if the specified argument is clean, i.e. it does not contain
any tokens which need to be expanded or otherwise altered. Clean
strings can be passed through expand_string and expand_one without
changing them. About 90% of all strings are clean, so skipping
expansion on them actually does save a small amount of time, since
it avoids multiple memory allocations during the expansion process.
*/
static int is_clean( const wchar_t *in )
int expand_is_clean( const wchar_t *in )
{
const wchar_t * str = in;
@@ -159,32 +130,6 @@ static wchar_t *expand_var( wchar_t *in )
return env_get( in );
}
void expand_variable_array( const wchar_t *val, array_list_t *out )
{
if( val )
{
wchar_t *cpy = wcsdup( val );
wchar_t *pos, *start;
if( !cpy )
{
die_mem();
}
for( start=pos=cpy; *pos; pos++ )
{
if( *pos == ARRAY_SEP )
{
*pos=0;
al_push( out, start==cpy?cpy:wcsdup(start) );
start=pos+1;
}
}
al_push( out, start==cpy?cpy:wcsdup(start) );
}
}
/**
Test if the specified string does not contain character which can
not be used inside a quoted string.
@@ -217,7 +162,7 @@ wchar_t *expand_escape_variable( const wchar_t *in )
string_buffer_t buff;
al_init( &l );
expand_variable_array( in, &l );
tokenize_variable_array( in, &l );
sb_init( &buff );
switch( al_get_count( &l) )
@@ -225,7 +170,7 @@ wchar_t *expand_escape_variable( const wchar_t *in )
case 0:
sb_append( &buff, L"''");
break;
case 1:
{
wchar_t *el = (wchar_t *)al_get( &l, 0 );
@@ -281,28 +226,19 @@ wchar_t *expand_escape_variable( const wchar_t *in )
}
/**
Tests if all characters in the string are numeric
*/
static int isnumeric( const char *n )
{
if( *n == '\0' )
return 1;
if( *n < '0' || *n > '9' )
return 0;
return isnumeric( n+1 );
}
/**
Tests if all characters in the wide string are numeric
*/
static int iswnumeric( const wchar_t *n )
{
if( *n == L'\0' )
return 1;
if( *n < L'0' || *n > L'9' )
return 0;
return iswnumeric( n+1 );
for( ; *n; n++ )
{
if( *n < L'0' || *n > L'9' )
{
return 0;
}
}
return 1;
}
/**
@@ -377,9 +313,9 @@ static int find_process( const wchar_t *proc,
array_list_t *out )
{
DIR *dir;
struct dirent *next;
char *pdir_name;
char *pfile_name;
struct wdirent *next;
wchar_t *pdir_name;
wchar_t *pfile_name;
wchar_t *cmd=0;
int sz=0;
int found = 0;
@@ -515,20 +451,20 @@ static int find_process( const wchar_t *proc,
return 1;
}
pdir_name = malloc( 256 );
pfile_name = malloc( 64 );
strcpy( pdir_name, "/proc/" );
while( (next=readdir(dir))!=0 )
pdir_name = malloc( sizeof(wchar_t)*256 );
pfile_name = malloc( sizeof(wchar_t)*64 );
wcscpy( pdir_name, L"/proc/" );
while( (next=wreaddir(dir))!=0 )
{
char *name = next->d_name;
wchar_t *name = next->d_name;
struct stat buf;
if( !isnumeric( name ) )
if( !iswnumeric( name ) )
continue;
strcpy( pdir_name + 6, name );
if( stat( pdir_name, &buf ) )
wcscpy( pdir_name + 6, name );
if( wstat( pdir_name, &buf ) )
{
continue;
}
@@ -536,17 +472,17 @@ static int find_process( const wchar_t *proc,
{
continue;
}
strcpy( pfile_name, pdir_name );
strcat( pfile_name, "/cmdline" );
wcscpy( pfile_name, pdir_name );
wcscat( pfile_name, L"/cmdline" );
if( !stat( pfile_name, &buf ) )
if( !wstat( pfile_name, &buf ) )
{
/*
the 'cmdline' file exists, it should contain the commandline
*/
FILE *cmdfile;
if((cmdfile=fopen( pfile_name, "r" ))==0)
if((cmdfile=wfopen( pfile_name, "r" ))==0)
{
wperror( L"fopen" );
continue;
@@ -561,15 +497,15 @@ static int find_process( const wchar_t *proc,
else
{
#ifdef SunOS
strcpy( pfile_name, pdir_name );
strcat( pfile_name, "/psinfo" );
if( !stat( pfile_name, &buf ) )
wcscpy( pfile_name, pdir_name );
wcscat( pfile_name, L"/psinfo" );
if( !wstat( pfile_name, &buf ) )
{
psinfo_t info;
FILE *psfile;
if((psfile=fopen( pfile_name, "r" ))==0)
if((psfile=wfopen( pfile_name, "r" ))==0)
{
wperror( L"fopen" );
continue;
@@ -608,7 +544,7 @@ static int find_process( const wchar_t *proc,
}
else
{
wchar_t *res = str2wcs(name);
wchar_t *res = wcsdup(name);
if( res )
al_push( out, res );
}
@@ -804,8 +740,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
{
error( SYNTAX_ERROR,
-1,
COMPLETE_VAR_NULL_DESC,
in[stop_pos] );
COMPLETE_VAR_NULL_DESC );
break;
}
@@ -873,7 +808,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
if( is_ok )
{
expand_variable_array( var_val, &var_item_list );
tokenize_variable_array( var_val, &var_item_list );
if( !all_vars )
{
int j;
@@ -1403,7 +1338,6 @@ static void remove_internal_separator( const void *s, int conv )
*out=0;
}
/**
The real expansion function. expand_one is just a wrapper around this one.
*/
@@ -1420,9 +1354,7 @@ int expand_string( void *context,
int res = EXPAND_OK;
int start_count = al_get_count( end_out );
// debug( 1, L"Expand %ls", str );
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( str ) )
{
halloc_register( context, str );
al_push( end_out, str );
@@ -1667,8 +1599,8 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
array_list_t l;
int res;
wchar_t *one;
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( string ) )
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string ) )
{
halloc_register( context, string );
return string;

View File

@@ -112,6 +112,27 @@ enum
/** String containing the character for separating two array elements */
#define ARRAY_SEP_STR L"\x1e"
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean {$VARIABLE}? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
/**
@@ -158,13 +179,14 @@ wchar_t *expand_tilde(wchar_t *in);
/**
Tokenize the specified string into the specified array_list_t.
Each new element is allocated using malloc and must be freed by the
caller.
\param val the input string. The contents of this string is not changed.
\param out the list in which to place the elements.
Test if the specified argument is clean, i.e. it does not contain
any tokens which need to be expanded or otherwise altered. Clean
strings can be passed through expand_string and expand_one without
changing them. About two thirds of all strings are clean, so
skipping expansion on them actually does save a small amount of
time, since it avoids multiple memory allocations during the
expansion process.
*/
void expand_variable_array( const wchar_t *val, array_list_t *out );
int expand_is_clean( const wchar_t *in );
#endif

View File

@@ -990,9 +990,12 @@ int main( int argc, char **argv )
fwprintf( out_file, L"%ls", (wchar_t *)out_buff.buff );
if( is_ca_mode )
{
writembs(exit_ca_mode);
pager_flush();
}
}
destroy();
}

View File

@@ -110,6 +110,11 @@ time the original barrier request was sent have been received.
*/
#define LOCKTIMEOUT 1
/**
Getopt short switches for fishd
*/
#define GETOPT_STRING "hv"
/**
The list of connections to clients
*/
@@ -502,14 +507,14 @@ int main( int argc, char ** argv )
int opt = getopt_long( argc,
argv,
"hv",
GETOPT_STRING,
long_options,
&opt_index );
#else
int opt = getopt( argc,
argv,
"hv" );
GETOPT_STRING );
#endif
if( opt == -1 )
break;

View File

@@ -87,7 +87,7 @@ static void autoload_names( array_list_t *out, int get_hidden )
al_init( &path_list );
expand_variable_array( path_var, &path_list );
tokenize_variable_array( path_var, &path_list );
for( i=0; i<al_get_count( &path_list ); i++ )
{
wchar_t *ndir = (wchar_t *)al_get( &path_list, i );

View File

@@ -40,11 +40,10 @@ static void highlight_universal_internal( wchar_t * buff,
/**
The environment variables used to specify the color of different tokens.
*/
static wchar_t *hightlight_var[] =
static wchar_t *highlight_var[] =
{
L"fish_color_normal",
L"fish_color_command",
L"fish_color_subshell",
L"fish_color_redirection",
L"fish_color_end",
L"fish_color_error",
@@ -52,24 +51,24 @@ static wchar_t *hightlight_var[] =
L"fish_color_comment",
L"fish_color_match",
L"fish_color_search_match",
L"fish_color_pager_prefix",
L"fish_color_pager_completion",
L"fish_color_pager_description",
L"fish_color_pager_progress"
L"fish_color_operator",
L"fish_color_escape",
L"fish_color_quote"
}
;
#define VAR_COUNT ( sizeof(highlight_var)/sizeof(wchar_t *) )
int highlight_get_color( int highlight )
{
if( highlight < 0 )
return FISH_COLOR_NORMAL;
if( highlight >= (12) )
if( highlight >= VAR_COUNT )
return FISH_COLOR_NORMAL;
wchar_t *val = env_get( hightlight_var[highlight]);
wchar_t *val = env_get( highlight_var[highlight]);
if( val == 0 )
val = env_get( hightlight_var[HIGHLIGHT_NORMAL]);
val = env_get( highlight_var[HIGHLIGHT_NORMAL]);
if( val == 0 )
{
@@ -79,6 +78,289 @@ int highlight_get_color( int highlight )
return output_color_code( val );
}
/**
Highligt operators (such as $, ~, %, as well as escaped characters.
*/
static void highlight_param( const wchar_t * buff,
int *color,
int pos,
array_list_t *error )
{
int mode = 0;
int in_pos, len = wcslen( buff );
int bracket_count=0;
wchar_t c;
for( in_pos=0;
in_pos<len;
in_pos++ )
{
c = buff[in_pos];
switch( mode )
{
/*
Mode 0 means unquoted string
*/
case 0:
{
if( c == L'\\' )
{
int start_pos = in_pos;
in_pos++;
if( wcschr( L"~%", buff[in_pos] ) )
{
if( in_pos == 1 )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_NORMAL;
}
}
else if( buff[in_pos]==L',' )
{
if( bracket_count )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_NORMAL;
}
}
else if( wcschr( L"nrtbe*?$(){}'\"<>^ \\#;|&", buff[in_pos] ) )
{
color[start_pos]=HIGHLIGHT_ESCAPE;
color[in_pos+1]=HIGHLIGHT_NORMAL;
}
else if( wcschr( L"uUxX01234567", buff[in_pos] ) )
{
int i;
long long res=0;
int chars=2;
int base=16;
int byte = 0;
wchar_t max_val = ASCII_MAX;
switch( buff[in_pos] )
{
case L'u':
{
chars=4;
max_val = UCS2_MAX;
break;
}
case L'U':
{
chars=8;
max_val = WCHAR_MAX;
break;
}
case L'x':
{
break;
}
case L'X':
{
byte=1;
max_val = BYTE_MAX;
break;
}
default:
{
base=8;
chars=3;
in_pos--;
break;
}
}
for( i=0; i<chars; i++ )
{
int d = convert_digit( buff[++in_pos],base);
if( d < 0 )
{
in_pos--;
break;
}
res=(res*base)|d;
}
if( (res <= max_val) )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_NORMAL;
}
else
{
color[start_pos] = HIGHLIGHT_ERROR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
}
}
}
else
{
switch( buff[in_pos]){
case L'~':
case L'%':
{
if( in_pos == 0 )
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
}
break;
}
case L'*':
case L'?':
case L'$':
case L'(':
case L')':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
break;
}
case L'{':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
bracket_count++;
break;
}
case L'}':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
bracket_count--;
break;
}
case L',':
{
if( bracket_count )
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
}
break;
}
case L'\'':
{
color[in_pos] = HIGHLIGHT_QUOTE;
mode = 1;
break;
}
case L'\"':
{
color[in_pos] = HIGHLIGHT_QUOTE;
mode = 2;
break;
}
}
}
break;
}
/*
Mode 1 means single quoted string, i.e 'foo'
*/
case 1:
{
if( c == L'\\' )
{
int start_pos = in_pos;
switch( buff[++in_pos] )
{
case '\\':
case L'\'':
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_QUOTE;
break;
}
case 0:
{
return;
}
}
}
if( c == L'\'' )
{
mode = 0;
color[in_pos+1] = HIGHLIGHT_NORMAL;
}
break;
}
/*
Mode 2 means double quoted string, i.e. "foo"
*/
case 2:
{
switch( c )
{
case '"':
{
mode = 0;
color[in_pos+1] = HIGHLIGHT_NORMAL;
break;
}
case '\\':
{
int start_pos = in_pos;
switch( buff[++in_pos] )
{
case L'\0':
{
return;
}
case '\\':
case L'$':
case '"':
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_QUOTE;
break;
}
}
break;
}
case '$':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_QUOTE;
break;
}
}
break;
}
}
}
}
void highlight_shell( wchar_t * buff,
int *color,
@@ -125,6 +407,12 @@ void highlight_shell( wchar_t * buff,
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_PARAM;
}
highlight_param( param,
&color[tok_get_pos( &tok )],
pos-tok_get_pos( &tok ),
error );
}
else
{
@@ -383,7 +671,7 @@ void highlight_shell( wchar_t * buff,
*end=0;
highlight_shell( begin+1, color +(begin-buffcpy)+1, -1, error );
color[end-buffcpy]=HIGHLIGHT_PARAM;
color[end-buffcpy]=HIGHLIGHT_OPERATOR;
if( done )
break;

View File

@@ -88,6 +88,11 @@ license. Read the source code of the library for more information.
*/
#define MIMEDB "mimedb"
/**
Getopt short switches for mimedb
*/
#define GETOPT_STRING "tfimdalhv"
/**
All types of input and output possible
*/
@@ -1216,14 +1221,14 @@ int main (int argc, char *argv[])
int opt = getopt_long( argc,
argv,
"tfimdalhv",
GETOPT_STRING,
long_options,
&opt_index );
#else
int opt = getopt( argc,
argv,
"tfimdalhv" );
GETOPT_STRING );
#endif
if( opt == -1 )
break;

View File

@@ -128,9 +128,20 @@ void set_color( int c, int c2 )
{
static int last_color = FISH_COLOR_NORMAL;
static int last_color2 = FISH_COLOR_NORMAL;
static int was_bold=0;
int bg_set=0, last_bg_set=0;
char *fg = 0, *bg=0;
int is_bold = 0;
is_bold |= (c&FISH_COLOR_BOLD)!=0;
is_bold |= (c2&FISH_COLOR_BOLD)!=0;
// debug( 1, L"WOO %d %d %d", is_bold, c&FISH_COLOR_BOLD,c2&FISH_COLOR_BOLD);
c = c&(~FISH_COLOR_BOLD);
c2 = c2&(~FISH_COLOR_BOLD);
if( (set_a_foreground != 0) && (strlen( set_a_foreground) != 0 ) )
{
fg = set_a_foreground;
@@ -145,14 +156,31 @@ void set_color( int c, int c2 )
if( (c == FISH_COLOR_RESET) || (c2 == FISH_COLOR_RESET))
{
c = c2 = FISH_COLOR_NORMAL;
was_bold=0;
if( fg )
{
/*
If we exit attibute mode, we must first set a color, or
previously coloured text might lose it's
color. Terminals are weird...
*/
writembs( tparm( fg, 0 ) );
}
writembs( exit_attribute_mode );
return;
}
if( was_bold && !is_bold )
{
/*
Only way to exit bold mode is a reset of all attributes.
*/
writembs( exit_attribute_mode );
last_color = FISH_COLOR_NORMAL;
last_color2 = FISH_COLOR_NORMAL;
was_bold=0;
}
if( last_color2 != FISH_COLOR_NORMAL &&
last_color2 != FISH_COLOR_RESET &&
last_color2 != FISH_COLOR_IGNORE )
@@ -164,7 +192,6 @@ void set_color( int c, int c2 )
}
if( c2 != FISH_COLOR_NORMAL &&
c2 != FISH_COLOR_RESET &&
c2 != FISH_COLOR_IGNORE )
{
/*
@@ -180,7 +207,8 @@ void set_color( int c, int c2 )
{
/*
Background color changed and is set, so we enter bold
mode to make reading easier
mode to make reading easier. This means bold mode is
_always_ on when the background color is set.
*/
writembs( enter_bold_mode );
}
@@ -252,8 +280,21 @@ void set_color( int c, int c2 )
last_color2 = c2;
}
}
/*
Lastly, we set bold mode correctly
*/
if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0) && !bg_set )
{
if( is_bold && !was_bold )
{
writembs( tparm( enter_bold_mode ) );
}
was_bold = is_bold;
}
}
/**
perm_left_cursor and parm_right_cursor don't seem to be properly
emulated by many terminal emulators, so we only use plain
@@ -475,23 +516,37 @@ int writespace( int c )
int output_color_code( const wchar_t *val )
{
int i, color=-1;
int j, i, color=FISH_COLOR_NORMAL;
array_list_t el;
int is_bold=0;
for( i=0; i<COLORS; i++ )
{
if( wcscasecmp( col[i], val ) == 0 )
{
color = col_idx[i];
break;
}
}
if( color >= 0 )
{
return color;
}
else
{
if( !val )
return FISH_COLOR_NORMAL;
al_init( &el );
tokenize_variable_array( val, &el );
for( j=0; j<al_get_count( &el ); j++ )
{
wchar_t *next = (wchar_t *)al_get( &el, j );
is_bold |= (wcsncmp( next, L"--bold", wcslen(next) ) == 0 ) && wcslen(next)>=3;
is_bold |= wcscmp( next, L"-b" ) == 0;
for( i=0; i<COLORS; i++ )
{
if( wcscasecmp( col[i], next ) == 0 )
{
color = col_idx[i];
break;
}
}
}
al_foreach( &el, (void (*)(const void *))&free );
al_destroy( &el );
return color | (is_bold?FISH_COLOR_BOLD:0);
}

View File

@@ -14,7 +14,6 @@ enum
{
HIGHLIGHT_NORMAL,
HIGHLIGHT_COMMAND,
HIGHLIGHT_SUBSHELL,
HIGHLIGHT_REDIRECTION,
HIGHLIGHT_END,
HIGHLIGHT_ERROR,
@@ -22,6 +21,9 @@ enum
HIGHLIGHT_COMMENT,
HIGHLIGHT_MATCH,
HIGHLIGHT_SEARCH_MATCH,
HIGHLIGHT_OPERATOR,
HIGHLIGHT_ESCAPE,
HIGHLIGHT_QUOTE,
}
;
@@ -39,10 +41,13 @@ enum
FISH_COLOR_CYAN,
FISH_COLOR_WHITE,
/** The default fg color of the terminal */
FISH_COLOR_NORMAL
FISH_COLOR_NORMAL,
FISH_COLOR_IGNORE,
FISH_COLOR_RESET
}
;
#define FISH_COLOR_BOLD 0x80
/**
Sets the fg and bg color. May be called as often as you like, since

View File

@@ -558,7 +558,7 @@ int parse_util_load( const wchar_t *cmd,
else
sb_clear( path );
expand_variable_array( path_var, path_list );
tokenize_variable_array( path_var, path_list );
/*
Iterate over path searching for suitable completion files

485
parser.c
View File

@@ -76,7 +76,7 @@ The fish parser. Contains functions for parsing code.
/**
Error message for short circuit command error.
*/
#define COND_ERR_MSG _( L"Short circuit command requires additional command")
#define COND_ERR_MSG _( L"Pipe or short circuit command requires additional command")
/**
Error message on reaching maximum recusrion depth
@@ -252,6 +252,10 @@ The fish parser. Contains functions for parsing code.
#define UNKNOWN_BLOCK _( L"unknown/invalid block" )
/**
Size of the error string buffer
*/
#define ERR_STR_SZ 1024
/** Last error code */
int error_code;
@@ -262,7 +266,7 @@ event_block_t *global_event_block=0;
static int err_pos;
/** Description of last error */
static wchar_t err_str[256];
static wchar_t err_str[ERR_STR_SZ];
/** Pointer to the current tokenizer */
static tokenizer *current_tokenizer;
@@ -698,7 +702,7 @@ void error( int ec, int p, const wchar_t *str, ... )
err_pos = p;
va_start( va, str );
vswprintf( err_str, 256, str, va );
vswprintf( err_str, ERR_STR_SZ, str, va );
va_end( va );
}
@@ -1976,7 +1980,7 @@ static int parse_job( process_t *p,
tmp = (wchar_t *)al_get( args, 0 );
al_truncate( args, 0 );
al_push( args, wcsdup( L"cd" ) );
al_push( args, halloc_wcsdup( j, L"cd" ) );
al_push( args, tmp );
/*
If we have defined a wrapper around cd, use it,
@@ -1994,7 +1998,7 @@ static int parse_job( process_t *p,
/*
We couln't find the specified command.
What we want to happen now is that the
specified job won't get executed, and an
error message is printed on-screen, but
@@ -2542,11 +2546,258 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
return code;
}
int parser_test( wchar_t * buff,
static int parser_get_block_type( const wchar_t *cmd )
{
if( wcscmp( cmd, L"while") == 0 )
return WHILE;
else if( wcscmp( cmd, L"for") == 0 )
return FOR;
else if( wcscmp( cmd, L"switch") == 0 )
return SWITCH;
else if( wcscmp( cmd, L"if") == 0 )
return IF;
else if( wcscmp( cmd, L"function") == 0 )
return FUNCTION_DEF;
else if( wcscmp( cmd, L"begin") == 0 )
return BEGIN;
else
return -1;
}
static int parser_test_argument( const wchar_t *arg, int babble, int offset )
{
wchar_t *unesc;
wchar_t *pos;
int err=0;
const wchar_t *paran_begin, *paran_end;
wchar_t *arg_cpy = wcsdup( arg );
int do_loop = 1;
while( do_loop )
{
switch( parse_util_locate_cmdsubst(arg_cpy,
&paran_begin,
&paran_end,
0 ) )
{
case -1:
err=1;
if( babble )
{
error( SYNTAX_ERROR,
offset,
L"Mismatched parans" );
print_errors();
}
free( arg_cpy );
return 1;
case 0:
do_loop = 0;
break;
case 1:
{
wchar_t *subst = wcsndup( paran_begin+1, paran_end-paran_begin-1 );
string_buffer_t tmp;
sb_init( &tmp );
sb_append_substring( &tmp, arg_cpy, paran_begin - arg_cpy);
sb_append_char( &tmp, INTERNAL_SEPARATOR);
sb_append( &tmp, paran_end+1);
// debug( 1, L"%ls -> %ls %ls", arg_cpy, subst, tmp.buff );
err |= parser_test( subst, babble );
free( subst );
free( arg_cpy );
arg_cpy = (wchar_t *)tmp.buff;
/*
Do _not_ call sb_destroy on this stringbuffer - it's
buffer is used as the new 'arg_cpy'. It is free'd at
the end of the loop.
*/
break;
}
}
}
unesc = unescape( arg_cpy, 1 );
free( arg_cpy );
/*
Check for invalid variable expansions
*/
for( pos = unesc; *pos; pos++ )
{
switch( *pos )
{
case VARIABLE_EXPAND:
case VARIABLE_EXPAND_SINGLE:
{
switch( *(pos+1))
{
case BRACKET_BEGIN:
{
err=1;
if( babble )
{
error( SYNTAX_ERROR,
offset,
COMPLETE_VAR_BRACKET_DESC );
print_errors();
}
break;
}
case INTERNAL_SEPARATOR:
{
err=1;
if( babble )
{
error( SYNTAX_ERROR,
offset,
COMPLETE_VAR_PARAN_DESC );
print_errors();
}
break;
}
case 0:
{
err=1;
if( babble )
{
error( SYNTAX_ERROR,
offset,
COMPLETE_VAR_NULL_DESC );
print_errors();
}
break;
}
default:
{
if( !iswalnum(*(pos+1)) &&
*(pos+1)!=L'_' &&
*(pos+1)!=VARIABLE_EXPAND &&
*(pos+1)!=VARIABLE_EXPAND_SINGLE )
{
err=1;
if( babble )
{
error( SYNTAX_ERROR,
offset,
COMPLETE_VAR_DESC,
*(pos+1) );
print_errors();
}
}
break;
}
}
break;
}
}
}
free( unesc );
return err;
}
int parser_test_args(const wchar_t * buff,
int babble )
{
tokenizer tok;
tokenizer *previous_tokenizer = current_tokenizer;
int previous_pos = current_tokenizer_pos;
int do_loop = 1;
int err = 0;
current_tokenizer = &tok;
for( tok_init( &tok, buff, 0 );
do_loop && tok_has_next( &tok );
tok_next( &tok ) )
{
current_tokenizer_pos = tok_get_pos( &tok );
switch( tok_last_type( &tok ) )
{
case TOK_STRING:
{
err |= parser_test_argument( tok_last( &tok ), babble, tok_get_pos( &tok ) );
break;
}
case TOK_END:
{
break;
}
case TOK_ERROR:
{
if( babble )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
TOK_ERR_MSG,
tok_last(&tok) );
print_errors();
}
err=1;
do_loop=0;
break;
}
default:
{
if( babble )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
UNEXPECTED_TOKEN_ERR_MSG,
tok_get_desc( tok_last_type(&tok)) );
print_errors();
}
err=1;
do_loop=0;
break;
}
}
}
tok_destroy( &tok );
current_tokenizer=previous_tokenizer;
current_tokenizer_pos = previous_pos;
error_code=0;
return err;
}
int parser_test( const wchar_t * buff,
int babble )
{
tokenizer tok;
int had_cmd=0;
/*
Set to one if a command name has been given for the currently
parsed process specification
*/
int had_cmd=0;
int count = 0;
int err=0;
tokenizer *previous_tokenizer=current_tokenizer;
@@ -2554,10 +2805,18 @@ int parser_test( wchar_t * buff,
static int block_pos[BLOCK_MAX_COUNT];
static int block_type[BLOCK_MAX_COUNT];
int is_pipeline = 0;
/*
Set to one if the currently specified process can not be used inside a pipeline
*/
int forbid_pipeline = 0;
int needs_cmd=0;
int require_additional_commands=0;
/*
Set to one if an additional process specification is needed
*/
int needs_cmd=0;
void *context = halloc( 0, 0 );
int arg_count=0;
wchar_t *cmd=0;
current_tokenizer = &tok;
for( tok_init( &tok, buff, 0 );
@@ -2575,10 +2834,32 @@ int parser_test( wchar_t * buff,
{
int mark = tok_get_pos( &tok );
had_cmd = 1;
if( require_additional_commands )
arg_count=0;
if( !(cmd = expand_one( context,
wcsdup( tok_last( &tok ) ),
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES ) ) )
{
if( contains_str( tok_last(&tok),
err=1;
if( babble )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
ILLEGAL_CMD_ERR_MSG,
cmd );
print_errors();
}
}
if( needs_cmd )
{
/*
end is not a valid command when a followup
command is needed, such as after 'and' or
'while'
*/
if( contains_str( cmd,
L"end",
0 ) )
{
@@ -2588,18 +2869,18 @@ int parser_test( wchar_t * buff,
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
COND_ERR_MSG );
print_errors();
}
}
require_additional_commands--;
needs_cmd=0;
}
/*
Decrement block count on end command
*/
if( wcscmp(tok_last(&tok), L"end")==0)
if( wcscmp(cmd, L"end")==0)
{
tok_next( &tok );
count--;
@@ -2609,7 +2890,7 @@ int parser_test( wchar_t * buff,
/*
Handle block commands
*/
if( parser_is_block( tok_last(&tok) ) )
if( parser_is_block( cmd ) )
{
if( count >= BLOCK_MAX_COUNT )
{
@@ -2621,24 +2902,7 @@ int parser_test( wchar_t * buff,
}
else
{
if( wcscmp( tok_last(&tok), L"while") == 0 )
block_type[count] = WHILE;
else if( wcscmp( tok_last(&tok), L"for") == 0 )
block_type[count] = FOR;
else if( wcscmp( tok_last(&tok), L"switch") == 0 )
block_type[count] = SWITCH;
else if( wcscmp( tok_last(&tok), L"if") == 0 )
block_type[count] = IF;
else if( wcscmp( tok_last(&tok), L"function") == 0 )
block_type[count] = FUNCTION_DEF;
else if( wcscmp( tok_last(&tok), L"begin") == 0 )
block_type[count] = BEGIN;
else
block_type[count] = -1;
// debug( 2, L"add block of type %d after cmd %ls\n", block_type[count], tok_last(&tok) );
block_type[count] = parser_get_block_type( cmd );
block_pos[count] = current_tokenizer_pos;
tok_next( &tok );
count++;
@@ -2652,20 +2916,20 @@ int parser_test( wchar_t * buff,
argument. If parser_skip_arguments is true, the
second argument is optional.
*/
if( parser_is_subcommand( tok_last( &tok ) ) && !parser_skip_arguments(tok_last( &tok ) ) )
if( parser_is_subcommand( cmd ) && !parser_skip_arguments(cmd ) )
{
needs_cmd = 1;
had_cmd = 0;
}
/*
The short circuit commands requires _two_ additional commands.
*/
if( contains_str( tok_last( &tok ),
if( contains_str( cmd,
L"or",
L"and",
0 ) )
{
/*
'or' and 'and' can not be used inside pipelines
*/
if( is_pipeline )
{
err=1;
@@ -2679,15 +2943,14 @@ int parser_test( wchar_t * buff,
}
}
require_additional_commands=1;
}
/*
There are a lot of situations where pipelines
are forbidden, inclusing when using the exec
are forbidden, including when using the exec
builtin.
*/
if( parser_is_pipe_forbidden( tok_last( &tok ) ) )
if( parser_is_pipe_forbidden( cmd ) )
{
if( is_pipeline )
{
@@ -2706,17 +2969,14 @@ int parser_test( wchar_t * buff,
}
/*
Test that the case builtin is only used in a switch block
Test that the case builtin is only used directly in a switch block
*/
if( wcscmp( L"case", tok_last( &tok ) )==0 )
if( wcscmp( L"case", cmd )==0 )
{
if( !count || block_type[count-1]!=SWITCH )
{
err=1;
// debug( 2, L"Error on block type %d\n", block_type[count-1] );
if( babble )
{
error( SYNTAX_ERROR,
@@ -2729,10 +2989,9 @@ int parser_test( wchar_t * buff,
}
/*
Test that break and continue are only used in loop blocks
Test that break and continue are only used within loop blocks
*/
if( wcscmp( L"break", tok_last( &tok ) )==0 ||
wcscmp( L"continue", tok_last( &tok ) )==0)
if( contains_str( cmd, L"break", L"continue", (void *)0 ) )
{
int found_loop=0;
int i;
@@ -2761,9 +3020,9 @@ int parser_test( wchar_t * buff,
}
/*
Test that else is only used in an if-block
Test that else is only used directly in an if-block
*/
if( wcscmp( L"else", tok_last( &tok ) )==0 )
if( wcscmp( L"else", cmd )==0 )
{
if( !count || block_type[count-1]!=IF )
{
@@ -2781,7 +3040,7 @@ int parser_test( wchar_t * buff,
}
/*
Test that end is not used when not inside a blovk
Test that end is not used when not inside any block
*/
if( count < 0 )
{
@@ -2795,6 +3054,47 @@ int parser_test( wchar_t * buff,
}
}
}
else
{
err |= parser_test_argument( tok_last( &tok ), babble, tok_get_pos( &tok ) );
/*
If possible, keep track of number of supplied arguments
*/
if( arg_count >= 0 && expand_is_clean( tok_last( &tok ) ) )
{
arg_count++;
}
else
{
arg_count = -1;
}
/*
Try to make sure the second argument to 'for' is 'in'
*/
if( wcscmp( cmd, L"for" ) == 0 )
{
if( arg_count == 2 )
{
if( wcscmp( tok_last( &tok ), L"in" ) != 0 )
{
err = 1;
if( babble )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
BUILTIN_FOR_ERR_IN,
L"for" );
print_errors();
}
}
}
}
}
break;
}
@@ -2840,7 +3140,31 @@ int parser_test( wchar_t * buff,
case TOK_PIPE:
{
if( forbid_pipeline )
if( !had_cmd )
{
err=1;
if( babble )
{
if( tok_get_pos(&tok)>0 && buff[tok_get_pos(&tok)-1] == L'|' )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
CMD_OR_ERR_MSG,
tok_get_desc( tok_last_type(&tok) ) );
}
else
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
CMD_ERR_MSG,
tok_get_desc( tok_last_type(&tok)));
}
print_errors();
}
}
else if( forbid_pipeline )
{
err=1;
if( babble )
@@ -2848,31 +3172,46 @@ int parser_test( wchar_t * buff,
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
EXEC_ERR_MSG );
print_errors();
}
}
needs_cmd=0;
is_pipeline=1;
else
{
needs_cmd=1;
is_pipeline=1;
had_cmd=0;
}
break;
}
case TOK_BACKGROUND:
{
if( needs_cmd && !had_cmd )
if( !had_cmd )
{
err = 1;
if( babble )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
CMD_ERR_MSG,
tok_get_desc( tok_last_type(&tok)));
if( tok_get_pos(&tok)>0 && buff[tok_get_pos(&tok)-1] == L'&' )
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
CMD_AND_ERR_MSG,
tok_get_desc( tok_last_type(&tok) ) );
}
else
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
CMD_ERR_MSG,
tok_get_desc( tok_last_type(&tok)));
}
print_errors();
}
}
if( had_cmd )
{
had_cmd = 0;
@@ -2898,7 +3237,7 @@ int parser_test( wchar_t * buff,
}
}
if( require_additional_commands )
if( needs_cmd )
{
err=1;
if( babble )
@@ -2928,6 +3267,8 @@ int parser_test( wchar_t * buff,
error_code=0;
halloc_free( context );
return err | ((count!=0)<<1);
}

View File

@@ -315,10 +315,20 @@ const wchar_t *parser_get_block_desc( int block );
/**
Test if the specified string can be parsed, or if more bytes need to be read first.
The result has the first bit set if the string contains errors, and the second bit is set if the string contains an unclosed block.
Test if the specified string can be parsed, or if more bytes need
to be read first. The result has the first bit set if the string
contains errors, and the second bit is set if the string contains
an unclosed block.
*/
int parser_test( wchar_t * buff, int babble );
int parser_test( const wchar_t * buff, int babble );
/**
Test if the specified string can be parsed as an argument list,
e.g. sent to eval_args. The result has the first bit set if the
string contains errors, and the second bit is set if the string
contains an unclosed block.
*/
int parser_test_args( const wchar_t * buff, int babble );
/**
Returns the full path of the specified directory. If the \c in is a

View File

@@ -917,7 +917,7 @@ void repaint()
if( steps )
move_cursor( -steps );
set_color( FISH_COLOR_NORMAL, -1 );
set_color( FISH_COLOR_NORMAL, FISH_COLOR_IGNORE );
reader_save_status();
}
@@ -1144,7 +1144,7 @@ static int insert_char( int c )
}
else
writech(c);
set_color( FISH_COLOR_NORMAL, -1 );
set_color( FISH_COLOR_NORMAL, FISH_COLOR_IGNORE );
}
else
{
@@ -2082,7 +2082,7 @@ void reader_run_command( wchar_t *cmd )
term_steal();
env_set( L"_", L"fish", ENV_GLOBAL );
env_set( L"_", program_name, ENV_GLOBAL );
#ifdef HAVE__PROC_SELF_STAT
proc_update_jiffies();
@@ -2099,7 +2099,13 @@ void reader_run_command( wchar_t *cmd )
static int shell_test( wchar_t *b )
{
return !wcslen(b);
if( parser_test( b, 0 ) )
{
writech( L'\n' );
parser_test( b, 1 );
return 1;
}
return 0;
}
/**
@@ -2467,7 +2473,6 @@ wchar_t *reader_readline()
{
exit_forced = 1;
data->end_loop=1;
debug( 1, L"got R_EOF" );
break;
}

4
seq.in
View File

@@ -34,14 +34,14 @@ switch (count $argv)
case '*'
printf (_ "%s: Expected 1, 2 or 3 arguments, got %d\n") seq (count $argv)
return 1
exit 1
end
for i in $from $step $to
if not echo $i | grep '^-\?[0-9]*\(\|.[0-9]\+\)$' >/dev/null
printf (_ "%s: '%s' is not a number\n") seq $i
return 1
exit 1
end
end

View File

@@ -49,6 +49,11 @@
*/
#define SET_COLOR "set_color"
/**
Getopt short switches for set_color
*/
#define GETOPT_STRING "b:hvoc"
#if HAVE_GETTEXT
#define _(string) gettext(string)
#else
@@ -186,13 +191,13 @@ int main( int argc, char **argv )
int opt = getopt_long( argc,
argv,
"b:hvoc",
GETOPT_STRING,
long_options,
&opt_index );
#else
int opt = getopt( argc,
argv,
"b:hvoc" );
GETOPT_STRING );
#endif
if( opt == -1 )
break;

View File

@@ -4,7 +4,7 @@ complete -f -c apt-proxy-import -s V -l version -d (N_ 'Display version and exit
complete -f -c apt-proxy-import -s v -l verbose -d (N_ 'Verbose mode')
complete -f -c apt-proxy-import -s q -l quiet -d (N_ 'No message to STDOUT')
complete -f -c apt-proxy-import -s r -l recursive -d (N_ 'Recurse into subdir')
complete -r -c apt-proxy-import -s i -l import-dir -a '(ls -Fp|grep /$)' -d (N_ 'Dir to import')
complete -r -c apt-proxy-import -s i -l import-dir -a '(ls -Fp|grep /\$)' -d (N_ 'Dir to import')
complete -r -c apt-proxy-import -s u -l user -a '(__fish_complete_users)' -d (N_ 'Change to user')
complete -r -c apt-proxy-import -s d -l debug -d (N_ 'Debug level[default 0]')

View File

@@ -2,8 +2,8 @@
complete -c apt-show-source -s h -l help -d (N_ 'Display help and exit')
complete -r -c apt-show-source -l status-file -d (N_ 'Read package from file') -f
complete -r -c apt-show-source -o stf -d (N_ 'Read package from file') -f
complete -r -c apt-show-source -l list-dir -a '(ls -Fp .|grep /$) /var/lib/apt/lists' -d (N_ 'Specify APT list dir')
complete -r -c apt-show-source -o ld -a '(ls -Fp .|grep /$) /var/lib/apt/lists' -d (N_ 'Specify APT list dir')
complete -r -c apt-show-source -l list-dir -a '(ls -Fp .|grep /\$) /var/lib/apt/lists' -d (N_ 'Specify APT list dir')
complete -r -c apt-show-source -o ld -a '(ls -Fp .|grep /\$) /var/lib/apt/lists' -d (N_ 'Specify APT list dir')
complete -r -c apt-show-source -s p -l package -a '(apt-cache pkgnames)' -d (N_ 'List PKG info')
complete -f -c apt-show-source -l version-only -d (N_ 'Display version and exit')
complete -f -c apt-show-source -s a -l all -d (N_ 'Print all source packages with version')

View File

@@ -9,6 +9,6 @@ complete -f -c apt-show-versions -s v -l verbose -d (N_ 'Print verbose info')
complete -f -c apt-show-versions -s i -l initialize -d (N_ 'Init or update cache only')
complete -r -c apt-show-versions -l status-file -d (N_ 'Read package from file')
complete -r -c apt-show-versions -o stf -d (N_ 'Read package from file')
complete -r -c apt-show-versions -l list-dir -a '(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists' -d (N_ 'Specify APT list dir')
complete -r -c apt-show-versions -o ld -a '(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists' -d (N_ 'Specify APT list dir')
complete -r -c apt-show-versions -l list-dir -a '(ls -Fp .|grep /\$) /var/lib/apt/lists /var/state/apt/lists' -d (N_ 'Specify APT list dir')
complete -r -c apt-show-versions -o ld -a '(ls -Fp .|grep /\$) /var/lib/apt/lists /var/state/apt/lists' -d (N_ 'Specify APT list dir')

View File

@@ -12,3 +12,4 @@ complete -c complete -s u -l unauthorative -d (N_ "Option list is not complete")
complete -c complete -s e -l erase -d (N_ "Remove completion")
complete -c complete -s h -l help -d (N_ "Display help and exit")
complete -c complete -s C -l do-complete -d (N_ "Print all completions for the specified commandline")
complete -c complete -s n -l complete -d (N_ "The completion should only be used if the specified command has a zero exit status") -r

View File

@@ -6,6 +6,7 @@
complete -c fusermount -d (N_ "Mount point") -x -a '
(
cat /etc/mtab | grep "^sshfs" | cut -d " " -f 1-2|tr " " \n|sed -e "s/[0-9\.]*:\//\//"|grep "^/"
cat /etc/mtab | grep "^fuseiso" | cut -d " " -f 1-2|tr " " \n|sed -e "s/[0-9\.]*:\//\//"|grep "^/"
)
'
@@ -15,3 +16,4 @@ complete -c fusermount -s o -x -d (N_ "Mount options")
complete -c fusermount -s u -d (N_ "Unmount")
complete -c fusermount -s q -d (N_ "Quiet")
complete -c fusermount -s z -d (N_ "Lazy unmount")

View File

@@ -6,7 +6,7 @@ for i in (builtin -n)
complete -c help -x -a $i -d (N_ "Help for the specified builtin")
end
for i in count dirh dirs help mimedb nextd open popd prevd pushd set_color psub umask type
for i in case (sed -n < /usr/share/doc/fish-1.21.7/commands.html -e "s/.*<h2><a class=\"anchor\" name=\"\([^\"]*\)\">.*/\1/p")
complete -c help -x -a $i -d (N_ "Help for the specified command")
end

View File

@@ -24,7 +24,7 @@ complete -x -c ssh -s b -d (N_ "Interface to transmit from") -a "
)
"
complete -x -c ssh -s e -d (N_ "Escape character") -a "^ none"
complete -x -c ssh -s e -d (N_ "Escape character") -a "\^ none"
complete -c ssh -s f -d (N_ "Go to background")
complete -c ssh -s g -d (N_ "Allow remote host to connect to local forwarded ports")
complete -c ssh -s I -d (N_ "Smartcard device")

View File

@@ -43,7 +43,7 @@ complete -xc valgrind -l input-fd -d (N_ "File descriptor for input") -a "0 1 2
# Memcheck-specific options
complete -n "__fish_valgrind_skin memcheck" -xc valgrind -l leak-check -d (N_ "Check for memory leaks") -a "no\tDon't\ check\ for\ memory\ leaks summary\t'Show a leak summary' full\t'Describe memory leaks in detail'"
complete -n "__fish_valgrind_skin memcheck" -xc valgrind -l leak-check -d (N_ "Check for memory leaks") -a "no\tDon\'t\ check\ for\ memory\ leaks summary\t'Show a leak summary' full\t'Describe memory leaks in detail'"
complete -n "__fish_valgrind_skin memcheck" -xc valgrind -l show-reachable -d (N_ "Show reachable leaked memory") -a "yes\t'Show reachable leaked memory' no\t'Do not show reachable leaked memory'"
complete -n "__fish_valgrind_skin memcheck" -xc valgrind -l leak-resolution -d (N_ "Determines how willing Memcheck is to consider different backtraces to be the same") -a "low\t'Two entries need to match' med\t'Four entries need to match' high\t'All entries need to match'"
complete -n "__fish_valgrind_skin memcheck" -xc valgrind -l freelist-vol -d (N_ "Set size of freed memory pool")

View File

@@ -40,10 +40,11 @@ if test "$USER" = root
set path_list $path_list /sbin /usr/sbin /usr/local/sbin
end
# Make a regular expressin that matches any component in the PATH. A
# Make a regular expression that matches any component in the PATH. A
# trailing slash is ok. The sed call is to remove the last '\|'.
set -l path_regexp \\\((printf "^%s\\(\\|/\\)\$\\|" $PATH | sed -e "s/..\$//")\\\)
set -l path_regexp \\\((printf "%s" \^$PATH'\(\|/\)$\|' | sed -e "s/..\$//")\\\)
for i in (printf "%s\n" $path_list|grep -v $path_regexp)
if test -d $i

6
share/functions/N_.fish Normal file
View File

@@ -0,0 +1,6 @@
function N_ -d "No-op"
printf "%s" $argv
end

View File

@@ -11,7 +11,7 @@ function cd -d (N_ "Change directory")
end
# Avoid set completions
set previous (command pwd)
set previous $PWD
if test $argv[1] = - ^/dev/null
if test $__fish_cd_direction = next ^/dev/null
@@ -24,7 +24,7 @@ function cd -d (N_ "Change directory")
builtin cd $argv[1]
if test $status = 0 -a (command pwd) != $previous
if test $status = 0 -a $PWD != $previous
set -g dirprev $dirprev $previous
set -e dirnext
set -g __fish_cd_direction prev

View File

@@ -74,7 +74,12 @@ function help -d (N_ "Show help for the fish shell")
set fish_help_page "index.html\#expand"
case (builtin -n)
set fish_help_page "builtins.html\#$fish_help_item"
case contains count dirh dirs help mimedb nextd open popd prevd pushd set_color tokenize psub umask type vared
# This command substitution should locate all commands with
# documentation. It's a bit of a hack, since it relies on the
# Doxygen markup format to never change...
case (sed -n < /usr/share/doc/fish-1.21.7/commands.html -e "s/.*<h2><a class=\"anchor\" name=\"\([^\"]*\)\">.*/\1/p")
set fish_help_page "commands.html\#$fish_help_item"
case $help_topics
set fish_help_page "index.html\#$fish_help_item"

View File

@@ -3,5 +3,5 @@
#
function pwd -d (N_ "Print working directory")
command pwd | sed -e 's|/private||' -e "s|^$HOME|~|"
echo $PWD | sed -e 's|/private||' -e "s|^$HOME|~|"
end