Compare commits

...

109 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
axel
fe5bf8f80e Set version to 1.18.0
darcs-hash:20051207163122-ac50b-9844fb2917028886a5a1f6ce54edf7641abbc231.gz
2005-12-08 02:31:22 +10:00
axel
0a713a7939 Correct set help page. The handling of setting a variable to no value has changed.
darcs-hash:20051207162924-ac50b-3e3c579b8b932b9a5a11546fb4a042d5e2aa85c5.gz
2005-12-08 02:29:24 +10:00
axel
4ba2709452 Improved error messages
darcs-hash:20051207160647-ac50b-4061540829a108381c20a1a6f3c8fd2d004a9800.gz
2005-12-08 02:06:47 +10:00
axel
0c877183b9 Spelling
darcs-hash:20051207155717-ac50b-6146b02bd8aff0fd27816acd5e31b38093d8575d.gz
2005-12-08 01:57:17 +10:00
axel
a46be4cadb Handle setting zero length variable name
darcs-hash:20051207144849-ac50b-d919481d54ef80c68d5f4cc847d5c2370e94ddcc.gz
2005-12-08 00:48:49 +10:00
axel
8b4637e900 Insert boundary token at quotes, makes things like $foo"bar" work right
darcs-hash:20051207144307-ac50b-a708fa43b196f435efdcb1bfac17ce592cdb4533.gz
2005-12-08 00:43:07 +10:00
axel
ab13c4caad Give intelligent warning messages on zero-length variable names.
darcs-hash:20051207130330-ac50b-cc9d78ba63f592925b6076049e2c59aaaa930eec.gz
2005-12-07 23:03:30 +10:00
axel
479696a8ec Set status to 1 on parse errors
darcs-hash:20051207130209-ac50b-f1431d395bf741bb4c8f99ed64ed8ccc53a960a3.gz
2005-12-07 23:02:09 +10:00
netocrat
acde745e34 Add a distclean target to Makefile.in
darcs-hash:20051103170348-344c5-9e8f20f2363ac031c8eeb991d01c58fde86fd33b.gz
2005-11-04 03:03:48 +10:00
netocrat
064d49215a Add missing files to remove for make clean
darcs-hash:20051103151026-344c5-c79770e8273cc18f0515c4bbbed730fec89af060.gz
2005-11-04 01:10:26 +10:00
netocrat
78d3b37e11 Modify fish init scripts to take account of @SYSCONFDIR@
darcs-hash:20051103143535-344c5-203a64cc8bdb14cc018254f6eb74852a1db4843f.gz
2005-11-04 00:35:35 +10:00
axel
12aa33fad4 Even more documentation updates. Variable expantion and design document sections.
darcs-hash:20051204132259-ac50b-d63356923e41c85a8d4aae1a4db3c815867fe5e2.gz
2005-12-04 23:22:59 +10:00
axel
e4ade8f41b Remove silly warnings in help script
darcs-hash:20051204132218-ac50b-e9e74283b7fe3f12a9af90f2b6d93b189e80a684.gz
2005-12-04 23:22:18 +10:00
axel
9d7723b330 More documentation corrections and updates
darcs-hash:20051204124043-ac50b-11a283ee48103cb24efdaf18f6de62f503d6e028.gz
2005-12-04 22:40:43 +10:00
axel
2bc2e0b9ec More documentation tweaks
darcs-hash:20051204023353-ac50b-196f21f186237d5e7074667fc86f2172a7ac40e2.gz
2005-12-04 12:33:53 +10:00
axel
02083a1bd7 Updated some obsolete documentation sections, and added some general polish
darcs-hash:20051204022740-ac50b-d3258d6b6f6caaf1b728c3c5074e1318135d6752.gz
2005-12-04 12:27:40 +10:00
axel
e534a952b7 Fix display bug causing the wrong completion string prefix to be shown in some situations
darcs-hash:20051204015613-ac50b-3c9feaf11d9657a30272303f9605f8139a0c5923.gz
2005-12-04 11:56:13 +10:00
axel
754d8d3712 Fix bug breaking filename completions, introduced by csh wildcard syntax
darcs-hash:20051204015402-ac50b-911c6188f6c8213a733f4e967fc903f5290f1772.gz
2005-12-04 11:54:02 +10:00
axel
86230813de Remove more deprecated event hooks
darcs-hash:20051203195135-ac50b-bcdfc71f1e634ee9e2745683a8b23243e03a0412.gz
2005-12-04 05:51:35 +10:00
axel
2faba57e5a Update todo list to reflect recent changes
darcs-hash:20051203195003-ac50b-3c0bcaebf8a6d81fa0e0940ab6b215781cb26d52.gz
2005-12-04 05:50:03 +10:00
axel
3789127d28 No longer track changes to the ChangeLog file, since it is autogenerated
darcs-hash:20051203194801-ac50b-215457a371538276fd71f9aa368e13f1b8bfff73.gz
2005-12-04 05:48:01 +10:00
axel
32e833f331 Remove old event hooks, add more event handler documentation
darcs-hash:20051203194618-ac50b-e90683cb69b19da789152164a89a34bf187fd4e4.gz
2005-12-04 05:46:18 +10:00
axel
9b4c34aa4c Use csh-style error rules with wildcards, i.e. if no matches are found, the command is not executed
darcs-hash:20051203164356-ac50b-1b1818db2698eab9ae765a5af1e259bce3ab37e7.gz
2005-12-04 02:43:56 +10:00
axel
e2ebc0e443 Set version to 1.17.0, disable fishd optimization patch.
darcs-hash:20051201154544-ac50b-9b0f5502659d9f1facc04e4fd6a0b7287b197f2d.gz
2005-12-02 01:45:44 +10:00
axel
8ff66e718c Fix broken recursive wildcard patch
darcs-hash:20051130153303-ac50b-3d0973badb50a98fe8038135a031a8ee14e4f894.gz
2005-12-01 01:33:03 +10:00
axel
2789da6a1a Only insert fishd barrier after non-builtin commands to increase performance
darcs-hash:20051129195132-ac50b-7fcf7b2458b162c9c668fe823f17dc070604b00d.gz
2005-11-30 05:51:32 +10:00
axel
51c345311a Make the not builtin work with shellscript functions
darcs-hash:20051129195030-ac50b-7ada30d327f2dcc8ad23f56b0a36c975cb90c481.gz
2005-11-30 05:50:30 +10:00
axel
4a68a34c50 Change stupid call signature for tilde expand function
darcs-hash:20051129165202-ac50b-f442d0d75864317cc70059fffe5e8eb956ad54a6.gz
2005-11-30 02:52:02 +10:00
axel
9993ff07f2 Fix problem with recursive wildcards not working properly when postfixed with a regular string
darcs-hash:20051129143352-ac50b-6fec789be36250f29d35458b15dbae423eed195c.gz
2005-11-30 00:33:52 +10:00
axel
fc8b56da0d Remove accidentally included test code for recursive wildcard feature
darcs-hash:20051129101414-ac50b-929f0b9928bbed8a485699c66e1b4e3e8cedcfdc.gz
2005-11-29 20:14:14 +10:00
axel
02981a1750 Minor cleanups
darcs-hash:20051129101303-ac50b-11843dc32a9d05037b907fe1ac5df6a90cb7dd36.gz
2005-11-29 20:13:03 +10:00
axel
c2e6b07b35 Try to report IO redirection errors resulting from redirection stderr
darcs-hash:20051129101206-ac50b-970569a8b710d74b6e16a3c09b8848618cec4a7e.gz
2005-11-29 20:12:06 +10:00
James Vega
8fcacdd5df common.c: Include the header file for ioctl()
darcs-hash:20051128144202-35ec8-5148e095c81538cb26c232e93dbe94a93e75e253.gz
2005-11-29 00:42:02 +10:00
axel
6bf58e44f4 Make sure fishd saves before exiting from signal
darcs-hash:20051127232409-ac50b-d316781e373c078fecf857a199594a00184361a9.gz
2005-11-28 09:24:09 +10:00
axel
bda7948719 Make sure fishd synchronization happens only when needed
darcs-hash:20051127232208-ac50b-927157fb9b5d3e44981f9ec029735531ae59fd61.gz
2005-11-28 09:22:08 +10:00
axel
e800fca499 Use better test for presense of getopt_long function
darcs-hash:20051127150603-ac50b-566999b0cb32bc150dc6ef43220452ab42f1ad64.gz
2005-11-28 01:06:03 +10:00
axel
eed4b75389 Remove config.h.in from repo, it is autogenerated by autoheader
darcs-hash:20051125162839-ac50b-bbd4dc02684028a45c19de50cdfa52e020368491.gz
2005-11-26 02:28:39 +10:00
axel
5974dd68b0 Use iswspace instead of the GNU extention iswblank
darcs-hash:20051125144434-ac50b-088a2a8066537f19f287f9dad1611a172addd053.gz
2005-11-26 00:44:34 +10:00
axel
680c0aff05 Use short style switch on set_color, since long style getopt not always available
darcs-hash:20051125144406-ac50b-ca222e2fb3f2396489fb5eca64f2eff32b654404.gz
2005-11-26 00:44:06 +10:00
axel
4a2bdeebef Fire pending events when interrupted while reading from keyboard
darcs-hash:20051125141826-ac50b-12e763c0a7f1b4e9136e38de7a8921ff2d1a74e7.gz
2005-11-26 00:18:26 +10:00
axel
dfa251a1ab Remove ifdefs from function code
darcs-hash:20051125141657-ac50b-4dabc1dea3c90accafdcab78f683412858d77541.gz
2005-11-26 00:16:57 +10:00
Claes Nästén
82cb97d3e3 builtin ulimit checks
Adds checks for RLIMIT_NPROC, RLIMIT_RSS and RLIMIT_MEMLOCK not available
on all platforms.

darcs-hash:20051124111321-cac88-606a61ca0f3baa69115be658a056f42a5a9318ad.gz
2005-11-24 21:13:21 +10:00
axel
7d334914f7 Minor code tweaks
darcs-hash:20051123185743-ac50b-dc35b7f64e5416f3f2749edebd5235abb5bdff98.gz
2005-11-24 04:57:43 +10:00
axel
27a60f465d Change name of fishd log file
darcs-hash:20051123185710-ac50b-bd3e5d1664a4832bfee579a027bbce9ac6661b2d.gz
2005-11-24 04:57:10 +10:00
horeah
279159384e Added support for recursive wildcards
darcs-hash:20051123153503-b56f0-6d837388e8bbfdebba9a399f8374b3e8433e5a32.gz
2005-11-24 01:35:03 +10:00
axel
d748e05cb9 Make sure installation path is in PATH
darcs-hash:20051103162625-ac50b-e70d6bff6a83130cd905008e65da34984bf64a7b.gz
2005-11-04 02:26:25 +10:00
axel
d50c051eec Change quoting rules to POSIX style
darcs-hash:20051102164913-ac50b-d4b696394e13a2d4c787f8ee1a2b209317dddb51.gz
2005-11-03 02:49:13 +10:00
85 changed files with 3712 additions and 2968 deletions

1015
ChangeLog

File diff suppressed because it is too large Load Diff

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)
@@ -134,9 +134,9 @@ MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
config.guess fish_tests.c main.c fish_pager.c fishd.c
# Files in ./init/
INIT_DIR_FILES :=init/fish.in init/fish_complete.fish \
INIT_DIR_FILES :=init/fish.in init/fish_complete.fish.in \
init/fish_function.fish init/fish_inputrc \
init/fish_interactive.fish
init/fish_interactive.fish.in
# Files in ./tests/
TESTS_DIR_FILES := $(TEST_IN) $(TEST_IN:.in=.out) $(TEST_IN:.in=.err) \
@@ -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 \
@@ -374,10 +376,16 @@ rpm: fish-@PACKAGE_VERSION@.tar.bz2
mv /usr/src/redhat/RPMS/*/fish*@PACKAGE_VERSION@*.rpm .
mv /usr/src/redhat/SRPMS/fish*@PACKAGE_VERSION@*.src.rpm .
distclean: clean
rm -f fish.spec doc_src/fish.1 doc_src/Doxyfile
rm -f init/fish init/fish_interactive.fish init/fish_complete.fish
rm -f config.status config.log config.h Makefile
clean:
rm -f *.o doc.h doc_src/*.doxygen doc_src/*.c builtin_help.c
rm -f config.status config.log config.h Makefile
rm -f tests/tmp.err tests/tmp.out tests/tmp.status tests/foo.txt
rm -f tokenizer_test fish key_reader set_color tokenize gen_hdr2 mimedb
rm -f fishd fish_pager count
rm -f fish-@PACKAGE_VERSION@.tar
rm -f fish-@PACKAGE_VERSION@.tar.gz
rm -f fish-@PACKAGE_VERSION@.tar.bz2

854
builtin.c

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,10 @@ enum
*/
#define BUILTIN_ERR_UNKNOWN L": Unknown option"
#define BUILTIN_ERR_VARCHAR L"%ls: Invalid character in variable name: '%lc'. Only alphanumerical characters and underscores are valid in a variable name.\n"
#define BUILTIN_ERR_VARNAME_ZERO L"%ls: Variable name can not be the empty string\n"
/**
Stringbuffer used to represent standard output
*/

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

@@ -40,10 +40,8 @@ static int parse_fill_name( string_buffer_t *name,
if (*src != L'[' && *src != L'\0')
{
sb_append(sb_err, L"set: Invalid character in variable name: ");
sb_append_char(sb_err, *src);
sb_append2(sb_err, L"\n", parser_current_line(), L"\n", (void *)0 );
sb_printf( sb_err, BUILTIN_ERR_VARCHAR, L"set", *src );
sb_append2(sb_err, parser_current_line(), L"\n", (void *)0 );
// builtin_print_help( L"set", sb_err );
return -1;
@@ -83,7 +81,7 @@ static int parse_fill_indexes( array_list_t *indexes,
return -1;
}
while (iswblank(*src))
while (iswspace(*src))
{
src++;
}
@@ -105,7 +103,7 @@ static int parse_fill_indexes( array_list_t *indexes,
al_push(indexes, ind);
src = end;
count++;
while (iswblank(*src)) src++;
while (iswspace(*src)) src++;
}
return count;
@@ -292,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);
@@ -435,6 +433,13 @@ int builtin_set( wchar_t **argv )
{
dest = wcsdup(argv[woptind++]);
//fwprintf(stderr, L"Dest: %ls\n", dest);
if( !wcslen( dest ) )
{
free( dest );
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
return 1;
}
}
/* Parse values */

View File

@@ -35,6 +35,10 @@ struct resource_t
Switch used on commandline to specify resource
*/
wchar_t switch_char;
/**
The implicit multiplier used when setting getting values
*/
int multiplier;
}
;
@@ -44,49 +48,55 @@ struct resource_t
const static struct resource_t resource_arr[] =
{
{
RLIMIT_CORE, L"Maximum size of core files created", L'c'
RLIMIT_CORE, L"Maximum size of core files created", L'c', 1024
}
,
{
RLIMIT_DATA, L"Maximum size of a processs data segment", L'd'
RLIMIT_DATA, L"Maximum size of a processs data segment", L'd', 1024
}
,
{
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f'
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024
}
,
#if HAVE_RLIMIT_MEMLOCK
{
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024
}
,
#endif
#if HAVE_RLIMIT_RSS
{
RLIMIT_RSS, L"Maximum resident set size", L'm', 1024
}
,
#endif
{
RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n', 1
}
,
{
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l'
RLIMIT_STACK, L"Maximum stack size", L's', 1024
}
,
{
RLIMIT_RSS, L"Maximum resident set size", L'm'
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1
}
,
#if HAVE_RLIMIT_NPROC
{
RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n'
}
,
{
RLIMIT_STACK, L"Maximum stack size", L's'
}
,
{
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't'
}
,
{
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u'
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1
}
,
#endif
#if HAVE_RLIMIT_AS
{
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v'
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
}
,
#endif
{
0, 0
0, 0, 0, 0
}
}
;
@@ -96,13 +106,16 @@ const static struct resource_t resource_arr[] =
*/
static int get_multiplier( int what )
{
if( ( what == RLIMIT_NPROC ) ||
( what == RLIMIT_NOFILE ) ||
( what == RLIMIT_CPU ) )
int i;
for( i=0; resource_arr[i].desc; i++ )
{
return 1;
if( resource_arr[i].resource == what )
{
return resource_arr[i].multiplier;
}
}
return 1024;
return -1;
}
/**
@@ -365,14 +378,17 @@ int builtin_ulimit( wchar_t ** argv )
case L'f':
what=RLIMIT_FSIZE;
break;
#if HAVE_RLIMIT_MEMLOCK
case L'l':
what=RLIMIT_MEMLOCK;
break;
#endif
#if HAVE_RLIMIT_RSS
case L'm':
what=RLIMIT_RSS;
break;
#endif
case L'n':
what=RLIMIT_NOFILE;
@@ -385,10 +401,12 @@ int builtin_ulimit( wchar_t ** argv )
case L't':
what=RLIMIT_CPU;
break;
#if HAVE_RLIMIT_NPROC
case L'u':
what=RLIMIT_NPROC;
break;
#endif
#if HAVE_RLIMIT_AS
case L'v':

616
common.c
View File

@@ -13,6 +13,7 @@ parts of fish.
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wctype.h>
@@ -314,8 +315,7 @@ char **wcsv2strv( const wchar_t **in )
char **res = malloc( sizeof( char *)*(count+1));
if( res == 0 )
{
die_mem();
die_mem();
}
for( i=0; i<count; i++ )
@@ -353,8 +353,10 @@ wchar_t *wcsdupcat2( const wchar_t *a, ... )
wchar_t *res = malloc( sizeof(wchar_t)*(len +1 ));
if( res == 0 )
return 0;
{
die_mem();
}
wcscpy( res, a );
pos = wcslen(a);
while( (arg=va_arg(va2, wchar_t *) )!= 0 )
@@ -391,7 +393,7 @@ wchar_t **strv2wcsv( const char **in )
}
#ifndef HAVE_WCSNDUP
wchar_t *wcsndup( const wchar_t *in, int c )
{
c3++;
@@ -405,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 )
{
@@ -489,17 +492,6 @@ long wcstol(const wchar_t *nptr,
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
Appends src to string dst of size siz (unlike wcsncat, siz is the
full size of dst, not space left). At most siz-1 characters will be
copied. Always NUL terminates (unless siz <= wcslen(dst)). Returns
wcslen(src) + MIN(siz, wcslen(initial dst)). If retval >= siz,
truncation occurred.
This is the OpenBSD strlcat function, modified for wide characters,
and renamed to reflect this change.
*/
size_t
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
{
@@ -552,14 +544,6 @@ wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/**
Copy src to string dst of size siz. At most siz-1 characters will
be copied. Always NUL terminates (unless siz == 0). Returns
wcslen(src); if retval >= siz, truncation occurred.
This is the OpenBSD strlcpy function, modified for wide characters,
and renamed to reflect this change.
*/
size_t
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
{
@@ -591,9 +575,7 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
/* count does not include NUL */
}
/**
Fallback implementation if missing from libc
*/
#ifndef HAVE_WCSDUP
wchar_t *wcsdup( const wchar_t *in )
{
size_t len=wcslen(in);
@@ -601,17 +583,26 @@ wchar_t *wcsdup( const wchar_t *in )
if( out == 0 )
{
die_mem();
}
memcpy( out, in, sizeof( wchar_t)*(len+1));
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 )
@@ -628,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 )
@@ -651,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 )
{
@@ -706,43 +698,25 @@ int my_wcswidth( const wchar_t *c )
wchar_t *quote_end( const wchar_t *in )
{
int level=1;
int offset = (*in != L'\"');
in++;
while(1)
switch( *in )
{
/* fwprintf( stderr, L"Check %c\n", *tok->buff );*/
switch( *in )
case '"':
{
case L'\\':
in++;
if( *in == L'\0' )
{
while(1)
{
in = wcschr( in+1, L'"' );
if( !in )
return 0;
}
break;
case L'\"':
case L'\'':
if( (((level+offset) % 2)?L'\"':L'\'') == *in )
{
level--;
}
else
{
level++;
}
break;
if( *(in-1) != L'\\' )
return (wchar_t *)in;
}
}
case '\'':
{
return wcschr( in+1, L'\'' );
}
if( (*in == L'\0') ||(level==0))
break;
in++;
}
return level?0:(wchar_t *)in;
return 0;
}
@@ -959,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'?':
@@ -970,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;
@@ -997,8 +973,10 @@ wchar_t *escape( const wchar_t *in,
}
wchar_t *unescape( const wchar_t * orig, int escape_special )
wchar_t *unescape( const wchar_t * orig, int unescape_special )
{
int mode = 0;
int in_pos, out_pos, len = wcslen( orig );
int c;
int bracket_count=0;
@@ -1007,194 +985,346 @@ wchar_t *unescape( const wchar_t * orig, int escape_special )
if( !in )
die_mem();
for( in_pos=0, out_pos=0; in_pos<len; prev=in[out_pos], out_pos++, in_pos++ )
for( in_pos=0, out_pos=0;
in_pos<len;
(prev=(out_pos>=0)?in[out_pos]:0), out_pos++, in_pos++ )
{
c = in[in_pos];
if( c == L'\\' )
switch( mode )
{
switch( in[++in_pos] )
/*
Mode 0 means unquoted string
*/
case 0:
{
case L'\0':
free(in);
return 0;
case L'n':
in[out_pos]=L'\n';
break;
case L'r':
in[out_pos]=L'\r';
break;
case L't':
in[out_pos]=L'\t';
break;
case L'b':
in[out_pos]=L'\b';
break;
case L'e':
in[out_pos]=L'\e';
break;
case L'u':
case L'U':
case L'x':
case L'o':
if( c == L'\\' )
{
int i;
wchar_t res=0;
int chars=2;
int base=16;
switch( in[in_pos] )
switch( in[++in_pos] )
{
case L'u':
base=16;
chars=4;
break;
case L'U':
base=16;
chars=8;
break;
case L'x':
base=16;
chars=2;
break;
case L'o':
base=8;
chars=3;
break;
}
for( i=0; i<chars; i++ )
{
int d = convert_digit( in[++in_pos],base);
if( d < 0 )
case L'\0':
{
in_pos--;
free(in);
return 0;
}
case L'n':
{
in[out_pos]=L'\n';
break;
}
res=(res*base)|d;
case L'r':
{
in[out_pos]=L'\r';
break;
}
case L't':
{
in[out_pos]=L'\t';
break;
}
case L'b':
{
in[out_pos]=L'\b';
break;
}
case L'e':
{
in[out_pos]=L'\e';
break;
}
case L'u':
case L'U':
case L'x':
case L'o':
{
int i;
wchar_t res=0;
int chars=2;
int base=16;
switch( in[in_pos] )
{
case L'u':
{
base=16;
chars=4;
break;
}
case L'U':
{
base=16;
chars=8;
break;
}
case L'x':
{
base=16;
chars=2;
break;
}
case L'o':
{
base=8;
chars=3;
break;
}
}
for( i=0; i<chars; i++ )
{
int d = convert_digit( in[++in_pos],base);
if( d < 0 )
{
in_pos--;
break;
}
res=(res*base)|d;
}
in[out_pos] = res;
break;
}
default:
{
in[out_pos]=in[in_pos];
break;
}
}
}
else
{
switch( in[in_pos]){
case L'~':
{
if( unescape_special && (in_pos == 0) )
{
in[out_pos]=HOME_DIRECTORY;
}
else
{
in[out_pos] = L'~';
}
break;
}
case L'%':
{
if( unescape_special && (in_pos == 0) )
{
in[out_pos]=PROCESS_EXPAND;
}
else
{
in[out_pos]=in[in_pos];
}
break;
}
case L'*':
{
if( unescape_special )
{
if( out_pos > 0 && in[out_pos-1]==ANY_STRING )
{
out_pos--;
in[out_pos] = ANY_STRING_RECURSIVE;
}
else
in[out_pos]=ANY_STRING;
}
else
{
in[out_pos]=in[in_pos];
}
break;
}
case L'?':
{
if( unescape_special )
{
in[out_pos]=ANY_CHAR;
}
else
{
in[out_pos]=in[in_pos];
}
break;
}
case L'$':
{
if( unescape_special )
{
in[out_pos]=VARIABLE_EXPAND;
}
else
{
in[out_pos]=in[in_pos];
}
break;
}
case L'{':
{
if( unescape_special )
{
bracket_count++;
in[out_pos]=BRACKET_BEGIN;
}
else
{
in[out_pos]=in[in_pos];
}
break;
}
case L'}':
{
if( unescape_special )
{
bracket_count--;
in[out_pos]=BRACKET_END;
}
else
{
in[out_pos]=in[in_pos];
}
break;
}
case L',':
{
if( unescape_special && bracket_count && prev!=BRACKET_SEP)
{
in[out_pos]=BRACKET_SEP;
}
else
{
in[out_pos]=in[in_pos];
}
break;
}
case L'\'':
{
mode = 1;
in[out_pos] = INTERNAL_SEPARATOR;
break;
}
case L'\"':
{
mode = 2;
in[out_pos] = INTERNAL_SEPARATOR;
break;
}
default:
{
in[out_pos] = in[in_pos];
break;
}
}
}
break;
}
/*
Mode 1 means single quoted string, i.e 'foo'
*/
case 1:
{
if( c == L'\'' )
{
in[out_pos] = INTERNAL_SEPARATOR;
mode = 0;
}
else
{
in[out_pos] = in[in_pos];
}
break;
}
/*
Mode 2 means double quoted string, i.e. "foo"
*/
case 2:
{
switch( c )
{
case '"':
{
mode = 0;
in[out_pos] = INTERNAL_SEPARATOR;
break;
}
case '\\':
{
switch( in[++in_pos] )
{
case L'\0':
{
free(in);
return 0;
}
case L'$':
{
in[out_pos]=in[in_pos];
break;
}
default:
{
in[out_pos++] = L'\\';
in[out_pos] = in[in_pos];
break;
}
}
break;
}
in[out_pos] = res;
break;
}
default:
in[out_pos]=in[in_pos];
break;
}
}
else
{
switch( in[in_pos]){
case L'~':
if( escape_special && (in_pos == 0) )
in[out_pos]=HOME_DIRECTORY;
else
in[out_pos] = L'~';
break;
case L'%':
if( escape_special && (in_pos == 0) )
in[out_pos]=PROCESS_EXPAND;
else
in[out_pos]=in[in_pos];
break;
case L'*':
if( escape_special )
case '$':
{
if( out_pos > 0 && in[out_pos-1]==ANY_STRING )
if( unescape_special )
{
out_pos--;
in[out_pos] = ANY_STRING_RECURSIVE;
in[out_pos]=VARIABLE_EXPAND_SINGLE;
}
else
in[out_pos]=ANY_STRING;
{
in[out_pos]=in[in_pos];
}
break;
}
else
in[out_pos]=in[in_pos];
break;
case L'?':
if( escape_special )
in[out_pos]=ANY_CHAR;
else
in[out_pos]=in[in_pos];
break;
case L'$':
if( escape_special )
in[out_pos]=VARIABLE_EXPAND;
else
in[out_pos]=in[in_pos];
break;
case L'{':
if( escape_special )
default:
{
bracket_count++;
in[out_pos]=BRACKET_BEGIN;
in[out_pos] = in[in_pos];
break;
}
else
in[out_pos]=in[in_pos];
break;
case L'}':
if( escape_special )
{
bracket_count--;
in[out_pos]=BRACKET_END;
}
else
in[out_pos]=in[in_pos];
break;
case L',':
if( escape_special && bracket_count && prev!=BRACKET_SEP)
{
in[out_pos]=BRACKET_SEP;
}
else
in[out_pos]=in[in_pos];
break;
case L'\'':
case L'\"':
{
wchar_t *end = quote_end( &in[in_pos] );
int len;
if( end == 0 )
{
free(in);
return 0;
}
len = end- &in[in_pos]-1;
if( escape_special)
in[out_pos++]=INTERNAL_SEPARATOR;
memmove( &in[out_pos], &in[in_pos+1], sizeof(wchar_t)*(len) );
in_pos += len+1;
out_pos += len-1;
if( escape_special)
in[++out_pos]=INTERNAL_SEPARATOR;
break;
}
default:
in[out_pos] = in[in_pos];
break;
}
break;
}
}
}
}
in[out_pos]=L'\0';
return in;
@@ -1310,13 +1440,13 @@ static char *gen_unique_nfs_filename( const char *filename )
pidlen = sprint_pid_t( getpid(), newname + orglen + 1 + hnlen + 1 );
newname[orglen + 1 + hnlen + 1 + pidlen] = '\0';
/* debug( 1, L"gen_unique_nfs_filename returning with: newname = \"%s\"; "
L"HOST_NAME_MAX = %d; hnlen = %d; orglen = %d; "
L"sizeof(pid_t) = %d; maxpiddigits = %d; malloc'd size: %d",
newname, (int)HOST_NAME_MAX, hnlen, orglen,
(int)sizeof(pid_t),
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1),
(int)(orglen + 1 + hnlen + 1 +
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) + 1) ); */
L"HOST_NAME_MAX = %d; hnlen = %d; orglen = %d; "
L"sizeof(pid_t) = %d; maxpiddigits = %d; malloc'd size: %d",
newname, (int)HOST_NAME_MAX, hnlen, orglen,
(int)sizeof(pid_t),
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1),
(int)(orglen + 1 + hnlen + 1 +
(int)(0.31 * sizeof(pid_t) * CHAR_BIT + 1) + 1) ); */
return newname;
}

103
common.h
View File

@@ -14,7 +14,10 @@
#include "util.h"
/**
Under curses, tputs expects an int (*func)(char) as its last parameter, but in ncurses, tputs expects a int (*func)(int) as its last parameter. tputs_arg_t is defined to always be what tputs expects. Hopefully.
Under curses, tputs expects an int (*func)(char) as its last
parameter, but in ncurses, tputs expects a int (*func)(int) as its
last parameter. tputs_arg_t is defined to always be what tputs
expects. Hopefully.
*/
#ifdef NCURSES_VERSION
@@ -24,7 +27,7 @@ typedef char tputs_arg_t;
#endif
/**
Maximum number of bytes in a utf-8 character
Maximum number of bytes used by a single utf-8 character
*/
#define MAX_UTF8_BYTES 6
@@ -39,11 +42,14 @@ typedef char tputs_arg_t;
*/
#define FISH_COLOR_RESET -2
/** Save the shell mode on startup so we can restore them on exit */
/**
Save the shell mode on startup so we can restore them on exit
*/
extern struct termios shell_modes;
/**
The character to use where the text has been truncated. Is an ellipsis on unicode system and a $ on other systems.
The character to use where the text has been truncated. Is an
ellipsis on unicode system and a $ on other systems.
*/
extern wchar_t ellipsis_char;
@@ -69,7 +75,8 @@ extern char *profile;
extern wchar_t *program_name;
/**
Take an array_list_t containing wide strings and converts them to a wchar_t **.
Take an array_list_t containing wide strings and converts them to a
single null-terminated wchar_t **.
*/
wchar_t **list_to_char_arr( array_list_t *l );
@@ -87,22 +94,26 @@ wchar_t **list_to_char_arr( array_list_t *l );
int fgetws2( wchar_t **buff, int *len, FILE *f );
/**
Sorts a list of wide strings according to the wcsfilecmp-function from the util library
Sorts a list of wide strings according to the wcsfilecmp-function
from the util library
*/
void sort_list( array_list_t *comp );
/**
Returns a newly allocated wide character string equivalent of the specified multibyte character string
Returns a newly allocated wide character string equivalent of the
specified multibyte character string
*/
wchar_t *str2wcs( const char *in );
/**
Returns a newly allocated multibyte character string equivalent of the specified wide character string
Returns a newly allocated multibyte character string equivalent of
the specified wide character string
*/
char *wcs2str( const wchar_t *in );
/**
Returns a newly allocated wide character string array equivalent of the specified multibyte character string array
Returns a newly allocated wide character string array equivalent of
the specified multibyte character string array
*/
char **wcsv2strv( const wchar_t **in );
@@ -112,19 +123,26 @@ char **wcsv2strv( const wchar_t **in );
wchar_t **strv2wcsv( const char **in );
/**
Returns a newly allocated concatenation of the specified wide character strings
Returns a newly allocated concatenation of the specified wide
character strings
*/
wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b );
/**
Returns a newly allocated concatenation of the specified wide character strings. The last argument must be a null pointer.
Returns a newly allocated concatenation of the specified wide
character strings. The last argument must be a null pointer.
*/
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 always null terminated, and the null is not included in the string length.
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
always null terminated, and the null is not included in the string
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
@@ -144,17 +162,42 @@ long wcstol(const wchar_t *nptr,
wchar_t **endptr,
int base);
size_t
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz);
/**
Appends src to string dst of size siz (unlike wcsncat, siz is the
full size of dst, not space left). At most siz-1 characters will be
copied. Always NUL terminates (unless siz <= wcslen(dst)). Returns
wcslen(src) + MIN(siz, wcslen(initial dst)). If retval >= siz,
truncation occurred.
size_t
wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz);
This is the OpenBSD strlcat function, modified for wide characters,
and renamed to reflect this change.
*/
size_t wcslcat( wchar_t *dst, const wchar_t *src, size_t siz );
/**
Create a dublicate string. Wide string version of strdup.
Copy src to string dst of size siz. At most siz-1 characters will
be copied. Always NUL terminates (unless siz == 0). Returns
wcslen(src); if retval >= siz, truncation occurred.
This is the OpenBSD strlcpy function, modified for wide characters,
and renamed to reflect this change.
*/
size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
#ifndef HAVE_WCSDUP
/**
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.
@@ -163,10 +206,26 @@ wchar_t *wcsdup(const wchar_t *in);
esoteric locales where uppercase and lowercase do not cleanly
transform between each other. Hopefully this should be fine since
fish only uses this function with one of the strings supplied by
fish and guaranteed to be a sane, english word.
fish and guaranteed to be a sane, english word. Using wcscasecmp on
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.
This implementation of wcsncasecmp does not take into account
esoteric locales where uppercase and lowercase do not cleanly
transform between each other. Hopefully this should be fine since
fish only uses this function with one of the strings supplied by
fish and guaranteed to be a sane, english word. Using wcsncasecmp on
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
@@ -188,7 +247,11 @@ int wcwidth( wchar_t c );
int my_wcswidth( const wchar_t *c );
/**
This functions returns the end of a quoted substring. It can handle nested single and double quotes.
This functions returns the end of the quoted substring beginning at
\c in. It can handle both single and double quotes. Returns 0 on
error.
\param in the position of the opening quote
*/
wchar_t *quote_end( const wchar_t *in );
@@ -205,7 +268,7 @@ void error_reset();
/**
Set the locale, also change the ellipsis character
*/
void fish_setlocale(int category, const wchar_t *locale);
void fish_setlocale( int category, const wchar_t *locale );
/**
Checks if \c needle is included in the list of strings specified

View File

@@ -1213,10 +1213,12 @@ static void complete_cmd( const wchar_t *cmd,
array_list_t tmp;
al_init( &tmp );
expand_string( wcsdup(cmd),
comp,
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY );
complete_cmd_desc( cmd, comp );
if( expand_string( wcsdup(cmd),
comp,
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
complete_cmd_desc( cmd, comp );
}
al_destroy( &tmp );
}
else
@@ -1237,14 +1239,15 @@ static void complete_cmd( const wchar_t *cmd,
al_init( &tmp );
expand_string( nxt_completion,
if( expand_string( nxt_completion,
&tmp,
ACCEPT_INCOMPLETE |
EXECUTABLES_ONLY );
for( i=0; i<al_get_count(&tmp); i++ )
EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
al_push( comp, al_get( &tmp, i ) );
for( i=0; i<al_get_count(&tmp); i++ )
{
al_push( comp, al_get( &tmp, i ) );
}
}
al_destroy( &tmp );
@@ -1290,24 +1293,26 @@ static void complete_cmd( const wchar_t *cmd,
al_init( &tmp );
expand_string( nxt_completion,
if( expand_string( nxt_completion,
&tmp,
ACCEPT_INCOMPLETE | DIRECTORIES_ONLY );
for( i=0; i<al_get_count(&tmp); i++ )
ACCEPT_INCOMPLETE | DIRECTORIES_ONLY ) != EXPAND_ERROR )
{
wchar_t *nxt = (wchar_t *)al_get( &tmp, i );
wchar_t *desc = wcsrchr( nxt, COMPLETE_SEP );
int is_valid = (desc && (wcscmp(desc,
COMPLETE_DIRECTORY_DESC)==0));
if( is_valid )
for( i=0; i<al_get_count(&tmp); i++ )
{
al_push( comp, nxt );
}
else
{
free(nxt);
wchar_t *nxt = (wchar_t *)al_get( &tmp, i );
wchar_t *desc = wcsrchr( nxt, COMPLETE_SEP );
int is_valid = (desc && (wcscmp(desc,
COMPLETE_DIRECTORY_DESC)==0));
if( is_valid )
{
al_push( comp, nxt );
}
else
{
free(nxt);
}
}
}
@@ -1766,7 +1771,10 @@ static void complete_param_expand( wchar_t *str,
else
comp_str = str;
// fwprintf( stderr, L"expand_string( \"%ls\", [list], EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls )\n", comp_str, do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
debug( 2,
L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );",
comp_str,
do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
expand_string( wcsdup(comp_str), comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) );
}
@@ -1963,7 +1971,7 @@ void complete( const wchar_t *cmd,
error_max=0;
/**
If we are completing a variable name or a tilde expantion user
If we are completing a variable name or a tilde expansion user
name, we do that and return. No need for any other competions.
*/
@@ -2009,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 ) )
{
@@ -2055,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,97 +0,0 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* CPU type */
#undef CPU
/* Documentation directory */
#undef DOCDIR
/* Define to 1 if you have the `futimes' function. */
#undef HAVE_FUTIMES
/* Define to 1 if you have the <getopt.h> header file. */
#undef HAVE_GETOPT_H
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the `rt' library (-lrt). */
#undef HAVE_LIBRT
/* Define to 1 if you have the `socket' library (-lsocket). */
#undef HAVE_LIBSOCKET
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <ncurses.h> header file. */
#undef HAVE_NCURSES_H
/* Define to 1 if HAVE_RLIMIT_AS is defined in <sys/resource.h>. */
#undef HAVE_RLIMIT_AS
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/resource.h> header file. */
#undef HAVE_SYS_RESOURCE_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <termio.h> header file. */
#undef HAVE_TERMIO_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the `wcswidth' function. */
#undef HAVE_WCSWIDTH
/* Define to 1 if you have the `wcwidth' function. */
#undef HAVE_WCWIDTH
/* Define to 1 if you have the `wprintf' function. */
#undef HAVE_WPRINTF
/* Define to 1 if you have the file `AC_File'. */
#undef HAVE__PROC_SELF_STAT
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Installation directory */
#undef PREFIX
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* System configuration directory */
#undef SYSCONFDIR
/* Evil kludge to get Power based machines to work */
#undef TPUTS_KLUDGE

View File

@@ -1,5 +1,5 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(fish,1.16.2,axel@liljencrantz.se)
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],
@@ -56,6 +65,7 @@ fi
AC_DEFINE_UNQUOTED( DOCDIR, [L"$(eval echo $docdir)"], [Documentation directory] )
AC_DEFINE_UNQUOTED( SYSCONFDIR, [L"$(eval echo $sysconfdir)"], [System configuration directory] )
AC_SUBST( SYSCONFDIR, ["$(eval echo $sysconfdir)"] )
# See if Linux procfs is present
AC_CHECK_FILES([/proc/self/stat])
@@ -64,7 +74,7 @@ AC_CHECK_FILES([/proc/self/stat])
AC_CHECK_FILE([/usr/pkg/lib],[AC_SUBST(LIBDIR,[-L/usr/pkg/lib\ -R/usr/pkg/lib])])
AC_CHECK_FILE([/usr/pkg/include],[AC_SUBST(INCLUDEDIR,[-I/usr/pkg/include])])
AC_CHECK_FUNCS( [wprintf futimes wcwidth wcswidth] )
AC_CHECK_FUNCS( [wprintf futimes wcwidth wcswidth getopt_long] )
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h])
# Check for RLIMIT_AS in sys/resource.h.
@@ -79,9 +89,48 @@ 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 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
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])])
@@ -90,5 +139,5 @@ AC_CHECK_HEADERS([ncurses.h],[AC_SUBST(CURSESLIB,[ncurses]) AC_DEFINE(HAVE_NCURS
#does not properly support terminfo.
AC_CHECK_FILE([/usr/pkg/include/ncurses.h],[AC_SUBST(CURSESLIB,[ncurses]) AC_DEFINE(HAVE_NCURSES_H)])
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile init/fish])
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile init/fish init/fish_interactive.fish init/fish_complete.fish])
AC_OUTPUT

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

@@ -4,6 +4,11 @@
<tt>complete (-c|--command|-p|--path) COMMAND [(-s|--short-option) SHORT_OPTION] [(-l|--long-option|-o|--old-option) LONG_OPTION [(-a||--arguments) OPTION_ARGUMENTS] [(-d|--description) DESCRIPTION] </tt>
\subsection complete-description Description
For an introduction to how to specify completions, see the section <a
href='index.html#completions-own'>Writing your own completions</a> of
the fish manual.
- <tt>COMMAND</tt> is the name of the command for which to add a completion
- <tt>SHORT_OPTION</tt> is a one character option for the command
- <tt>LONG_OPTION</tt> is a multi character option for the command
@@ -61,7 +66,9 @@ are valid, like the \c nodeps switch.
This can be written as:
<tt>complete -c rpm -n "__fish_contains_opt -s e erase" -l nodeps -d 'Dont check dependencies'</tt>
<tt>complete -c rpm -n "__fish_contains_opt -s e erase" -l nodeps -d
"Don't check dependencies"</tt>
where \c __fish_contains_opt is a function that checks the commandline buffer for the presense of a specified set of options.
where \c __fish_contains_opt is a function that checks the commandline
buffer for the presense of a specified set of options.

View File

@@ -16,7 +16,7 @@ the user does not have to worry about an array containing elements
such as dashes. \c fish performs a special check when invoking the
count program, and if the user uses a help option, this help page is
displayed, but if a help option is contained inside of a variable or
is the result of expantion, it will be passed on to the count program.
is the result of expansion, it will be passed on to the count program.
\subsection count-example Example

View File

@@ -1,15 +1,20 @@
/** \mainpage fish
/** \mainpage Fish user documentation
\c fish is a user friendly shell intended mostly for interactive use.
A shell is a program which allows you to execute other programs by
typing their names. For updates on \c fish, go to the <a
\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 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>.
\section syntax Syntax overview
Shells like \c fish are used by giving them commands. Every \c fish command follows the same simple syntax.
Shells like fish are used by giving them commands. Every \c fish
command follows the same simple syntax.
A command is executed by writing the name of the command followed by any arguments.
A command is executed by writing the name of the command followed by
any arguments.
Example:
@@ -18,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.
@@ -61,11 +66,13 @@ written on the same line by separating them with semicolons.
Sometimes features such as <a href="#globbing">parameter expansion</a>
and <a href="#escapes">character escapes</a> get in the way. When that
happens, the user can write a parameter within quotes, either '
(single quote) or " (double quote). There is no difference between
single quoted and double quoted strings. A quoted parameter will not
be parameter expanded, may contain spaces, and the only escape
sequences allowed is the corresponding quote character. Single and
double quotes may be nested.
(single quote) or " (double quote). There is one important difference
between single quoted and double quoted strings: When using double
quoted string, <a href='#expand-variable'>variable expansion</a> still
takes place. Other than that, a quoted parameter will not be
parameter expanded, may contain spaces, and escape sequences are
ignored. Single quotes have no special meaning withing double quotes
and vice versa.
Example:
@@ -113,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.
@@ -210,7 +217,7 @@ This is a short explanation of some of the commonly used words in fish.
- argument, a parameter given to a command
- builtin, a command that is implemented as part of the shell
- command, a program
- function, a command that is implemented as a set of fish commands
- function, a block of one or more fish commands that can be called as a single command. By using functions, it is possible to string together multiple smaller commands into one more advanced command.
- job, a running pipeline or command
- pipeline, a set of commands stringed together so that the output of one command is the input of the next command
- redirection, a operation that changes one of the input/output streams associated with a job
@@ -240,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:
@@ -264,34 +271,62 @@ in the known_hosts file. (see the ssh documentation for more information)
- The 'su' command complete using all users on the system
- The \c apt-get, \c rpm and \c tym commands complete using all installed packages.
Specifying your own completions is easy. If the command 'myprog' has
an option '-o' which can also be written as '--output', which requires
an additional value of either 'yes' or 'no' and decides if the program
should write anything, this can be specified by writing:
\subsection completion-own Writing your own completions
<tt>complete -c myprog -s o -l output -r -a "yes no" -d "Write output"</tt>
Specifying your own completions is not complicated. To specify a
completion, one simply uses the \c complete command. \c complete takes
as a parameter the name of the command to specify a completion
for. For example, to add a completion for the program \c myprog, one
would start the completion command with <tt>complete -c myprog
...</tt>. To provide a list of possible completions for myprog, use
the \c -a switch. If \c myprog accepts the arguments start and stop,
this can be specified as <tt>complete -c myprog -a 'start
stop'</tt>. The argument to the \c -a switch is always a single
string. At completion time, it will be tokenized on spaces and tabs,
and variable expansion, command substitution and other forms of
parameter expansion will take place.
For a more complete description of how to specify your own
completions, go <a href="builtins.html#complete">here</a> or write 'complete --help' in the \c fish shell.
Fish has a special syntax to support specifying switches accepted by a
command. The switches \c -s, \c -l and \c -o are used to specify a
short switch (single character, such as -l), a gnu style long switch (such as
--color) and an old-style long switch (like -shuffle),
respectively. If the command 'myprog' has an option '-o' which can
also be written as '--output', and which can take an additional value
of either 'yes' or 'no', this can be specified by writing:
<tt>complete -c myprog -s o -l output -a "yes no"</tt>
There are also special switches for specifying that a switch requires
an argument, to disable filename completion, to create completions
that are only available in some combinations, etc.. For a complete
description of the various switches accepted by the \c complete
command, see the documentation for the <a
href="builtins.html#complete">complete</a> builtin, or write 'complete
--help' inside the \c fish shell.
For examples of how to write your own complex completions, study the
completions in /etc/fish.d/completions (or ~/etc/fish.d/completions if
you installed fish in your home directory).
If you wish to use a completion, you should consider adding it to your
startup files. When completion has been requested for a command \c
COMMAND, fish will automatically look for the file
~/.fish.d/completions/COMMAND.fish. If it exists, it will be
automatically loaded. For examples of how to write your own complex
completions, study the completions in /etc/fish.d/completions (or ~/etc/fish.d/completions if you installed fish in your home directory).
automatically loaded. If you have written new completions for a common
Unix command, please consider sharing your work by sending it to <a
href='mailto: fish-users@lists.sf.net'>the fish mailinglist</a>.
\section expand Parameter expansion (Globbing)
When an argument for a program is given on the commandline, it
undergoes the process of parameter expantion before it is sent on to
undergoes the process of parameter expansion before it is sent on to
the command. There are many ways in which the user can specify a
parameter to be expanded. These include:
\subsection expand-wildcards Wildcards
\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 '/'.
@@ -300,17 +335,24 @@ Example:
<code>???</code> matches any file in the current directory whose name is exactly three characters long.
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
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 expantion,
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.
Example:
The command <code>echo (basename image.jpg .jpg).png</code> will output 'image.png'.
The command <code>echo (basename image.jpg .jpg).png</code> will
output 'image.png'.
The command <tt>for i in *.jpg; convert $i (basename $i .jpg).png;
end</tt> will convert all Jpeg files in the current directory to the
@@ -339,11 +381,44 @@ href="#variables"> Environment variables</a> section.
Example:
<tt> echo \$HOME</tt> prints the home directory of the current
user. If you wish to combine environment variables with text, you can
user.
If you wish to combine environment variables with text, you can
encase the variables within braces to embed a variable inside running
text like <tt>echo Konnichiwa {$USER}san</tt>, which will print a
personalized Japanese greeting.
The {$USER}san syntax might need a bit of an elaboration. Posix
shells allow you to specify a variable name using '$VARNAME' or
'${VARNAME}'. Fish only supports the former, but has no support
whatsoever for the latter or anything remotely like it. So what is
'{$VARNAME}' then? Well, '{WHATEVER}' is <a href='#brace'>brace
expansion</a>, the same as supported by Posix shells, i.e. 'a{b,c}d'
-> 'abd acd' works both in bash and on fish. So '{$VARNAME}' is a
bracket-expansion with only a single element, i.e. it becomes
expanded to '$VARNAME', which will be variable expanded to the value
of the variable 'VARNAME'. So you might think that the brackets don't
actually do anything, and that is nearly the truth. The snag is that
there once along the way was a '}' in there somewhere, and } is not a
valid character in a variable name. So anything after the otherwise
pointless bracket expansion becomes NOT a part of the variable name,
even if it happens to be a legal variable name character. That's why
'{$USER}san' works. A case of one syntax just lending itself so nicely
to solving an unrelated problem in it's spare time.
Variable expansion is the only type of expansion performed on double
quoted strings. There is, however, an important difference in how
variables are expanded when quoted and when unquoted. An unquoted
variable expansion will result in a variable number of arguments. For
example, if the variable $foo has zero elements or is undefined, the
argument $foo will expand to zero elements. If the variable $foo is an
array of five elements, the argument $foo will expand to five
elements. When quoted, like "$foo", a variable expansion will always
result in exactly one argument. Undefined variables will expand to the
empty string, and array variables will be concatenated using the space
character.
\subsection expand-home Home directory expansion
The ~ (tilde) character at the beginning of a parameter, followed by a
@@ -354,7 +429,7 @@ directory of the process owner.
\subsection expand-process Process expansion
The \% (percent) character at the beginning of a parameter followed by
a string is expanded into a process id. The following expantions are
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
@@ -394,7 +469,9 @@ will output 'abar1 abar2 abar3 afoo1 afoo2 afoo3'.
The concept of environment variables are central to any
shell. Environment variables are variables, whose values can be set
and used by the user.
and used by the user. For information on how to use the current value
of a variable, see the section on <a href='#expand-variable'>variable
expansion</a>.
To set a variable value, use the <a href="builtins.html#set"> \c set
command</a>.
@@ -409,25 +486,25 @@ the shell through <a href="expand-variable">variable expansion</a>.
Example:
To use the value of a the variable \c smurf, use the command <tt>echo
Smurfs are $smurf</tt>, which would print the result 'Smurfs are
blue'.
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'.
\subsection variables-scope Variable scope
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, 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 goes out of scope. A block of commands is a series of
commands that begins with one of the commands \c 'for, \c 'while' , \c
'if', \c 'function', \c 'begin' or \c 'switch', and ends with the
command \c 'end'. The user can specify that a variable should have
either global or local scope using the \c -g/--global or \c -l/--local
switches.
specific to the current fish session, but are not associated with any
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
goes out of scope. A block of commands is a series of commands that
begins with one of the commands \c 'for, \c 'while' , \c 'if', \c
'function', \c 'begin' or \c 'switch', and ends with the command \c
'end'. The user can specify that a variable should have either global
or local scope using the \c -g/--global or \c -l/--local switches.
Variables can be explicitly set to be universal with the \c -U or \c
--universal switch, global with the \c -g or \c --global switch, or
@@ -436,21 +513,24 @@ 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 current scope
-# 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
inside out, i.e. a local variable will be used rather than a global
variable with the same name, a global variable will be used rather
than a universal variable with the same name.
For example, the following code will not output anything:
Example:
The following code will not output anything:
<pre>
if true
begin
# This is a nice local scope where all variables will die
set pirate 'There be treasure in them thar hills'
set -l pirate 'There be treasure in them thar hills'
end
# This will not output anything, since the pirate is dead
# This will not output anything, since the pirate was local
echo $pirate
</pre>
@@ -472,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':
@@ -510,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
@@ -563,22 +643,25 @@ 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 preffered 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 values of these variables. They are:
values of certain environment variables. The user can not change the
values of these variables. They are:
- \c _, which is the name of the currently running command.
- \c history, which is an array containing the last commands that where entered
- \c history, which is an array containing the last commands that where entered.
- \c HOME, which is the users home directory. This variable can only be changed by the root user.
- \c PWD, which is the current working directory.
- \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.
Variables whose name are in uppercase are exported to the commands
started by fish. \c fish also uses several variables internally. Such
variables are prefixed with the string __FISH or __fish. These should
be ignored by the user.
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
__fish. These should be ignored by the user.
\section builtin-overview Builtins
@@ -599,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
@@ -654,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:
@@ -700,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)
@@ -721,24 +811,34 @@ After a command has been entered, it is inserted at the end of a
history list. Any duplicate history items are automatically
removed. By pressing the up and down keys, the user can search
forwards and backwards in the history. If the current command line is
not empty when starting a history search, only the commands starting
with the string entered into the command line are searched.
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.
Example:
To search for previous entries starting with the letter 'l', type 'l'
To search for previous entries containing the word 'make', type 'make'
in the console and press the up key.
\section job-control Running multiple programs
Normally when \c fish starts a program, this program will be put
in the foreground, meaning it will take control of the terminal and
\c fish will be stopped until the program finishes. Sometimes
this is not desirable. In such cases, there are several ways in which
the user can change <tt>fish</tt>'s behaviour.
Normally when \c fish starts a program, this program will be put in
the foreground, meaning it will take control of the terminal and \c
fish will be stopped until the program finishes. Sometimes this is not
desirable. For example, you may wish to start an application with a
graphical user interface from the terminal, and then be able to
continue using the shell. In such cases, there are several ways in
which the user can change <tt>fish</tt>'s behaviour.
-# By ending a command with the \& (ampersand) symbol, the user tells \c fish to put the specified command into the background. A background process will be run simultaneous with \c fish. \c fish will retain control of the terminal, so the program will not be able to read from the keyboard.
-# By pressing ^Z, the user stops a currently running foreground program and returns control to \c fish. Some programs do not support this feature, or remap it to another key. Gnu emacs uses ^X z to stop running.
@@ -746,14 +846,29 @@ the user can change <tt>fish</tt>'s behaviour.
\section initialization Initialization files
On startup, \c fish evaluates the file /etc/fish (Or ~/etc/fish if you installed fish in your home directory) and ~/.fish, in that
order. If you want to run a command only on starting an interactive
shell, use the output of the 'status --is-interactive' command. If
you want to run a command only on starting a login shell, use 'status --is-login' instead.
On startup, \c fish evaluates the file /etc/fish (Or ~/etc/fish if you
installed fish in your home directory) and ~/.fish, in that order. If
you want to run a command only on starting an interactive shell, use
the exit status of the command 'status --is-interactive' to determine
if the shell is interactive. If you want to run a command only on
starting a login shell, use 'status --is-login' instead.
If you want to run a set of commands when \c fish exits, redefine the
<a href="#hooks">function hook</a> \c fish_on_exit. If the \c
fish_on_exit is defined, it will be execute before the shell exits.
Example:
If you want to add the directory ~/linux/bin to your PATH variable
when loging in, add the following to your ~/.fish file:
<pre>if status --is-login
set PATH $PATH ~/linux/bin
end</pre>
If you want to run a set of commands when \c fish exits, use an <a
href='#event'>event handler</a> that is triggered by the exit of the
shell:
<pre>function on_exit --on-process %self
echo fish is now exiting
end</pre>
<a href="#variables-universal">Universal variables</a> are stored in
the file .fishd.HOSTNAME, where HOSTNAME is the name of your
@@ -772,7 +887,7 @@ marked red.
Detected errors include:
- Non existing commands.
- Reading or appending from non existing files.
- Reading from or appending to a non existing file.
- Incorrect use of output redirects
- Mismatched parenthesis
@@ -789,7 +904,7 @@ fish_pager_color_description and \c fish_pager_color_progress. Valid
values are \c black, \c red, \c green, \c brown, \c yellow, \c blue,
\c magenta, \c purple, \c cyan, \c white or \c normal. Setting one of
the above variables to normal will mean that the text color will be
set to the default color for the terminal.
set to the default foreground color for the terminal.
\subsection prompt Programmable prompt
@@ -804,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
@@ -835,15 +944,28 @@ end
</pre>
</p>
\subsection hooks Event hooks
\subsection event Event handlers
There are several special function names in fish. If a function is
given this name, it will be automatically called when a specific event
has occured. These functions are:
When defining a new function in fish, it is possible to make it into an
event handler, i.e. a function that is automatically run when a
specific event takes place. Events that can trigger a handler currently are:
- \c fish_on_exit, which is called before the shell exits
- \c fish_on_exec, which is called before interactively executing a command
- \c fish_on_return, which is called when control returns to the shell after interactively executing a command
* When a signal is delivered
* When a process or job exits
* When the value of a variable is updated
Example:
To specify a signal handler for the WINCH signal, write:
<pre>function --on-signal WINCH my_signal_handler
echo Got WINCH signal!
end
</pre>
For more information on how to define new event handlers, see the
documentation for the <a href='builtins.html#function'>function</a>
command.
\section issues Common issues with fish
@@ -860,9 +982,7 @@ directory, or install them in /etc.
\subsection todo-features Missing features
- Complete vi-mode key bindings
- '**' wildcard for recursive wildcard matching
- next-history-complete
- umask shellscript function
- builtin wait command
- More completions (for example xterm, vim,
konsole, gnome-terminal, dcop, cdrecord, cron, xargs
@@ -871,11 +991,10 @@ bibtex, patch, aspell, xpdf,
zip, compress, wine, xmms, dig, wine, batch, cron,
g++, javac, java, gcj, lpr, doxygen, whois, find)
- Undo support
- Multiple input characters should be inserted in one batch whenever possible, to avoid flickering
- 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
- 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
@@ -897,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
@@ -904,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
- Prefix string in completion display is sometimes incorrect
- 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
@@ -942,6 +1063,10 @@ Most tradeoffs between power and ease of use can be avoided with careful design.
-# Whenever possible without breaking the above goals, fish should
follow the Posix syntax.
To achive these high-level goals, the fish design relies on a number
of more specific design principles. These are presented below,
together with a rationale and a few examples for each.
\subsection ortho The law of orthogonality
The shell language should have a small set of orthogonal features. Any
@@ -958,7 +1083,10 @@ program harder to maintain and update.
Examples:
- Here documents are too similar to using echo inside of a pipeline.
- The different quoting styles are silly. ("", '' and \$'')
- Subshells, command substitution and process substitution are strongly related. \c fish only supports command substitution, the others can be achived either using a block or the psub shellscript function.
- Having both aliases and functions is confusing, especially since both of them have limitations and problems. \c fish sunctions have none of the drawbacks of either syntax.
- The many Posix quoting styles are silly, especially \$''.
\subsection sep The law of minimalism
@@ -990,9 +1118,8 @@ and many other funtions can easily be done in external programs. They
should not be supported internally by the shell.
The law of minimalism does not imply that a large feature set is
bad. So long as a feature is not part of the language itself, but a
separate command or at least a shellscript function, bloat is much
more acceptable.
bad. So long as a feature is not part of the shell itself, but a
separate command or at least a shellscript function, bloat is fine.
\subsection conf Configurability is the root of all evil
@@ -1015,7 +1142,7 @@ enough approximation of it.
Examples:
- Fish allows the user to set various syntax highlighting colors. This is needed because fish does not know what colors the terminal uses by default, which might make some things unreadable. The proper solution would be for text color preferences to be defined centrally by the user for all programs, and for the terminal emulator to send these color properties to fish.
- Fish does not allow you to set the history filename, the number of history entries, different language substyles or any number of other common cshell configuration options
- Fish does not allow you to set the history filename, the number of history entries, different language substyles or any number of other common shell configuration options.
A special note on the evils of configurability is the long list of
very useful features found in some shells, that are not turned on by
@@ -1033,13 +1160,18 @@ considered once a user interface has been designed.
Rationale:
If too much attention is given to what is easy to implement the law of
orthogonality and the law of minimalism will by necessity be disobeyed.
This design rule is different than the others, since it describes how
one should go about designing new features, not what the features
should be. The problem with focusing on what can be done, and what is
easy to do, is that to much of the implementation is exposed. This
means that the user must know a great deal about the underlying system
to be able to guess how the shell works, it also means that the
language will often be rather low-level.
Examples:
- There should only be one type of input to the shell, lists of commands. Loops, conditionals and variable assignments are all performed through regular commands.
- The differences between builtin commands, shellscript functions and builtin commands should be made as small as possible. Builtins and shellscript functions should have exactly the same types of argument expantion as other commands, should be possible to use in any position in a pipeline, and should support any io redirection.
- The differences between builtin commands, shellscript functions and builtin commands should be made as small as possible. Builtins and shellscript functions should have exactly the same types of argument expansion as other commands, should be possible to use in any position in a pipeline, and should support any io redirection.
- Instead of forking when performing command substitution to provide a fake variable scope, all fish commands are performed from the same process, and fish instead supports true scoping
- All blocks end with the \c end builtin
@@ -1074,7 +1206,6 @@ Examples:
/** \page about About fish
\section about-program About the program
\c fish is meant to be used for interactive shell tasks on a modern
@@ -1255,17 +1386,6 @@ builtin. The are very few builtins, \c fish relies on normal commands
like <tt>echo</tt>, <tt>kill</tt>, <tt>printf</tt> and <tt>time</tt>
instead of reimplementing them as builtins.
The globbing in fish is significantly simplified. Since I can never
remember all the subtle differences between single and double quotes,
which kind of tick is used for command substitution and all the other
strange quirks of of the Posix shell language, that aspect of shells
has been significantly simplified. This makes \c fish unsuitable for
strange shell scripting, but much more suited to interactive needs
than regular shells.
There is no difference between double and single quotes. They both
turn of all globbing and escape sequences. They can be nested.
Token separation is performed before variable expansion. This means
that even if a variable contains spaces, it will never be separated
into multiple arguments. If you want to tokenize a string, you can use

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\%.

View File

@@ -18,16 +18,12 @@ The <tt>set</tt> builtin causes fish to assign the variable <tt>VARIABLE_NAME</t
If set is called with no arguments, the names and values of all
environment variables are printed.
If set is called with only one argument, the scope of the variable
with the given name will be changed as specified, but it's value will
remain the same. If the variable did not previously exist, it's value
will be an empty string.
If the \c -e or \c --erase option is specified, the variable
specified by the following arguments will be erased
If a variable is set to more than one value, the variable will be an
array with the specified elements.
array with the specified elements. If a variable is set to zero
elements, it will become an array with zero elements.
If the variable name is one or more array elements, such as <tt>PATH[1
3 7]</tt>, only those array elements specified will be changed.

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.

113
env.c
View File

@@ -45,7 +45,7 @@
/**
Command used to start fishd
*/
#define FISHD_CMD L"if which fishd >/dev/null; fishd ^/tmp/fish.%s.log; end"
#define FISHD_CMD L"if which fishd >/dev/null; fishd ^/tmp/fishd.%s.log; end"
/**
Value denoting a null string
@@ -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 );
}
}
@@ -343,43 +342,66 @@ void env_init()
if( !path )
{
env_set( L"PATH", L"/bin" ARRAY_SEP_STR L"/usr/bin", ENV_EXPORT | ENV_GLOBAL );
path = env_get( L"PATH" );
}
else
{
int i;
int i, j;
array_list_t l;
int has_bin=0, has_usr_bin=0;
al_init( &l );
expand_variable_array( path, &l );
debug( 3, L"PATH is %ls", path );
for( i=0; i<al_get_count( &l); i++ )
{
wchar_t * el = (wchar_t *)al_get( &l, i );
if( contains_str( el, L"/bin", L"/bin/", (void *)0) )
const wchar_t *path_el[] =
{
has_bin = 1;
L"/bin",
L"/usr/bin",
PREFIX L"/bin",
0
}
if( contains_str( el, L"/usr/bin", L"/usr/bin/", (void *)0) )
;
for( j=0; path_el[j]; j++ )
{
int has_el=0;
debug( 3, L"Check directory %ls", path_el[j] );
for( i=0; i<al_get_count( &l); i++ )
{
has_bin = 1;
wchar_t * el = (wchar_t *)al_get( &l, i );
size_t len = wcslen( el );
while( (len > 0) && (el[len-1]==L'/') )
len--;
if( (wcslen( path_el[j] ) == len) && (wcsncmp( el, path_el[j], len)==0) )
{
has_el = 1;
}
}
if( !has_el )
{
string_buffer_t b;
debug( 3, L"directory %ls was missing", path_el[j] );
sb_init( &b );
sb_append2( &b, path,
ARRAY_SEP_STR,
path_el[j],
(void *)0 );
env_set( L"PATH", (wchar_t *)b.buff, ENV_GLOBAL | ENV_EXPORT );
sb_destroy( &b );
path = env_get( L"PATH" );
}
}
if( !( has_bin && has_usr_bin ) )
{
string_buffer_t b;
sb_init( &b );
sb_append( &b, path );
if( !has_bin )
sb_append( &b, ARRAY_SEP_STR L"/bin" );
if( !has_usr_bin )
sb_append( &b, ARRAY_SEP_STR L"/usr/bin" );
env_set( L"PATH", (wchar_t *)b.buff, ENV_GLOBAL | ENV_EXPORT );
sb_destroy( &b );
}
debug( 3, L"After: PATH is %ls", path );
al_foreach( &l, (void (*)(const void *))&free );
al_destroy( &l );
@@ -466,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 ) &&
@@ -569,8 +590,11 @@ void env_set( const wchar_t *key,
else
{
if( !proc_had_barrier)
{
proc_had_barrier=1;
env_universal_barrier();
}
if( env_universal_get( key ) )
{
int export = 0;
@@ -643,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 );
}
}
@@ -785,7 +809,11 @@ wchar_t *env_get( const wchar_t *key )
env = env->next;
}
if( !proc_had_barrier)
{
proc_had_barrier=1;
env_universal_barrier();
}
item = env_universal_get( key );
if( !item || (wcscmp( item, ENV_NULL )==0))
@@ -822,7 +850,11 @@ int env_exist( const wchar_t *key )
env = env->next;
}
if( !proc_had_barrier)
{
proc_had_barrier=1;
env_universal_barrier();
}
item = env_universal_get( key );
return item != 0;
@@ -1056,8 +1088,11 @@ static void export_func2( const void *k, const void *v, void *aux )
char **env_export_arr( int recalc)
{
if( recalc && !proc_had_barrier)
{
proc_had_barrier=1;
env_universal_barrier();
}
if( has_changed )
{
array_list_t uni;

View File

@@ -117,19 +117,16 @@ static int get_socket( int fork_ok )
if( connect( s, (struct sockaddr *)&local, len) == -1 )
{
close( s );
if( fork_ok )
if( fork_ok && start_fishd )
{
debug( 2, L"Could not connect to socket %d, starting fishd", s );
if( start_fishd )
{
start_fishd();
}
start_fishd();
return get_socket( 0 );
}
debug( 3, L"Could not connect to socket %d, already tried forking, giving up", s );
debug( 2, L"Could not connect to socket %d, already tried manual restart (or no command supplied), giving up", s );
return -1;
}
@@ -174,7 +171,7 @@ static void check_connection()
if( env_universal_server.killme )
{
debug( 2, L"Lost connection to universal variable server." );
debug( 3, L"Lost connection to universal variable server." );
close( env_universal_server.fd );
env_universal_server.fd = -1;
env_universal_server.killme=0;
@@ -193,7 +190,7 @@ static void reconnect()
if( get_socket_count >= RECONNECT_COUNT )
return;
debug( 2, L"Get new fishd connection" );
debug( 3, L"Get new fishd connection" );
init = 0;
env_universal_server.fd = get_socket(1);
@@ -262,6 +259,8 @@ int env_universal_read_all()
if( !init)
return 0;
debug( 3, L"env_universal_read_all()" );
if( env_universal_server.fd == -1 )
{
reconnect();
@@ -290,11 +289,13 @@ wchar_t *env_universal_get( const wchar_t *name )
if( !name )
return 0;
debug( 3, L"env_universal_get( \"%ls\" )", name );
return env_universal_common_get( name );
}
int env_universal_get_export( const wchar_t *name )
{
debug( 3, L"env_universal_get_export()" );
return env_universal_common_get_export( name );
}
@@ -305,7 +306,7 @@ void env_universal_barrier()
if( !init || ( env_universal_server.fd == -1 ))
return;
barrier_reply = 0;
/*
@@ -330,6 +331,7 @@ void env_universal_barrier()
if( env_universal_server.fd == -1 )
{
reconnect();
debug( 2, L"barrier interrupted, exiting" );
return;
}
@@ -347,6 +349,7 @@ void env_universal_barrier()
if( env_universal_server.fd == -1 )
{
reconnect();
debug( 2, L"barrier interrupted, exiting (2)" );
return;
}
FD_ZERO( &fds );
@@ -365,7 +368,7 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
if( !init )
return;
debug( 3, L"env_universal_set( %ls, %ls )", name, value );
debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name, value );
msg = create_message( export?SET_EXPORT:SET,
name,
@@ -388,8 +391,8 @@ void env_universal_remove( const wchar_t *name )
if( !init )
return;
debug( 2,
L"env_universal_remove( %ls )",
debug( 3,
L"env_universal_remove( \"%ls\" )",
name );
msg= create_message( ERASE, name, 0);

154
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,11 +317,14 @@ 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;
array_list_t *fire=0;
int was_subshell = is_subshell;
int was_interactive = is_interactive;
/*
First we free all events that have been removed
@@ -334,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 );
@@ -344,15 +396,22 @@ static void event_fire_internal( event_t *event, array_list_t *arguments )
// debug( 1, L"Event handler fires command '%ls'", (wchar_t *)b->buff );
/*
Event handlers are not part of the main flow of code, so
they are marked as non-interactive and as a subshell
*/
is_subshell=1;
is_interactive=1;
is_interactive=0;
eval( (wchar_t *)b->buff, 0, TOP );
is_subshell=0;
is_interactive=1;
}
/*
Restore interactivity flags
*/
is_subshell = was_subshell;
is_interactive = was_interactive;
if( b )
{
sb_destroy( b );
@@ -375,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
@@ -411,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) )
@@ -442,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--;
}
@@ -477,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 );
}

27
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;
/**
@@ -61,7 +70,17 @@ typedef struct
} param1;
/**
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;
@@ -95,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

44
exec.c
View File

@@ -261,17 +261,13 @@ static void handle_child_io( io_data_t *io )
free_fd( io, io->fd );
}
/*
We don't mind if this fails, it is just a speculative close
to make sure no unexpected untracked fd causes us to fail
*/
close(io->fd);
switch( io->io_mode )
{
case IO_CLOSE:
close(io->fd);
break;
case IO_FILE:
{
if( (tmp=wopen( io->param1.filename,
io->param2.flags, 0777 ) )==-1 )
{
@@ -284,6 +280,8 @@ static void handle_child_io( io_data_t *io )
}
else if( tmp != io->fd)
{
close(io->fd);
if(dup2( tmp, io->fd ) == -1 )
{
debug( 1,
@@ -295,7 +293,11 @@ static void handle_child_io( io_data_t *io )
exec_close( tmp );
}
break;
}
case IO_FD:
{
close(io->fd);
/* debug( 3, L"Redirect fd %d in process %ls (%d) from fd %d",
io->fd,
p->actual_cmd,
@@ -311,10 +313,12 @@ static void handle_child_io( io_data_t *io )
exit(1);
}
break;
}
case IO_BUFFER:
case IO_PIPE:
{
close(io->fd);
/* debug( 3, L"Pipe fd %d in process %ls (%d) (Through fd %d)",
io->fd,
@@ -937,15 +941,23 @@ void exec( job_t *j )
case INTERNAL_FUNCTION:
{
int status = proc_get_last_status();
/*
Handle output from a block or function. This usually
means do nothing, but in the case of pipes, we have
to buffer such io, since otherwisethe internal pipe
to buffer such io, since otherwise the internal pipe
buffer might overflow.
*/
if( !io_buffer )
{
/*
No buffer, se we exit directly. This means we
have to manually set the exit status.
*/
if( p->next == 0 )
{
proc_set_last_status( j->negate?(status?0:1):status);
}
p->completed = 1;
break;
}
@@ -956,8 +968,6 @@ void exec( job_t *j )
if( io_buffer->param2.out_buffer->used != 0 )
{
pid = fork();
if( pid == 0 )
{
@@ -1040,7 +1050,6 @@ void exec( job_t *j )
{
debug( 3, L"Set status of %ls to %d using short circut", j->command, p->status );
proc_set_last_status( p->status );
proc_set_last_status( j->negate?(p->status?0:1):p->status );
}
break;
@@ -1089,10 +1098,7 @@ void exec( job_t *j )
case EXTERNAL:
{
// fwprintf( stderr,
// L"fork on %ls\n", j->command );
pid = fork ();
pid = fork();
if( pid == 0 )
{
/*
@@ -1110,8 +1116,8 @@ void exec( job_t *j )
{
/* The fork failed. */
debug( 0, FORK_ERROR );
wperror (L"fork");
exit (1);
wperror( L"fork" );
exit( 1 );
}
else
{
@@ -1195,7 +1201,7 @@ int exec_subshell( const wchar_t *cmd,
if( !cmd )
{
debug( 1,
L"Sent null command to subshell. This is a fish bug. If it can be reproduced, please send a bug report to %ls",
L"Sent null command to subshell. This is a fish bug. If it can be reproduced, please send a bug report to %s",
PACKAGE_BUGREPORT );
return 0;
}

390
expand.c
View File

@@ -20,6 +20,8 @@ parameter expansion.
#include <unistd.h>
#include <signal.h>
#include <assert.h>
#ifdef SunOS
#include <procfs.h>
#endif
@@ -67,6 +69,9 @@ 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"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
*/
@@ -92,23 +97,29 @@ parameter expansion.
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
expantion on them actually does save a small amount of time.
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 )
{
const wchar_t * str = in;
/*
Test characters that have a special meaning in the first character position
*/
if( wcschr( UNCLEAN_FIRST, *str ) )
return 0;
/*
Test characters that have a special meaning in any character position
*/
while( *str )
{
if( wcschr( UNCLEAN, *str ) )
return 0;
str++;
}
// debug( 1, L"%ls", in );
return 1;
}
@@ -120,7 +131,7 @@ static wchar_t *expand_var( wchar_t *in )
{
if( !in )
return 0;
return (in[0] == VARIABLE_EXPAND )? env_get( expand_var(in+1) ) : env_get( in );
return env_get( in );
}
void expand_variable_array( const wchar_t *val, array_list_t *out )
@@ -133,7 +144,6 @@ void expand_variable_array( const wchar_t *val, array_list_t *out )
if( !cpy )
{
die_mem();
}
for( start=pos=cpy; *pos; pos++ )
@@ -146,7 +156,7 @@ void expand_variable_array( const wchar_t *val, array_list_t *out )
}
}
al_push( out, wcsdup(start) );
free(cpy);
}
}
@@ -196,7 +206,7 @@ wchar_t *expand_escape_variable( const wchar_t *in )
switch( al_get_count( &l) )
{
case 0:
sb_append( &buff, L"\'\'");
sb_append( &buff, L"''");
break;
case 1:
@@ -206,9 +216,9 @@ wchar_t *expand_escape_variable( const wchar_t *in )
if( wcschr( el, L' ' ) && is_quotable( el ) )
{
sb_append2( &buff,
L"\'",
L"'",
el,
L"\'",
L"'",
(void *)0 );
}
else
@@ -232,9 +242,9 @@ wchar_t *expand_escape_variable( const wchar_t *in )
if( is_quotable( el ) )
{
sb_append2( &buff,
L"\'",
L"'",
el,
L"\'",
L"'",
(void *)0 );
}
else
@@ -335,7 +345,8 @@ static int match_pid( const wchar_t *cmd,
Searches for a job with the specified job id, or a job or process
which has the string \c proc as a prefix of its commandline.
If accept_incomplete is true, the remaining string for any matches are inserted.
If accept_incomplete is true, the remaining string for any matches
are inserted.
If accept_incomplete is false, any job matching the specified
string is matched, and the job pgid is returned. If no job
@@ -358,8 +369,6 @@ static int find_process( const wchar_t *proc,
wchar_t *result;
job_t *j;
if( iswnumeric(proc) || (wcslen(proc)==0) )
{
@@ -693,11 +702,10 @@ static int expand_variables( wchar_t *in, array_list_t *out )
int is_ok= 1;
int empty=0;
for( i=wcslen(in)-1; (i>=0) && is_ok && !empty; i-- )
{
c = in[i];
if( c == VARIABLE_EXPAND )
if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) )
{
int start_pos = i+1;
int stop_pos;
@@ -706,15 +714,8 @@ static int expand_variables( wchar_t *in, array_list_t *out )
wchar_t * var_val;
wchar_t * new_in;
array_list_t l;
int is_single = (c==VARIABLE_EXPAND_SINGLE);
// fwprintf( stderr, L"Expand %ls\n", in );
// while (in[stop_pos]==VARIABLE_EXPAND)
// stop_pos++;
stop_pos = start_pos;
while( 1 )
@@ -731,106 +732,157 @@ static int expand_variables( wchar_t *in, array_list_t *out )
/* printf( "Stop for '%c'\n", in[stop_pos]);*/
var_len = stop_pos - start_pos;
if( var_len == 0 )
{
if( in[stop_pos] == BRACKET_BEGIN )
{
error( SYNTAX_ERROR,
-1, COMPLETE_VAR_DESC
COMPLETE_VAR2_DESC );
}
else
{
error( SYNTAX_ERROR,
-1,
COMPLETE_VAR_DESC);
}
is_ok = 0;
break;
}
if( !(var_name = malloc( sizeof(wchar_t)*(var_len+1) )))
{
die_mem();
}
else
{
wcsncpy( var_name, &in[start_pos], var_len );
var_name[var_len]='\0';
wcsncpy( var_name, &in[start_pos], var_len );
var_name[var_len]='\0';
/* printf( "Variable name is %s, len is %d\n", var_name, var_len );*/
wchar_t *var_val_orig = expand_var( var_name );
wchar_t *var_val_orig = expand_var( var_name );
if( var_val_orig && (var_val = wcsdup( var_val_orig) ) )
{
int all_vars=1;
array_list_t idx;
al_init( &idx );
al_init( &l );
if( var_val_orig && (var_val = wcsdup( var_val_orig) ) )
{
int all_vars=1;
array_list_t idx;
al_init( &idx );
al_init( &l );
if( in[stop_pos] == L'[' )
{
wchar_t *end;
if( in[stop_pos] == L'[' )
{
wchar_t *end;
all_vars = 0;
all_vars = 0;
stop_pos++;
while( 1 )
stop_pos++;
while( 1 )
{
int tmp;
while( iswspace(in[stop_pos]) || (in[stop_pos]==INTERNAL_SEPARATOR))
stop_pos++;
if( in[stop_pos] == L']' )
{
int tmp;
while( iswspace(in[stop_pos]) || (in[stop_pos]==INTERNAL_SEPARATOR))
stop_pos++;
if( in[stop_pos] == L']' )
{
stop_pos++;
break;
}
stop_pos++;
break;
}
errno=0;
tmp = wcstol( &in[stop_pos], &end, 10 );
if( ( errno ) || ( end == &in[stop_pos] ) )
errno=0;
tmp = wcstol( &in[stop_pos], &end, 10 );
if( ( errno ) || ( end == &in[stop_pos] ) )
{
error( SYNTAX_ERROR,
-1,
L"Expected integer or \']\'" );
is_ok = 0;
break;
}
al_push( &idx, (void *)tmp );
stop_pos = end-in;
}
}
if( is_ok )
{
expand_variable_array( var_val, &l );
if( !all_vars )
{
int j;
for( j=0; j<al_get_count( &idx ); j++)
{
int tmp = (int)al_get( &idx, j );
if( tmp < 1 || tmp > al_get_count( &l ) )
{
error( SYNTAX_ERROR,
L"Expected integer or \']\'",
-1 );
is_ok = 0;
-1,
L"Array index out of bounds" );
is_ok=0;
al_truncate( &idx, j );
break;
}
al_push( &idx, (void *)tmp );
stop_pos = end-in;
}
}
if( is_ok )
{
expand_variable_array( var_val, &l );
if( !all_vars )
{
int j;
for( j=0; j<al_get_count( &idx ); j++)
}
else
{
int tmp = (int)al_get( &idx, j );
if( tmp < 1 || tmp > al_get_count( &l ) )
{
error( SYNTAX_ERROR, L"Array index out of bounds", -1 );
is_ok=0;
al_truncate( &idx, j );
break;
}
else
{
/* Move string from list l to list idx */
al_set( &idx, j, al_get( &l, tmp-1 ) );
al_set( &l, tmp-1, 0 );
}
/* Move string from list l to list idx */
al_set( &idx, j, al_get( &l, tmp-1 ) );
al_set( &l, tmp-1, 0 );
}
/* Free remaining strings in list l and truncate it */
al_foreach( &l, (void (*)(const void *))&free );
al_truncate( &l, 0 );
/* Add items from list idx back to list l */
al_push_all( &l, &idx );
}
free( var_val );
}
/* Free remaining strings in list l and truncate it */
al_foreach( &l, (void (*)(const void *))&free );
al_truncate( &l, 0 );
/* Add items from list idx back to list l */
al_push_all( &l, &idx );
}
free( var_val );
}
if( is_single )
{
string_buffer_t res;
sb_init( &res );
in[i]=0;
sb_append( &res, in );
sb_append_char( &res, INTERNAL_SEPARATOR );
for( j=0; j<al_get_count( &l); j++ )
{
wchar_t *next = (wchar_t *)al_get( &l, j );
if( is_ok )
{
if( j != 0 )
sb_append( &res, L" " );
sb_append( &res, next );
}
free( next );
}
sb_append( &res, &in[stop_pos] );
is_ok &= expand_variables( wcsdup((wchar_t *)res.buff), out );
sb_destroy( &res );
}
else
{
for( j=0; j<al_get_count( &l); j++ )
{
wchar_t *next = (wchar_t *)al_get( &l, j );
if( is_ok )
{
new_len = wcslen(in) - (stop_pos-start_pos+1) + wcslen( next) +2;
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
{
error( OOM, L"Out of memory", -1 );
is_ok = 0;
die_mem();
}
else
{
@@ -853,21 +905,54 @@ static int expand_variables( wchar_t *in, array_list_t *out )
}
}
free( next );
}
al_destroy( &l );
al_destroy( &idx );
free(in);
free(var_name );
return is_ok;
}
}
al_destroy( &l );
al_destroy( &idx );
free(in);
free(var_name );
return is_ok;
}
else
{
/*
Expand a non-existing variable
*/
if( c == VARIABLE_EXPAND )
{
/*
Regular expansion, i.e. expand this argument to nothing
*/
empty = 1;
}
else
{
empty = 1;
/*
Expansion to single argument.
*/
string_buffer_t res;
sb_init( &res );
in[i]=0;
sb_append( &res, in );
sb_append( &res, &in[stop_pos] );
is_ok &= expand_variables( wcsdup((wchar_t *)res.buff), out );
sb_destroy( &res );
free(in);
free(var_name );
return is_ok;
}
free(var_name );
}
free(var_name );
}
prev_char = c;
}
@@ -966,7 +1051,9 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
if( syntax_error )
{
error( SYNTAX_ERROR, L"Mismatched brackets", -1 );
error( SYNTAX_ERROR,
-1,
L"Mismatched brackets" );
return 0;
}
@@ -1089,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;
}
@@ -1112,7 +1204,9 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
0 ) )
{
case -1:
error( SYNTAX_ERROR, L"Mismatched parans", -1 );
error( SYNTAX_ERROR,
-1,
L"Mismatched parans" );
return 0;
case 0:
al_push( out, in );
@@ -1191,26 +1285,25 @@ wchar_t *expand_unescape( const wchar_t * in, int escape_special )
{
wchar_t *res = unescape( in, escape_special );
if( !res )
error( SYNTAX_ERROR, L"Unexpected end of string", -1 );
error( SYNTAX_ERROR, -1, L"Unexpected end of string" );
return res;
}
/**
Attempts tilde expansion. Of the string specified. If tilde
expansion is performed, the argument is freed and a new string is
allocated in its place. Horrible call signature. Should be
altered. Fugly!
expansion is performed, the original string is freed and a new
string allocated using malloc is returned, otherwise, the original
string is returned.
*/
static int tilde_expand( wchar_t **ptr )
static wchar_t * expand_tilde_internal( wchar_t *in )
{
wchar_t *in = *ptr;
if( in[0] == HOME_DIRECTORY )
{
int tilde_error = 0;
wchar_t *home=0;
wchar_t *new_in;
wchar_t *old_in;
wchar_t *new_in=0;
wchar_t *old_in=0;
// fwprintf( stderr, L"Tilde expand ~%ls\n", (*ptr)+1 );
if( in[1] == '/' || in[1] == '\0' )
@@ -1267,26 +1360,23 @@ static int tilde_expand( wchar_t **ptr )
free(name);
}
if( !tilde_error )
if( !tilde_error && home && old_in )
{
new_in = wcsdupcat( home, old_in );
free( in );
in = new_in;
free(home);
*ptr = in;
}
}
free(home);
free( in );
return new_in;
}
return 1;
return in;
}
wchar_t *expand_tilde(wchar_t *in)
wchar_t *expand_tilde( wchar_t *in)
{
if( in[0] == L'~' )
{
in[0] = HOME_DIRECTORY;
tilde_expand( &in );
return in;
return expand_tilde_internal( in );
}
return in;
}
@@ -1300,8 +1390,6 @@ static void remove_internal_separator( const void *s, int conv )
wchar_t *in = (wchar_t *)s;
wchar_t *out=in;
// int changed=0;
while( *in )
{
switch( *in )
@@ -1325,16 +1413,11 @@ static void remove_internal_separator( const void *s, int conv )
}
}
*out=0;
/* if( changed )
{
fwprintf( stderr, L" -> %ls\n", s );
}
*/
}
/**
The real expansion function. All other expansion functions are wrappers to this one.
The real expansion function. expand_one is just a wrapper around this one.
*/
int expand_string( wchar_t *str,
array_list_t *end_out,
@@ -1345,11 +1428,15 @@ int expand_string( wchar_t *str,
int i;
int subshell_ok = 1;
int res = EXPAND_OK;
// debug( 1, L"Expand %ls", str );
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
{
al_push( end_out, str );
return 1;
return EXPAND_OK;
}
al_init( &list1 );
@@ -1367,11 +1454,11 @@ int expand_string( wchar_t *str,
if( (pos == str) || ( *(pos-1) != L'\\' ) )
{
error( SUBSHELL_ERROR, L"Subshells not allowed", -1 );
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
free( str );
al_destroy( &list1 );
al_destroy( &list2 );
return 0;
return EXPAND_ERROR;
}
pos++;
}
@@ -1385,7 +1472,7 @@ int expand_string( wchar_t *str,
if( !subshell_ok )
{
al_destroy( &list1 );
return 0;
return EXPAND_ERROR;
}
else
{
@@ -1400,7 +1487,7 @@ int expand_string( wchar_t *str,
1);
free( (void *)al_get( in, i ) );
if( !next )
continue;
@@ -1419,7 +1506,7 @@ int expand_string( wchar_t *str,
{
al_destroy( in );
al_destroy( out );
return 0;
return EXPAND_ERROR;
}
}
}
@@ -1436,7 +1523,7 @@ int expand_string( wchar_t *str,
{
al_destroy( in );
al_destroy( out );
return 0;
return EXPAND_ERROR;
}
}
al_truncate( in, 0 );
@@ -1447,21 +1534,26 @@ int expand_string( wchar_t *str,
for( i=0; i<al_get_count( in ); i++ )
{
wchar_t *next = (wchar_t *)al_get( in, i );
if(!tilde_expand( &next ))
if( !(next=expand_tilde_internal( next ) ) )
{
al_destroy( in );
al_destroy( out );
return 0;
return EXPAND_ERROR;
}
if( flags & ACCEPT_INCOMPLETE )
{
if( *next == PROCESS_EXPAND )
{
/*
If process expansion matches, we are not
interested in other completions, so we
short-circut and return
*/
expand_pid( next, flags, end_out );
al_destroy( in );
al_destroy( out );
return 1;
return EXPAND_OK;
}
else
al_push( out, next );
@@ -1472,7 +1564,7 @@ int expand_string( wchar_t *str,
{
al_destroy( in );
al_destroy( out );
return 0;
return EXPAND_ERROR;
}
}
}
@@ -1505,19 +1597,18 @@ int expand_string( wchar_t *str,
case 0:
if( !(flags & ACCEPT_INCOMPLETE) )
{
if( res == EXPAND_OK )
res = EXPAND_WILDCARD_NO_MATCH;
break;
}
case 1:
res = EXPAND_WILDCARD_MATCH;
sort_list( out );
al_push_all( end_out, out );
al_truncate( out, 0 );
break;
default:
fwprintf( stderr, L"error\n" );
/*al_destroy( &list1 );*/
/*al_destroy( &list2 );*/
/*return 0;*/
}
}
else
@@ -1532,7 +1623,8 @@ int expand_string( wchar_t *str,
al_destroy( out );
}
return 1;
return res;
}

View File

@@ -1,12 +1,12 @@
/**\file expand.h
Prototypes for string expantion functions. These functions perform
several kinds of parameter expantion. There are a lot of issues
Prototypes for string expansion functions. These functions perform
several kinds of parameter expansion. There are a lot of issues
with regards to memory allocation. Overall, these functions would
benefit from using a more clever memory allocation scheme, perhaps
an evil combination of talloc, string buffers and reference
counting.
*/
#ifndef FISH_EXPAND_H
@@ -20,17 +20,17 @@
#include "util.h"
/**
Flag specifying that subshell expantion should be skipped
Flag specifying that subshell expansion should be skipped
*/
#define EXPAND_SKIP_SUBSHELL 1
/**
Flag specifying that variable expantion should be skipped
Flag specifying that variable expansion should be skipped
*/
#define EXPAND_SKIP_VARIABLES 2
/**
Flag specifying that wildcard expantion should be skipped
Flag specifying that wildcard expansion should be skipped
*/
#define EXPAND_SKIP_WILDCARDS 4
@@ -64,20 +64,45 @@ enum
/** Character represeting a home directory */
HOME_DIRECTORY = EXPAND_RESERVED,
/** Character represeting process expantion */
/** Character represeting process expansion */
PROCESS_EXPAND,
/** Character representing variable expantion */
/** Character representing variable expansion */
VARIABLE_EXPAND,
/** Character representing the start of a bracket expantion */
/** Character rpresenting variable expansion into a single element*/
VARIABLE_EXPAND_SINGLE,
/** Character representing the start of a bracket expansion */
BRACKET_BEGIN,
/** Character representing the end of a bracket expantion */
/** Character representing the end of a bracket expansion */
BRACKET_END,
/** Character representing separation between two bracket elements */
BRACKET_SEP,
/**
Separate subtokens in a token with this character.
*/
INTERNAL_SEPARATOR,
}
;
/**
These are the possible return values for expand_string
*/
enum
{
/** Error */
EXPAND_ERROR,
/** Ok */
EXPAND_OK,
/** Ok, a wildcard in the string matched no files */
EXPAND_WILDCARD_NO_MATCH,
/* Ok, a wildcard in the string matched a file */
EXPAND_WILDCARD_MATCH
}
;
@@ -87,18 +112,13 @@ enum
/** String containing the character for separating two array elements */
#define ARRAY_SEP_STR L"\x1e"
/**
Separate subtokens in a token with this character.
*/
#define INTERNAL_SEPARATOR 0xfffffff0
/**
Perform various forms of expansion on in, such as tilde expansion
(~USER becomes the users home directory), variable expansion
($VAR_NAME becomes the value of the environment variable VAR_NAME),
subshell expantion and wildcard expansion. The results are inserted
subshell expansion and wildcard expansion. The results are inserted
into the list out.
If the parameter does not need expansion, it is copied into the list
@@ -106,8 +126,9 @@ enum
newly allocated strings are inserted into the list out.
\param in The parameter to expand
\param flag Specifies if any expantion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
\param out The list to which the result will be appended.
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH
*/
int expand_string( wchar_t *in, array_list_t *out, int flag );
@@ -117,7 +138,7 @@ int expand_string( wchar_t *in, array_list_t *out, int flag );
names.
\param in The parameter to expand
\param flag Specifies if any expantion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
\return The expanded parameter, or 0 on failiure
*/
wchar_t *expand_one( wchar_t *in, int flag );
@@ -154,9 +175,9 @@ wchar_t *expand_escape_variable( const wchar_t *in );
/**
Perform tilde expantion and nothing else on the specified string.
Perform tilde expansion and nothing else on the specified string.
If tilde expantion is needed, the original string is freed and a
If tilde expansion is needed, the original string is freed and a
new string, allocated using malloc, is returned.
*/
wchar_t *expand_tilde(wchar_t *in);

View File

@@ -69,6 +69,9 @@ fi
%config %_sysconfdir/fish.d/completions/*.fish
%changelog
* Tue Nov 29 2005 Axel Liljencrantz <axel@liljencrantz.se> 1.17.0-0
- 1.17.0
* Sat Sep 24 2005 Axel Liljencrantz <axel@liljencrantz.se> 1.14.0-0
- 1.14.0

View File

@@ -518,7 +518,7 @@ static void test_parser()
}
/**
Perform parameter expantion and test if the output equals the zero-terminated parameter list supplied.
Perform parameter expansion and test if the output equals the zero-terminated parameter list supplied.
\param in the string to expand
\param flags the flags to send to expand_string
@@ -561,11 +561,11 @@ static int expand_test( const wchar_t *in, int flags, ... )
}
/**
Test globbing and other parameter expantion
Test globbing and other parameter expansion
*/
static void test_expand()
{
say( L"Testing parameter expantion" );
say( L"Testing parameter expansion" );
if( !expand_test( L"foo", 0, L"foo", 0 ))
{
@@ -574,12 +574,12 @@ static void test_expand()
if( !expand_test( L"a{b,c,d}e", 0, L"abe", L"ace", L"ade", 0 ) )
{
err( L"Bracket expantion is broken" );
err( L"Bracket expansion is broken" );
}
if( !expand_test( L"a*", EXPAND_SKIP_WILDCARDS, L"a*", 0 ) )
{
err( L"Cannot skip wildcard expantion" );
err( L"Cannot skip wildcard expansion" );
}
}

60
fishd.c
View File

@@ -70,6 +70,11 @@ static connection_t *conn;
*/
static int sock;
/**
Set to one when fishd should save and exit
*/
static int quit=0;
/**
Constructs the fish socket filename
*/
@@ -110,6 +115,15 @@ static char *get_socket_filename()
return name;
}
/**
Signal handler for the term signal.
*/
static void handle_term( int signal )
{
quit=1;
}
/**
Acquire the lock for the socket
Returns the name of the lock file if successful or
@@ -268,26 +282,37 @@ static void daemonize()
case 0:
{
/*
Make fishd ignore the HUP signal.
*/
struct sigaction act;
sigemptyset( & act.sa_mask );
act.sa_flags=0;
act.sa_handler=SIG_IGN;
sigaction( SIGHUP, &act, 0);
/*
Make fishd save and exit on the TERM signal.
*/
sigfillset( & act.sa_mask );
act.sa_flags=0;
act.sa_handler=&handle_term;
sigaction( SIGTERM, &act, 0);
break;
}
default:
{
debug( 0, L"Parent calling exit" );
debug( 0, L"Parent process exiting (This is normal)" );
exit(0);
}
}
/*
Put ourself in out own processing group
*/
setsid();
/*
Close stdin and stdout. We only use stderr, anyway.
*/
@@ -386,8 +411,9 @@ static void init()
*/
int main( int argc, char ** argv )
{
int child_socket, t;
int child_socket;
struct sockaddr_un remote;
socklen_t t;
int max_fd;
int update_count=0;
@@ -416,15 +442,27 @@ int main( int argc, char ** argv )
FD_SET( c->fd, &write_fd );
}
}
res=select( max_fd, &read_fd, &write_fd, 0, 0 );
if( res==-1 )
while( 1 )
{
wperror( L"select" );
exit(1);
res=select( max_fd, &read_fd, &write_fd, 0, 0 );
if( quit )
{
save();
exit(0);
}
if( res != -1 )
break;
if( errno != EINTR )
{
wperror( L"select" );
exit(1);
}
}
if( FD_ISSET( sock, &read_fd ) )
{
if( (child_socket =

View File

@@ -58,7 +58,7 @@ void function_set_desc( const wchar_t *name, const wchar_t *desc );
/**
Returns true if the function witrh the name name exists.
*/
int function_exists( const wchar_t *name);
int function_exists( const wchar_t *name );
/**
Insert all function names into l. These are not copies of the strings and should not be freed after use.

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

@@ -1,11 +1,12 @@
function __fish_complete_apropos
if test (commandline -ct)
set str (commandline -ct)
apropos $str|sed -e 's/^\(.*'$str'\([^ ]*\).*\)$/'$str'\2\t\1/'
apropos $str|sed -e "s/^\(.*$str\([^ ]*\).*\)$/$str\2\t\1/"
end
end
complete -xc apropos -a "(__fish_complete_apropos)" -d "Whatis entry"
complete -xc apropos -a '(__fish_complete_apropos)' -d "Whatis entry"
complete -c apropos -s h -l help -d "apropos command help"
complete -f -c apropos -s d -l debug -d "print debugging info"
@@ -14,7 +15,7 @@ complete -f -c apropos -s r -l regex -d "keyword as regex"
complete -f -c apropos -s w -l wildcard -d "keyword as wildwards"
complete -f -c apropos -s e -l exact -d "keyword as exactly match"
complete -x -c apropos -s m -l system -d "search for other system"
complete -x -c apropos -s M -l manpath -a "(echo $MANPATH)" -d "specify man path"
complete -x -c apropos -s M -l manpath -a '(echo $MANPATH)' -d "specify man path"
complete -x -c apropos -s C -l config-file -d "specify a conf file"
complete -f -c apropos -s V -l version -d "Display version"

View File

@@ -1,6 +1,6 @@
#completion for apt-get
function __fish_apt_no_subcommand -d "test if apt has yet to be given the subcommand"
function __fish_apt_no_subcommand -d 'test if apt has yet to be given the subcommand'
for i in (commandline -opc)
if contains -- $i update upgrade dselect-upgrade dist-upgrade install remove source build-dep check clean autoclean
return 1
@@ -9,7 +9,7 @@ function __fish_apt_no_subcommand -d "test if apt has yet to be given the subcom
return 0
end
function __fish_apt_use_package -d "Test if apt command should have packages as potential completion"
function __fish_apt_use_package -d 'Test if apt command should have packages as potential completion'
for i in (commandline -opc)
if contains -- $i contains install remove build-dep
return 0
@@ -18,47 +18,47 @@ function __fish_apt_use_package -d "Test if apt command should have packages as
return 1
end
complete -c apt-get -n "__fish_apt_use_package" -a "(__fish_print_packages)" -d "Package"
complete -c apt-get -n '__fish_apt_use_package' -a '(__fish_print_packages)' -d 'Package'
complete -c apt-get -s h -l help -d "apt-get command help"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "update" -d "update sources"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "upgrade" -d "upgrade or install newest packages"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "dselect-upgrade" -d "use with dselect front-end"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "dist-upgrade" -d "distro upgrade"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "install" -d "install one or more packages"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "remove" -d "remove one or more packages"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "source" -d "fetch source packages"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "build-dep" -d "install/remove packages for dependencies"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "check" -d "update cache and check dep"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "clean" -d "clean local caches and packages"
complete -f -n "__fish_apt_no_subcommand" -c apt-get -a "autoclean" -d "clean packages no longer be downloaded"
complete -c apt-get -s d -l download-only -d "Download Only"
complete -c apt-get -s f -l fix-broken -d "correct broken deps"
complete -c apt-get -s m -l fix-missing -d "ignore missing packages"
complete -c apt-get -l no-download -d "Disable downloading packages"
complete -c apt-get -s q -l quiet -d "quiet output"
complete -c apt-get -s s -l simulate -d "perform a siulation"
complete -c apt-get -s y -l assume-yes -d "automatic yes to prompts"
complete -c apt-get -s u -l show-upgraded -d "show upgraded packages"
complete -c apt-get -s V -l verbose-versions -d "show full versions for packages"
complete -c apt-get -s b -l compile -d "compile source packages"
complete -c apt-get -s b -l build -d "compile source packages"
complete -c apt-get -l ignore-hold -d "ignore package Holds"
complete -c apt-get -l no-upgrade -d "Do not upgrade packages"
complete -c apt-get -l force-yes -d "Force yes"
complete -c apt-get -l print-uris -d "print the URIs"
complete -c apt-get -l purge -d "use purge instead of remove"
complete -c apt-get -l reinstall -d "reinstall packages"
complete -c apt-get -l list-cleanup -d "erase obsolete files"
complete -c apt-get -s t -l target-release -d "control default input to the policy engine"
complete -c apt-get -l trivial-only -d "only perform operations that are trivial"
complete -c apt-get -l no-remove -d "abort if any packages are to be removed"
complete -c apt-get -l only-source -d "only accept source packages"
complete -c apt-get -l diff-only -d "download only diff file"
complete -c apt-get -l tar-only -d "download only tar file"
complete -c apt-get -l arch-only -d "only process arch-dep build-deps"
complete -c apt-get -l allow-unauthenticated -d "ignore non-authenticated packages"
complete -c apt-get -s v -l version -d "show program version"
complete -r -c apt-get -s c -l config-file -d "specify a config file"
complete -r -c apt-get -s o -l option -d "set a config option"
complete -c apt-get -s h -l help -d 'apt-get command help'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'update' -d 'update sources'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'upgrade' -d 'upgrade or install newest packages'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'dselect-upgrade' -d 'use with dselect front-end'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'dist-upgrade' -d 'distro upgrade'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'install' -d 'install one or more packages'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'remove' -d 'remove one or more packages'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'source' -d 'fetch source packages'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'build-dep' -d 'install/remove packages for dependencies'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'check' -d 'update cache and check dep'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'clean' -d 'clean local caches and packages'
complete -f -n '__fish_apt_no_subcommand' -c apt-get -a 'autoclean' -d 'clean packages no longer be downloaded'
complete -c apt-get -s d -l download-only -d 'Download Only'
complete -c apt-get -s f -l fix-broken -d 'correct broken deps'
complete -c apt-get -s m -l fix-missing -d 'ignore missing packages'
complete -c apt-get -l no-download -d 'Disable downloading packages'
complete -c apt-get -s q -l quiet -d 'quiet output'
complete -c apt-get -s s -l simulate -d 'perform a siulation'
complete -c apt-get -s y -l assume-yes -d 'automatic yes to prompts'
complete -c apt-get -s u -l show-upgraded -d 'show upgraded packages'
complete -c apt-get -s V -l verbose-versions -d 'show full versions for packages'
complete -c apt-get -s b -l compile -d 'compile source packages'
complete -c apt-get -s b -l build -d 'compile source packages'
complete -c apt-get -l ignore-hold -d 'ignore package Holds'
complete -c apt-get -l no-upgrade -d 'Do not upgrade packages'
complete -c apt-get -l force-yes -d 'Force yes'
complete -c apt-get -l print-uris -d 'print the URIs'
complete -c apt-get -l purge -d 'use purge instead of remove'
complete -c apt-get -l reinstall -d 'reinstall packages'
complete -c apt-get -l list-cleanup -d 'erase obsolete files'
complete -c apt-get -s t -l target-release -d 'control default input to the policy engine'
complete -c apt-get -l trivial-only -d 'only perform operations that are trivial'
complete -c apt-get -l no-remove -d 'abort if any packages are to be removed'
complete -c apt-get -l only-source -d 'only accept source packages'
complete -c apt-get -l diff-only -d 'download only diff file'
complete -c apt-get -l tar-only -d 'download only tar file'
complete -c apt-get -l arch-only -d 'only process arch-dep build-deps'
complete -c apt-get -l allow-unauthenticated -d 'ignore non-authenticated packages'
complete -c apt-get -s v -l version -d 'show program version'
complete -r -c apt-get -s c -l config-file -d 'specify a config file'
complete -r -c apt-get -s o -l option -d 'set a config option'

View File

@@ -1,10 +1,10 @@
#apt-proxy-import
complete -c apt-proxy-import -s h -l help -d "apt-proxy-import command help"
complete -f -c apt-proxy-import -s V -l version -d "print version"
complete -f -c apt-proxy-import -s v -l verbose -d "verbose info"
complete -f -c apt-proxy-import -s q -l quiet -d "no message to STDOUT"
complete -f -c apt-proxy-import -s r -l recursive -d "recurse into subdir"
complete -r -c apt-proxy-import -s i -l import-dir -a "(ls -Fp|grep /$)" -d "dir to import"
complete -r -c apt-proxy-import -s u -l user -a "(__fish_complete_users)" -d "change to user"
complete -r -c apt-proxy-import -s d -l debug -d "debug level[default 0]"
complete -c apt-proxy-import -s h -l help -d 'apt-proxy-import command help'
complete -f -c apt-proxy-import -s V -l version -d 'print version'
complete -f -c apt-proxy-import -s v -l verbose -d 'verbose info'
complete -f -c apt-proxy-import -s q -l quiet -d 'no message to STDOUT'
complete -f -c apt-proxy-import -s r -l recursive -d 'recurse into subdir'
complete -r -c apt-proxy-import -s i -l import-dir -a '(ls -Fp|grep /$)' -d 'dir to import'
complete -r -c apt-proxy-import -s u -l user -a '(__fish_complete_users)' -d 'change to user'
complete -r -c apt-proxy-import -s d -l debug -d 'debug level[default 0]'

View File

@@ -1,10 +1,10 @@
#apt-show-source
complete -c apt-show-source -s h -l help -d "apt-show-source command help"
complete -r -c apt-show-source -l status-file -d "read pkg from FILE" -f
complete -r -c apt-show-source -o stf -d "read pkg from FILE" -f
complete -r -c apt-show-source -l list-dir -a "(ls -Fp .|grep /$) /var/lib/apt/lists" -d "specify APT list dir"
complete -r -c apt-show-source -o ld -a "(ls -Fp .|grep /$) /var/lib/apt/lists" -d "specify APT list dir"
complete -r -c apt-show-source -s p -l package -a "(apt-cache pkgnames)" -d "list PKG info"
complete -f -c apt-show-source -l version-only -d "print version only"
complete -f -c apt-show-source -s a -l all -d "print all src pkgs with version"
complete -f -c apt-show-source -s v -l verbose -d "verbose message"
complete -c apt-show-source -s h -l help -d 'apt-show-source command help'
complete -r -c apt-show-source -l status-file -d 'read pkg from FILE' -f
complete -r -c apt-show-source -o stf -d 'read pkg from FILE' -f
complete -r -c apt-show-source -l list-dir -a '(ls -Fp .|grep /$) /var/lib/apt/lists' -d 'specify APT list dir'
complete -r -c apt-show-source -o ld -a '(ls -Fp .|grep /$) /var/lib/apt/lists' -d 'specify APT list dir'
complete -r -c apt-show-source -s p -l package -a '(apt-cache pkgnames)' -d 'list PKG info'
complete -f -c apt-show-source -l version-only -d 'print version only'
complete -f -c apt-show-source -s a -l all -d 'print all src pkgs with version'
complete -f -c apt-show-source -s v -l verbose -d 'verbose message'

View File

@@ -1,14 +1,14 @@
#apt-show-versions
complete -c apt-show-source -s h -l help -d "apt-show-versions command help"
complete -r -c apt-show-versions -s p -l packages -a "(apt-cache pkgnames)" -d "print PKG versions"
complete -f -c apt-show-versions -s r -l regex -d "using regex"
complete -f -c apt-show-versions -s u -l upgradeable -d "print only upgradeable pkgs"
complete -f -c apt-show-versions -s a -l allversions -d "print all versions"
complete -f -c apt-show-versions -s b -l brief -d "print pkg name/distro"
complete -f -c apt-show-versions -s v -l verbose -d "print verbose info"
complete -f -c apt-show-versions -s i -l initialize -d "init or update cache only"
complete -r -c apt-show-versions -l status-file -d "read pkg from FILE"
complete -r -c apt-show-versions -o stf -d "read pkg from FILE"
complete -r -c apt-show-versions -l list-dir -a "(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists" -d "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 "specify APT list dir"
complete -c apt-show-source -s h -l help -d 'apt-show-versions command help'
complete -r -c apt-show-versions -s p -l packages -a '(apt-cache pkgnames)' -d 'print PKG versions'
complete -f -c apt-show-versions -s r -l regex -d 'using regex'
complete -f -c apt-show-versions -s u -l upgradeable -d 'print only upgradeable pkgs'
complete -f -c apt-show-versions -s a -l allversions -d 'print all versions'
complete -f -c apt-show-versions -s b -l brief -d 'print pkg name/distro'
complete -f -c apt-show-versions -s v -l verbose -d 'print verbose info'
complete -f -c apt-show-versions -s i -l initialize -d 'init or update cache only'
complete -r -c apt-show-versions -l status-file -d 'read pkg from FILE'
complete -r -c apt-show-versions -o stf -d 'read pkg from FILE'
complete -r -c apt-show-versions -l list-dir -a '(ls -Fp .|grep /$) /var/lib/apt/lists /var/state/apt/lists' -d '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 'specify APT list dir'

View File

@@ -1,12 +1,12 @@
complete -c cat -s A -l show-all -d "Escape all non-printing characters"
complete -c cat -s b -l number-nonblank -d "Number nonblank lines"
complete -c cat -s e -d "Escape non-printing characters except tab"
complete -c cat -s E -l show-ends -d "Display $ at end of line"
complete -c cat -s n -l number -d "Number all lines"
complete -c cat -s s -l squeeze-blank -d "Never more than single blank line"
complete -c cat -s t -d "Escape non-printing characters except newline"
complete -c cat -s T -l show-tabs -d "Escape tab"
complete -c cat -s v -d "Escape non-printing except newline and tab"
complete -c cat -l help -d "Display help and exit"
complete -c cat -l version -d "Display version and exit"
complete -c cat -s A -l show-all -d 'Escape all non-printing characters'
complete -c cat -s b -l number-nonblank -d 'Number nonblank lines'
complete -c cat -s e -d 'Escape non-printing characters except tab'
complete -c cat -s E -l show-ends -d 'Display $ at end of line'
complete -c cat -s n -l number -d 'Number all lines'
complete -c cat -s s -l squeeze-blank -d 'Never more than single blank line'
complete -c cat -s t -d 'Escape non-printing characters except newline'
complete -c cat -s T -l show-tabs -d 'Escape tab'
complete -c cat -s v -d 'Escape non-printing except newline and tab'
complete -c cat -l help -d 'Display help and exit'
complete -c cat -l version -d 'Display version and exit'

View File

@@ -2,52 +2,52 @@
# I don't use CVS, so these completions are probably not all that good.
#
complete -c cvs -x -a "add" -d "Add a new file/directory to the repository"
complete -c cvs -x -a "admin" -d "Administration front end for rcs"
complete -c cvs -x -a "annotate" -d "Show last revision where each line was modified"
complete -c cvs -x -a "checkout" -d "Checkout sources for editing"
complete -c cvs -x -a "commit" -d "Check files into the repository"
complete -c cvs -x -a "diff" -d "Show differences between revisions"
complete -c cvs -x -a "edit" -d "Get ready to edit a watched file"
complete -c cvs -x -a "editors" -d "See who is editing a watched file"
complete -c cvs -x -a "export" -d "Export sources from CVS, similar to checkout"
complete -c cvs -x -a "history" -d "Show repository access history"
complete -c cvs -x -a "import" -d "Import sources into CVS, using vendor branches"
complete -c cvs -x -a "init" -d "Create a CVS repository if it doesnt exist"
complete -c cvs -x -a "kserver" -d "Kerberos server mode"
complete -c cvs -x -a "log" -d "Print out history information for files"
complete -c cvs -x -a "login" -d "Prompt for password for authenticating server"
complete -c cvs -x -a "logout" -d "Removes entry in .cvspass for remote repository"
complete -c cvs -x -a "pserver" -d "Password server mode"
complete -c cvs -x -a "rannotate" -d "Show last revision where each line of module was modified"
complete -c cvs -x -a "rdiff" -d "Create 'patch' format diffs between releases"
complete -c cvs -x -a "release" -d "Indicate that a Module is no longer in use"
complete -c cvs -x -a "remove" -d "Remove an entry from the repository"
complete -c cvs -x -a "rlog" -d "Print out history information for a module"
complete -c cvs -x -a "rtag" -d "Add a symbolic tag to a module"
complete -c cvs -x -a "server" -d "Server mode"
complete -c cvs -x -a "status" -d "Display status information on checked out files"
complete -c cvs -x -a "tag" -d "Add a symbolic tag to checked out version of files"
complete -c cvs -x -a "unedit" -d "Undo an edit command"
complete -c cvs -x -a "update" -d "Bring work tree in sync with repository"
complete -c cvs -x -a "version" -d "Show current CVS version(s)"
complete -c cvs -x -a "watch" -d "Set watches"
complete -c cvs -x -a "watchers" -d "See who is watching a file"
complete -c cvs -x -a 'add' -d 'Add a new file/directory to the repository'
complete -c cvs -x -a 'admin' -d 'Administration front end for rcs'
complete -c cvs -x -a 'annotate' -d 'Show last revision where each line was modified'
complete -c cvs -x -a 'checkout' -d 'Checkout sources for editing'
complete -c cvs -x -a 'commit' -d 'Check files into the repository'
complete -c cvs -x -a 'diff' -d 'Show differences between revisions'
complete -c cvs -x -a 'edit' -d 'Get ready to edit a watched file'
complete -c cvs -x -a 'editors' -d 'See who is editing a watched file'
complete -c cvs -x -a 'export' -d 'Export sources from CVS, similar to checkout'
complete -c cvs -x -a 'history' -d 'Show repository access history'
complete -c cvs -x -a 'import' -d 'Import sources into CVS, using vendor branches'
complete -c cvs -x -a 'init' -d 'Create a CVS repository if it doesnt exist'
complete -c cvs -x -a 'kserver' -d 'Kerberos server mode'
complete -c cvs -x -a 'log' -d 'Print out history information for files'
complete -c cvs -x -a 'login' -d 'Prompt for password for authenticating server'
complete -c cvs -x -a 'logout' -d 'Removes entry in .cvspass for remote repository'
complete -c cvs -x -a 'pserver' -d 'Password server mode'
complete -c cvs -x -a 'rannotate' -d 'Show last revision where each line of module was modified'
complete -c cvs -x -a 'rdiff' -d 'Create "patch" format diffs between releases'
complete -c cvs -x -a 'release' -d 'Indicate that a Module is no longer in use'
complete -c cvs -x -a 'remove' -d 'Remove an entry from the repository'
complete -c cvs -x -a 'rlog' -d 'Print out history information for a module'
complete -c cvs -x -a 'rtag' -d 'Add a symbolic tag to a module'
complete -c cvs -x -a 'server' -d 'Server mode'
complete -c cvs -x -a 'status' -d 'Display status information on checked out files'
complete -c cvs -x -a 'tag' -d 'Add a symbolic tag to checked out version of files'
complete -c cvs -x -a 'unedit' -d 'Undo an edit command'
complete -c cvs -x -a 'update' -d 'Bring work tree in sync with repository'
complete -c cvs -x -a 'version' -d 'Show current CVS version(s)'
complete -c cvs -x -a 'watch' -d 'Set watches'
complete -c cvs -x -a 'watchers' -d 'See who is watching a file'
complete -c cvs -x -s H -d "Displays usage information for command"
complete -c cvs -x -s Q -d "Cause CVS to be really quiet"
complete -c cvs -x -s q -d "Cause CVS to be somewhat quiet"
complete -c cvs -x -s r -d "Make checked-out files read-only"
complete -c cvs -x -s w -d "Make checked-out files read-write (default)"
complete -c cvs -x -s n -d "Do not execute anything that will change the disk"
complete -c cvs -x -s t -d "Show trace of program execution -- try with -n"
complete -c cvs -x -s v -d "CVS version and copyright"
complete -c cvs -x -s T -r -d "Use 'tmpdir' for temporary files"
complete -c cvs -x -s e -r -d "Use 'editor' for editing log information"
complete -c cvs -x -s d -r -d "Overrides $CVSROOT as the root of the CVS tree"
complete -c cvs -x -s f -d "Do not use the ~/.cvsrc file"
complete -c cvs -x -s z -d "Compression level for net traffic" -x -a "1 2 3 4 5 6 7 8 9"
complete -c cvs -x -s x -d "Encrypt all net traffic"
complete -c cvs -x -s a -d "Authenticate all net traffic"
complete -c cvs -x -s s -d "Set CVS user variable" -x
complete -c cvs -x -s H -d 'Displays usage information for command'
complete -c cvs -x -s Q -d 'Cause CVS to be really quiet'
complete -c cvs -x -s q -d 'Cause CVS to be somewhat quiet'
complete -c cvs -x -s r -d 'Make checked-out files read-only'
complete -c cvs -x -s w -d 'Make checked-out files read-write (default)'
complete -c cvs -x -s n -d 'Do not execute anything that will change the disk'
complete -c cvs -x -s t -d 'Show trace of program execution -- try with -n'
complete -c cvs -x -s v -d 'CVS version and copyright'
complete -c cvs -x -s T -r -d 'Use "tmpdir" for temporary files'
complete -c cvs -x -s e -r -d 'Use "editor" for editing log information'
complete -c cvs -x -s d -r -d 'Overrides $CVSROOT as the root of the CVS tree'
complete -c cvs -x -s f -d 'Do not use the ~/.cvsrc file'
complete -c cvs -x -s z -d 'Compression level for net traffic' -x -a '1 2 3 4 5 6 7 8 9'
complete -c cvs -x -s x -d 'Encrypt all net traffic'
complete -c cvs -x -s a -d 'Authenticate all net traffic'
complete -c cvs -x -s s -d 'Set CVS user variable' -x

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

@@ -2,7 +2,7 @@
# The gcc completion list is incomplete. There are just so many of them...
#
complete -c gcc -s x -d "Language" -x -a "
complete -c gcc -s x -d 'Language' -x -a '
c
c-header
cpp-output
@@ -19,17 +19,17 @@ complete -c gcc -s x -d "Language" -x -a "
java
treelang
none
"
complete -c gcc -o pass-exit-codes -d "Pass program exit codes"
complete -c gcc -s c -d "Stop after assembler"
complete -c gcc -s S -d "Stop after compile"
complete -c gcc -s E -d "Stop after preprocesswor"
complete -c gcc -s o -r -d "Output file"
complete -c gcc -s v -d "Print commands to stderr"
complete -c gcc -o \#\#\# -d "Print quoted commands to stderr, do not run"
complete -c gcc -o pipe -d "Use pipes"
complete -c gcc -o ansi -d "Use ansi mode"
complete -c gcc -o std -d "Standard mode" -x -a '
'
complete -c gcc -o pass-exit-codes -d 'Pass program exit codes'
complete -c gcc -s c -d 'Stop after assembler'
complete -c gcc -s S -d 'Stop after compile'
complete -c gcc -s E -d 'Stop after preprocesswor'
complete -c gcc -s o -r -d 'Output file'
complete -c gcc -s v -d 'Print commands to stderr'
complete -c gcc -o \#\#\# -d 'Print quoted commands to stderr, do not run'
complete -c gcc -o pipe -d 'Use pipes'
complete -c gcc -o ansi -d 'Use ansi mode'
complete -c gcc -o std -d 'Standard mode' -x -a '
c89\t"ISO C90"
iso9899:1990\t"ISO C90"
iso9899:199409\t"ISO C90 as modified in amendment 1"
@@ -43,54 +43,54 @@ complete -c gcc -o std -d "Standard mode" -x -a '
c++98\t"ISO C++98"
gnu++98\t"ISO C++98 plus GNU extentions"
'
complete -c gcc -o aux-info -r -d "Write prototypes to file"
complete -c gcc -o fno-asm -d "Do not recognize asm, inline or typeof keywords"
complete -c gcc -o fno-builtin -d "Do not use builtin functions"
complete -c gcc -o fhosted -d "Assert hosted environment"
complete -c gcc -o ffreestanding -d "Assert freestanding environment"
complete -c gcc -o fms-extensions -d "Use Microsoft extensions"
complete -c gcc -o trigraphs -d "Use ANSI trigraphs"
complete -c gcc -o no-integrated-cpp -d "Do not use integrated preprocessor"
complete -c gcc -o funsigned-char -d "char is unsigned"
complete -c gcc -o fsigned-char -d "char is signed"
complete -c gcc -o funsigned-bitfields -d "bifield is unsigned"
complete -c gcc -o fsigned-bitfields -d "bifield is signed"
complete -c gcc -o fno-unsigned-bitfields -d "All bifields are signed"
complete -c gcc -o fno-signed-bitfields -d "All bifield are signed"
complete -c gcc -o fwritable-strings -d "String constants are not const"
complete -c gcc -o fabi-version -d "C++ ABI version" -r -x -a "1 0"
complete -c gcc -o fno-access-control -d "Turn off access checking"
complete -c gcc -o fcheck-new -d "Check pointer returned by new"
complete -c gcc -o fconserve-space -d "Put globals in the common segment"
complete -c gcc -o fno-const-strings -d "String constants are not const"
complete -c gcc -o fdollars-in-identifiers -d "Accept $ in identifiers"
complete -c gcc -o fno-dollars-in-identifiers -d "Reject $ in identifiers"
complete -c gcc -o fno-elide-constructors -d "Do not omit unneeded temporarys"
complete -c gcc -o fno-enforce-eh-specs -d "Allow exception violations"
complete -c gcc -o ffor-scope -d "Do not extend for-loop scope"
complete -c gcc -o fno-for-scope -d "Extend for-loop scope"
complete -c gcc -o fno-gnu-keywords -d "Do not recognize typeof as keyword"
complete -c gcc -o fno-implicit-templates -d "Do not emit code for implicit templates"
complete -c gcc -o fno-implicit-inline-templates -d "Do not emit code for implicit inline templates"
complete -c gcc -o fno-implement-inlines -d "Do not emit out-of-line code for inline functions"
complete -c gcc -o fms-extensions -d "Disable warnings about MFC"
complete -c gcc -o fno-nonansi-builtins -d "Disable some built-in functions"
complete -c gcc -o fno-operator-names -d "Disable operator keywords"
complete -c gcc -o fno-optional-diags -d "Disable optional diagnostics"
complete -c gcc -o fpermissive -d "Downgrade some errors to warnings"
complete -c gcc -o frepo -d "Enable automatic template instantiation at link time"
complete -c gcc -o fno-rtti -d "Disable generation of C++ runtime type information"
#complete -c gcc -o fstats -d "Emit front-end usage statistics"
complete -c gcc -o aux-info -r -d 'Write prototypes to file'
complete -c gcc -o fno-asm -d 'Do not recognize asm, inline or typeof keywords'
complete -c gcc -o fno-builtin -d 'Do not use builtin functions'
complete -c gcc -o fhosted -d 'Assert hosted environment'
complete -c gcc -o ffreestanding -d 'Assert freestanding environment'
complete -c gcc -o fms-extensions -d 'Use Microsoft extensions'
complete -c gcc -o trigraphs -d 'Use ANSI trigraphs'
complete -c gcc -o no-integrated-cpp -d 'Do not use integrated preprocessor'
complete -c gcc -o funsigned-char -d 'char is unsigned'
complete -c gcc -o fsigned-char -d 'char is signed'
complete -c gcc -o funsigned-bitfields -d 'bifield is unsigned'
complete -c gcc -o fsigned-bitfields -d 'bifield is signed'
complete -c gcc -o fno-unsigned-bitfields -d 'All bifields are signed'
complete -c gcc -o fno-signed-bitfields -d 'All bifield are signed'
complete -c gcc -o fwritable-strings -d 'String constants are not const'
complete -c gcc -o fabi-version -d 'C++ ABI version' -r -x -a '1 0'
complete -c gcc -o fno-access-control -d 'Turn off access checking'
complete -c gcc -o fcheck-new -d 'Check pointer returned by new'
complete -c gcc -o fconserve-space -d 'Put globals in the common segment'
complete -c gcc -o fno-const-strings -d 'String constants are not const'
complete -c gcc -o fdollars-in-identifiers -d 'Accept $ in identifiers'
complete -c gcc -o fno-dollars-in-identifiers -d 'Reject $ in identifiers'
complete -c gcc -o fno-elide-constructors -d 'Do not omit unneeded temporarys'
complete -c gcc -o fno-enforce-eh-specs -d 'Allow exception violations'
complete -c gcc -o ffor-scope -d 'Do not extend for-loop scope'
complete -c gcc -o fno-for-scope -d 'Extend for-loop scope'
complete -c gcc -o fno-gnu-keywords -d 'Do not recognize typeof as keyword'
complete -c gcc -o fno-implicit-templates -d 'Do not emit code for implicit templates'
complete -c gcc -o fno-implicit-inline-templates -d 'Do not emit code for implicit inline templates'
complete -c gcc -o fno-implement-inlines -d 'Do not emit out-of-line code for inline functions'
complete -c gcc -o fms-extensions -d 'Disable warnings about MFC'
complete -c gcc -o fno-nonansi-builtins -d 'Disable some built-in functions'
complete -c gcc -o fno-operator-names -d 'Disable operator keywords'
complete -c gcc -o fno-optional-diags -d 'Disable optional diagnostics'
complete -c gcc -o fpermissive -d 'Downgrade some errors to warnings'
complete -c gcc -o frepo -d 'Enable automatic template instantiation at link time'
complete -c gcc -o fno-rtti -d 'Disable generation of C++ runtime type information'
#complete -c gcc -o fstats -d 'Emit front-end usage statistics'
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17;
complete -c gcc -o ftemplate-depth-1 -d Set\ maximum\ template\ depth\ to\ $i;
end;
complete -c gcc -o fno-threadsafe-statistics -d "Do not emit code for thread-safe initialization of local statics"
complete -c gcc -o fuse-cxa-atexit -d "Use __cxa_atexit for destructors"
complete -c gcc -o fvisibility-inlines-hidden -d "Hides inline methods from export table"
complete -c gcc -o fno-weak -d "Do not use weak symbol support"
complete -c gcc -o fno-threadsafe-statistics -d 'Do not emit code for thread-safe initialization of local statics'
complete -c gcc -o fuse-cxa-atexit -d 'Use __cxa_atexit for destructors'
complete -c gcc -o fvisibility-inlines-hidden -d 'Hides inline methods from export table'
complete -c gcc -o fno-weak -d 'Do not use weak symbol support'
# gcc completion listing is incomplete.
#complete -c gcc -o -d ""
#complete -c gcc -o -d ''

View File

@@ -22,8 +22,6 @@ complete -c help -x -a prompt -d "Help on how to set the prompt"
complete -c help -x -a title -d "Help on how to set the titlebar message"
complete -c help -x -a killring -d "Help on how to copy and paste"
complete -c help -x -a editor -d "Help on editor shortcuts"
complete -c help -x -a expand -d "Help on parameter expantion (Globbing)"
complete -c help -x -a globbing -d "Help on parameter expantion (Globbing)"
complete -c help -x -a variables -d "Help on environment variables"
complete -c help -x -a color -d "Help on setting syntax highlighting colors"
complete -c help -x -a prompt -d "Help on changing the prompt"
@@ -31,3 +29,11 @@ complete -c help -x -a title -d "Help on changing the titlebar messages"
complete -c help -x -a builtin-overview -d "A short summary of all builtin commands"
complete -c help -x -a changes -d "The changelog"
complete -c help -x -a globbing -d "Help on parameter expansion (Globbing)"
complete -c help -x -a expand -d "Help on parameter expansion (Globbing)"
complete -c help -x -a expand-variable -d "Help on variable exapantion \$VARNAME"
complete -c help -x -a expand-home -d "Help on home directory expansion ~USER"
complete -c help -x -a expand-brace -d "Help on brace expansion {a,b,c}"
complete -c help -x -a expand-wildcard -d "Help on wildcard expansion *.*"
complete -c help -x -a expand-command-substitution -d "Help on command substututions (SUBCOMMAND)"
complete -c help -x -a expand-process -d "Help on process expansion %JOB"

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)
@@ -24,12 +24,12 @@ else
complete -c kill -s l -d "List codes and names of available signals"
for i in (kill -l|tr \ \t \n|grep "^[A-Z][A-Z0-9]*$")
for i in (kill -l|tr \ \t \n|grep '^[A-Z][A-Z0-9]*$')
complete -c kill -o $i -d Send\ $i\ signal
complete -c kill -o s -x -a $i\tSend\ $i\ signal -d "Send specified signal"
end
end
complete -c kill -xa "(__fish_complete_pids)"
complete -c kill -xa '(__fish_complete_pids)'
complete -c kill -s l -d "List names of available signals"

View File

@@ -17,7 +17,7 @@ complete -c less -s I -l IGNORE-CASE -d "Search ignores all case"
complete -c less -s j -l jump-target -d "Target line" -r -a "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19"
complete -c less -s J -l status-column -d "Display status column"
complete -c less -s k -l lesskey-file -d "Specify key bindings file" -r
complete -c less -s L -l no-lessopen -d "Ignore $LESSOPEN"
complete -c less -s L -l no-lessopen -d 'Ignore $LESSOPEN'
complete -c less -s m -l long-prompt -d "Prompt with percentage"
complete -c less -s M -l LONG-PROMPT -d "Verbose prompt"
complete -c less -s n -l line-numbers -d "Display line number"

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

@@ -3,7 +3,7 @@
# A list of all known filesystem types, used by various completions,
# including mount and df
set -g __fish_filesystems "
set -g __fish_filesystems '
adfs
affs
autofs
@@ -39,29 +39,29 @@ set -g __fish_filesystems "
xenix
xfs
xiafs
"
'
# Completions for mount
complete -x -c mount -a "(cat /etc/fstab|sed -e 's/^\([^ \t]*\)[ \t]*\([^ \t]*\).*/\1\n\2/'|grep '^/')" -d "Mount point"
complete -c mount -s V -d "Display version and exit"
complete -c mount -s h -d "Display help and exit"
complete -c mount -s v -d "Verbose mode"
complete -c mount -s a -d "Mount filesystems in fstab"
complete -c mount -s F -d "Fork process for each mount"
complete -c mount -s f -d "Fake mounting"
complete -c mount -s l -d "Add label to output"
complete -c mount -s n -d "Do not write mtab"
complete -c mount -s s -d "Tolerate sloppy mount options"
complete -c mount -s r -d "Read only"
complete -c mount -s w -d "Read/Write mode"
complete -x -c mount -s L -d "Mount partition with specified label"
complete -x -c mount -s U -d "Mount partition with specified UID"
complete -c mount -s O -x -d "Exclude filesystems"
complete -c mount -l bind -f -d "Remount a subtree to a second position"
complete -c mount -l move -f -d "Move a subtree to a new position"
complete -c mount -x -s t -d "Filesystem" -a $__fish_filesystems
complete -x -c mount -a '(cat /etc/fstab|sed -e "s/^\([^ \t]*\)[ \t]*\([^ \t]*\).*/\1\n\2/"|grep "^/")' -d 'Mount point'
complete -c mount -s V -d 'Display version and exit'
complete -c mount -s h -d 'Display help and exit'
complete -c mount -s v -d 'Verbose mode'
complete -c mount -s a -d 'Mount filesystems in fstab'
complete -c mount -s F -d 'Fork process for each mount'
complete -c mount -s f -d 'Fake mounting'
complete -c mount -s l -d 'Add label to output'
complete -c mount -s n -d 'Do not write mtab'
complete -c mount -s s -d 'Tolerate sloppy mount options'
complete -c mount -s r -d 'Read only'
complete -c mount -s w -d 'Read/Write mode'
complete -x -c mount -s L -d 'Mount partition with specified label'
complete -x -c mount -s U -d 'Mount partition with specified UID'
complete -c mount -s O -x -d 'Exclude filesystems'
complete -c mount -l bind -f -d 'Remount a subtree to a second position'
complete -c mount -l move -f -d 'Move a subtree to a new position'
complete -c mount -x -s t -d 'Filesystem' -a $__fish_filesystems
complete -c mount -x -s o -d "Mount option" -a "(__fish_append ',' $__fish_mount_opts)"
complete -c mount -x -s o -d 'Mount option' -a '(__fish_append , $__fish_mount_opts)'
set -g __fish_mount_opts async\tUse\ asynchronous\ I/O atime\tUpdate\ time\ on\ each\ access auto\tMounted\ with\ -a defaults\tUse\ default\ options dev\tInterpret\ character/block\ special\ devices exec\tPermit\ executables _netdev\tFilesystem\ uses\network noatime\tDo\ not\ update\ time\ on\ each\ access noauto\tNot\ mounted\ by\ -a nodev\tDo\ not\ interpret\ character/block\ special\ devices noexec\tDo\ not\ permit\ executables nosuid\tIgnore\ suid\ bits nouser\tOnly\ root\ may\ mount remount\tRemount\ read-only\ filesystem ro\tMount\ read-only rw\tMount\ read-write suid\tAllow\ suid\ bits sync\tUse\ synchronous\ I/O dirsync\tUse\ synchronous\ directory\ operations user\tAny\ user\ may\ mount users\tAny\ user\ may\ mount\ and\ unmount

View File

@@ -1,20 +1,20 @@
complete -c perl -s 0 -d "Specify record separator"
complete -c perl -s a -d "Feed input to split"
complete -c perl -s c -d "Check syntax"
complete -c perl -s d -d "Debugger"
complete -c perl -s D -x -d "Debug option"
complete -c perl -s e -x -d "Execute command"
complete -c perl -s F -d "Set regexp used to split input"
complete -c perl -s i -d "Edit files in-place"
complete -c perl -s I -d "Include path"
complete -c perl -s l -d "Line ending processing"
complete -c perl -s n -d "Loop script"
complete -c perl -s p -d "Loop script, print $_"
complete -c perl -s P -d "Invoke CPP"
complete -c perl -s s -d "Define custom switches"
complete -c perl -s S -d "Search $PATH for script"
complete -c perl -s T -d "Taint checking"
complete -c perl -s U -d "Unsafe mode"
complete -c perl -s v -d "Display version"
complete -c perl -s x -d "Extract script"
complete -c perl -s 0 -d 'Specify record separator'
complete -c perl -s a -d 'Feed input to split'
complete -c perl -s c -d 'Check syntax'
complete -c perl -s d -d 'Debugger'
complete -c perl -s D -x -d 'Debug option'
complete -c perl -s e -x -d 'Execute command'
complete -c perl -s F -d 'Set regexp used to split input'
complete -c perl -s i -d 'Edit files in-place'
complete -c perl -s I -d 'Include path'
complete -c perl -s l -d 'Line ending processing'
complete -c perl -s n -d 'Loop script'
complete -c perl -s p -d 'Loop script, print $_'
complete -c perl -s P -d 'Invoke CPP'
complete -c perl -s s -d 'Define custom switches'
complete -c perl -s S -d 'Search $PATH for script'
complete -c perl -s T -d 'Taint checking'
complete -c perl -s U -d 'Unsafe mode'
complete -c perl -s v -d 'Display version'
complete -c perl -s x -d 'Extract script'

View File

@@ -122,7 +122,7 @@ complete $rpm_erase -l repackage -d 'Re-package the files before erasing'
complete $rpm_erase -l test -d 'Dont really uninstall anything, just go through the motions'
set -e rpm_erase
set -- rpm_mode -c rpm -n "__fish_contains_opt -s e -s i -s F -s V -s U -s q erase install freshen verify upgrade query; if test $status = 0; false; else; true; end"
set -- rpm_mode -c rpm -n '__fish_contains_opt -s e -s i -s F -s V -s U -s q erase install freshen verify upgrade query; if test $status = 0; false; else; true; end'
complete $rpm_mode -s i -l install -d 'Install new package'
complete $rpm_mode -s U -l upgrade -d 'Upgrade existing package'
complete $rpm_mode -s F -l freshen -d 'Upgrade package if already installed'

View File

@@ -1,25 +1,25 @@
#Completions for ruby
complete -c ruby -s 0 -d "Specify record separator"
complete -c ruby -s a -d "Feed input to split"
complete -c ruby -s c -d "Check syntax"
complete -c ruby -s K -d "Kanji code-set"
complete -c ruby -s d -l debug -d "Debugger"
complete -c ruby -s e -x -d "Execute command"
complete -c ruby -s h -l help -d "Display help"
complete -c ruby -s F -d "Set regexp used to split input"
complete -c ruby -s i -d "Edit files in-place"
complete -c ruby -s I -d "Include path"
complete -c ruby -s l -d "Line ending processing"
complete -c ruby -s n -d "Loop script"
complete -c ruby -s p -d "Loop script, print $_"
complete -c ruby -s r -r -d "Require file"
complete -c ruby -s s -d "Define custom switches"
complete -c ruby -s S -d "Search $PATH for script"
complete -c ruby -s T -d "Taint checking"
complete -c ruby -s v -l verbose -d "Verbose mode"
complete -c ruby -s w -d "Verbose mode without message"
complete -c ruby -l version -d "Display version"
complete -c ruby -s x -d "Extract script"
complete -c ruby -s X -x -a "(__fish_complete_directory (commandline -ct))" -d "Directory"
complete -c ruby -s y -l yydebug -d "Compiler debug mode"
complete -c ruby -s 0 -d 'Specify record separator'
complete -c ruby -s a -d 'Feed input to split'
complete -c ruby -s c -d 'Check syntax'
complete -c ruby -s K -d 'Kanji code-set'
complete -c ruby -s d -l debug -d 'Debugger'
complete -c ruby -s e -x -d 'Execute command'
complete -c ruby -s h -l help -d 'Display help'
complete -c ruby -s F -d 'Set regexp used to split input'
complete -c ruby -s i -d 'Edit files in-place'
complete -c ruby -s I -d 'Include path'
complete -c ruby -s l -d 'Line ending processing'
complete -c ruby -s n -d 'Loop script'
complete -c ruby -s p -d 'Loop script, print $_'
complete -c ruby -s r -r -d 'Require file'
complete -c ruby -s s -d 'Define custom switches'
complete -c ruby -s S -d 'Search $PATH for script'
complete -c ruby -s T -d 'Taint checking'
complete -c ruby -s v -l verbose -d 'Verbose mode'
complete -c ruby -s w -d 'Verbose mode without message'
complete -c ruby -l version -d 'Display version'
complete -c ruby -s x -d 'Extract script'
complete -c ruby -s X -x -a '(__fish_complete_directory (commandline -ct))' -d 'Directory'
complete -c ruby -s y -l yydebug -d 'Compiler debug mode'

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

@@ -3,35 +3,35 @@ function __fish_complete_screen -d "Print a list of running screen sessions"
end
complete -c screen -x
complete -c screen -s a -d "Include all capabilitys"
complete -c screen -s A -d "Adapt window size"
complete -c screen -s c -r -d "Specify init file"
complete -c screen -s d -d "Detach screen" -a "(__fish_complete_screen)"
complete -c screen -s D -d "Detach screen" -a "(__fish_complete_screen)"
complete -c screen -s r -d "Reattach session" -a "(__fish_complete_screen)"
complete -c screen -s R -d "Reattach/create session"
complete -c screen -o RR -d "Reattach/create any session"
complete -c screen -s e -x -d "Escape character"
complete -c screen -s f -d "Flow control on"
complete -c screen -o fn -d "Flow control off"
complete -c screen -o fa -d "Flow control automatic"
complete -c screen -s h -x -d "History length"
complete -c screen -s i -d "Interrupt display on C-c"
complete -c screen -s l -d "Login on"
complete -c screen -o ln -d "Login off"
complete -c screen -o ls -d "List sessions"
complete -c screen -o list -d "List sessions"
complete -c screen -s L -d "Log on"
complete -c screen -s m -d "Ignore $STY"
complete -c screen -s O -d "Optimal output"
complete -c screen -s p -d "Preselect window"
complete -c screen -s q -d "Quiet mode"
complete -c screen -s s -r -d "Set shell"
complete -c screen -s S -x -d "Session name"
complete -c screen -s t -x -d "Session title"
complete -c screen -s U -d "UTF-8 mode"
complete -c screen -s v -d "Display version"
complete -c screen -o wipe -d "Wipe dead sessions"
complete -c screen -s x -d "Multi attach"
complete -c screen -s X -r -d "Send command"
complete -c screen -s a -d 'Include all capabilitys'
complete -c screen -s A -d 'Adapt window size'
complete -c screen -s c -r -d 'Specify init file'
complete -c screen -s d -d 'Detach screen' -a '(__fish_complete_screen)'
complete -c screen -s D -d 'Detach screen' -a '(__fish_complete_screen)'
complete -c screen -s r -d 'Reattach session' -a '(__fish_complete_screen)'
complete -c screen -s R -d 'Reattach/create session'
complete -c screen -o RR -d 'Reattach/create any session'
complete -c screen -s e -x -d 'Escape character'
complete -c screen -s f -d 'Flow control on'
complete -c screen -o fn -d 'Flow control off'
complete -c screen -o fa -d 'Flow control automatic'
complete -c screen -s h -x -d 'History length'
complete -c screen -s i -d 'Interrupt display on C-c'
complete -c screen -s l -d 'Login on'
complete -c screen -o ln -d 'Login off'
complete -c screen -o ls -d 'List sessions'
complete -c screen -o list -d 'List sessions'
complete -c screen -s L -d 'Log on'
complete -c screen -s m -d 'Ignore $STY'
complete -c screen -s O -d 'Optimal output'
complete -c screen -s p -d 'Preselect window'
complete -c screen -s q -d 'Quiet mode'
complete -c screen -s s -r -d 'Set shell'
complete -c screen -s S -x -d 'Session name'
complete -c screen -s t -x -d 'Session title'
complete -c screen -s U -d 'UTF-8 mode'
complete -c screen -s v -d 'Display version'
complete -c screen -o wipe -d 'Wipe dead sessions'
complete -c screen -s x -d 'Multi attach'
complete -c screen -s X -r -d 'Send command'

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,20 +15,30 @@ set -g IFS \ \t\n
# want this even for text-only terminals.
#
for i in /bin /usr/bin /usr/X11R6/bin @PREFIX@/bin
if test -d $i
if not echo $PATH|grep $i >/dev/null
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
end
end
end
#
# Set some value for LANG if nothing was set before
#
if status --is-login
if not count $LANG >/dev/null
if not set -q LANG >/dev/null
set -gx LANG en_US.UTF-8
end
end
@@ -39,13 +49,9 @@ end
# situation as well?
#
if count $LANG >/dev/null
if test (expr match $LANG ".*UTF") -gt 0
if count $TERM >/dev/null
if test linux = $TERM
unicode_start ^/dev/null
end
end
if expr match "$LANG" ".*UTF" >/dev/null
if test linux = "$TERM"
unicode_start ^/dev/null
end
end
@@ -56,7 +62,7 @@ end
#
for i in DISPLAY
if test (count $$i) -gt 1
if set -q $i
set -- $i (printf ":%s" $$i|cut -c 2-)
end
end

View File

@@ -10,7 +10,7 @@ if not status --is-interactive
exit
end
set -g fish_complete_path /etc/fish.d/completions ~/.fish.d/completions
set -g fish_complete_path @SYSCONFDIR@/fish.d/completions ~/.fish.d/completions
# Knowing the location of the whatis database speeds up command
# description lookup.
@@ -42,10 +42,10 @@ function __fish_complete_suffix -d "Complete using files"
set -- desc $argv[3]
set -- base (echo $comp |sed -e 's/\.[a-zA-Z0-9]*$//')
eval "set -- files "$base"*"$suff
eval "set -- files $base*$suff"
if test $files[1]
printf "%s\t"$desc"\n" $files
printf "%s\t$desc\n" $files
end
#
@@ -74,7 +74,7 @@ function __fish_complete_directory -d "Complete using directories"
eval "set -- dirs "$comp"*/"
if test $dirs[1]
printf "%s\t"$desc"\n" $dirs
printf "%s\t$desc\n" $dirs
end
end

View File

@@ -6,10 +6,8 @@
function _contains_help -d "Helper function for contains"
set bullet \*
if count $LANG >/dev/null
if test (expr match $LANG ".*UTF") -gt 0
set bullet \u2022
end
if expr match "$LANG" ".*UTF" >/dev/null
set bullet \u2022
end
echo \tcontains - Test if a word is present in a list\n
@@ -117,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
@@ -134,18 +132,20 @@ function help -d "Show help for the fish shell"
return 1
end
set fish_help_item $argv[1]
if count $argv >/dev/null
set fish_help_item $argv[1]
end
set fish_help_page ""
if test $fish_help_item = .
if test "$fish_help_item" = .
set fish_help_page "builtins.html\#source"
end
if test $fish_help_item = difference
if test "$fish_help_item" = difference
set fish_help_page difference.html
end
if test $fish_help_item = globbing
if test "$fish_help_item" = globbing
set fish_help_page "index.html\#expand"
end
@@ -158,8 +158,9 @@ function help -d "Show help for the fish shell"
end
set idx_subj syntax completion editor job-control todo bugs history
set idx_subj $idx_subj killring help color prompt title expand variables
set idx_subj $idx_subj builtin-overview changes
set idx_subj $idx_subj killring help color prompt title variables
set idx_subj $idx_subj builtin-overview changes
set idx_subj $idx_subj expand expand-variable expand-home expand-brace expand-wildcard expand-command-substitution expand-process
if contains -- $fish_help_item $idx_subj
set fish_help_page "index.html\#"$fish_help_item
@@ -215,22 +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 count $LANG >/dev/null
if test (expr match $LANG ".*UTF") -gt 0
set ellipsis \u2026
end
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
@@ -239,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
#
@@ -267,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
@@ -377,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
@@ -561,13 +545,149 @@ 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 \*
if count $LANG >/dev/null
if test (expr match $LANG ".*UTF") -gt 0
if expr match "$LANG" ".*UTF" >/dev/null
set bullet \u2022
end
end
echo \ttype - Indicate how a name would be interpreted if used as a \n\tcommand name
@@ -612,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
@@ -656,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
@@ -861,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
@@ -870,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
@@ -1008,3 +1128,4 @@ function delete-or-exit --key-binding
exit
end
end

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,17 +10,14 @@ 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
#
function fish_on_exit -d "Commands to execute when fish exits"
function fish_on_exit -d "Commands to execute when fish exits" --on-process %self
echo Good bye
end
@@ -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
#
@@ -39,9 +36,11 @@ end
# other than fish, which may use a different file. The new value should
# be exported, since the fish inputrc file plays nice with other files
# by including them when found.
# Give priority to the default file installed with fish in
# @SYSCONFDIR@/fish_inputrc.
#
for i in ~/.fish_inputrc ~/etc/fish_inputrc /etc/fish_inputrc ~/.inputrc /etc/inputrc
for i in ~/.fish_inputrc @SYSCONFDIR@/fish_inputrc ~/etc/fish_inputrc /etc/fish_inputrc ~/.inputrc /etc/inputrc
if test -f $i
set -xg INPUTRC $i
break
@@ -58,7 +57,7 @@ function set_default_color -d "Set an universal variable, unless it has already
set -U -- $argv
return
end
if contains -- $$argv[1] (set_color --print-colors)
if contains -- $$argv[1] (set_color -c)
return
end
set -U -- $argv

View File

@@ -49,6 +49,7 @@ implementation in fish is as of yet incomplete.
#include "parser.h"
#include "env.h"
#include "expand.h"
#include "event.h"
static void input_read_inputrc( wchar_t *fn );
@@ -1266,6 +1267,10 @@ static void add_vi_bindings()
*/
static int interrupt_handler()
{
/*
Fire any pending events
*/
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;

8
main.c
View File

@@ -111,7 +111,7 @@ int main( int argc, char **argv )
while( 1 )
{
#ifdef __GLIBC__
#ifdef HAVE_GETOPT_LONG
static struct option
long_options[] =
{
@@ -284,11 +284,7 @@ int main( int argc, char **argv )
}
}
if( function_exists(L"fish_on_exit"))
{
eval( L"fish_on_exit", 0, TOP );
}
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
reader_pop_current_filename();

View File

@@ -1018,7 +1018,7 @@ int main (int argc, char *argv[])
*/
while( 1 )
{
#ifdef __GLIBC__
#ifdef HAVE_GETOPT_LONG
static struct option
long_options[] =
{

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

604
parser.c

File diff suppressed because it is too large Load Diff

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
*/
@@ -125,18 +149,32 @@ enum while_status
*/
enum parser_error
{
/**
No error
*/
NO_ERR=0,
/**
An error in the syntax
*/
SYNTAX_ERROR,
/**
Error occured while evaluating commands
*/
EVAL_ERROR,
OOM,
STACK_ERROR,
SUBSHELL_ERROR
/**
Error while evaluating subshell
*/
SUBSHELL_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;
@@ -178,10 +216,11 @@ int eval_args( const wchar_t *line,
Sets the current error
\param ec The new error code
\param str The new error message
\param p The character offset at which the error occured
\param str The printf-style error message filter
*/
void error( int ec, const wchar_t *str, int p );
void error( int ec, int p, const wchar_t *str, ... );
/**
Tests if the specified commands parameters should be interpreted as another command, which will be true if the command is either 'command', 'exec', 'if', 'while' or 'builtin'.
@@ -274,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();

36
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 )
@@ -482,26 +483,23 @@ static void format_job_info( const job_t *j, const wchar_t *status )
fwprintf (stdout, L"\n" );
}
static void fire_process_event( const wchar_t *msg, int type, pid_t pid, int status )
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status )
{
static event_t ev;
event_t e;
e.function_name=0;
event.type=type;
event.param1.pid = pid;
ev.type=type;
ev.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 );
}
@@ -538,7 +536,7 @@ int job_reap( int interactive )
s = p->status;
fire_process_event( L"PROCESS_EXIT", EVENT_EXIT, p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) );
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, p->pid, ( WIFSIGNALED(s)?-1:WEXITSTATUS( s )) );
if( WIFSIGNALED(s) )
{
@@ -596,8 +594,8 @@ int job_reap( int interactive )
found=1;
}
}
fire_process_event( L"JOB_EXIT", EVENT_EXIT, -j->pgid, 0 );
fire_process_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 );
proc_fire_event( L"JOB_EXIT", EVENT_EXIT, -j->pgid, 0 );
proc_fire_event( L"JOB_EXIT", EVENT_JOB_ID, j->job_id, 0 );
job_free(j);
}

66
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 );
@@ -254,6 +295,11 @@ void proc_update_jiffies();
*/
void proc_sanity_check();
/**
Send of an process/job exit event notification. This function is a conveniance wrapper around event_fire().
*/
void proc_fire_event( const wchar_t *msg, int type, pid_t pid, int status );
/*
Initializations
*/

243
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();
@@ -1093,7 +1212,7 @@ static wchar_t get_quote( wchar_t *cmd, int l )
\param pos An index in the string which is inside the parameter
\param quote If not 0, store the type of quote this parameter has, can be either ', " or \\0, meaning the string is not quoted.
\param offset If not 0, get_param will store a pointer to the beginning of the parameter.
\param string If not o, get_parm will store a copy of the parameter string as returned by the tokenizer.
\param string If not 0, get_parm will store a copy of the parameter string as returned by the tokenizer.
\param type If not 0, get_param will store the token type as returned by tok_last.
*/
static void get_param( wchar_t *cmd,
@@ -1123,6 +1242,7 @@ static void get_param( wchar_t *cmd,
*type = tok_last_type( &tok );
if( string != 0 )
wcscpy( *string, tok_last( &tok ) );
prev_pos = tok_get_pos( &tok );
}
@@ -1381,13 +1501,12 @@ 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) );
wcsncpy( prefix, prefix_start, len );
wcslcpy( prefix, prefix_start, len );
prefix[len]=L'\0';
}
else
@@ -1400,7 +1519,9 @@ 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;
}
{
@@ -1710,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;
@@ -1722,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 )
@@ -1736,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 );
@@ -1754,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 );
@@ -1772,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) ) );
}
@@ -1874,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
@@ -1883,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) )
@@ -1924,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 ) )
{
@@ -1936,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 ))
@@ -1946,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 ) )
{
@@ -2347,21 +2498,13 @@ static int read_i()
that we can handle a call to reader_set_buffer
during evaluation.
*/
tmp = wcsdup( reader_readline() );
data->buff_pos=data->buff_len=0;
data->buff[data->buff_len]=L'\0';
if( function_exists(L"fish_on_exec"))
{
eval( L"fish_on_exec", 0, TOP );
}
reader_run_command( tmp );
free( tmp );
if( function_exists(L"fish_on_return"))
{
eval( L"fish_on_return", 0, TOP );
}
if( data->end_loop)
{
@@ -2405,7 +2548,6 @@ static int can_read( int fd )
static int wchar_private( wchar_t c )
{
return ( (c >= 0xe000) && (c <= 0xf8ff ) );
}
wchar_t *reader_readline()
@@ -2506,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*/
@@ -2593,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';
@@ -2761,8 +2904,8 @@ wchar_t *reader_readline()
break;
}
/* Move left*/
case R_BACKWARD_CHAR:
if( data->buff_pos > 0 )
@@ -2916,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

@@ -114,7 +114,7 @@ int main( int argc, char **argv )
while( 1 )
{
#ifdef __GLIBC__
#ifdef HAVE_GETOPT_LONG
static struct option
long_options[] =
{

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

@@ -32,7 +32,7 @@ int main( int argc, char **argv )
while( 1 )
{
#ifdef __GLIBC__
#ifdef HAVE_GETOPT_LONG
static struct option
long_options[] =
{

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

@@ -11,6 +11,8 @@
|
<a class="qindex" href="index.html">Main documentation page</a>
|
<a class="qindex" href="design.html">Design document</a>
|
<a class="qindex" href="about.html">About fish</a>
|
<a class="qindex" href="commands.html">External commands</a>

View File

@@ -7,12 +7,18 @@
internal commands use wide characters and hence this library is
useful.
If you want to use this version of getopt in your program, simply
copy wgetopt.c and wgetopt.h into your program, include wgetopt.h,
and use all the regular getopt functions, prefixing every
function, global variable and structure with a 'w', and use only
wide character strings. There are no other functional changes in
this version of getopt besides using wide character strings.
If you want to use this version of getopt in your program,
download the fish sourcecode, available at <a
href='http://roo.no-ip.org/fish/'>the fish homepage</a>. Extract
the sourcode, copy wgetopt.c and wgetopt.h into your program
directory, include wgetopt.h in your program, and use all the
regular getopt functions, prefixing every function, global
variable and structure with a 'w', and use only wide character
strings. There are no other functional changes in this version of
getopt besides using wide character strings.
For examples of how to use wgetopt, see the fish builtin
functions, many of which are defined in builtin.c.
*/

View File

@@ -7,12 +7,18 @@
internal commands use wide characters and hence this library is
useful.
If you want to use this version of getopt in your program, simply
copy wgetopt.c and wgetopt.h into your program, include wgetopt.h,
and use all the regular getopt functions, prefixing every
function, global variable and structure with a 'w', and use only
wide character strings. There are no other functional changes in
this version of getopt besides using wide character strings.
If you want to use this version of getopt in your program,
download the fish sourcecode, available at <a
href='http://roo.no-ip.org/fish/'>the fish homepage</a>. Extract
the sourcode, copy wgetopt.c and wgetopt.h into your program
directory, include wgetopt.h in your program, and use all the
regular getopt functions, prefixing every function, global
variable and structure with a 'w', and use only wide character
strings. There are no other functional changes in this version of
getopt besides using wide character strings.
For examples of how to use wgetopt, see the fish builtin
functions, many of which are defined in builtin.c.
*/

View File

@@ -1,6 +1,8 @@
/** \file wildcard.c
My own globbing implementation. Needed to implement this to
support tab-expansion of globbed parameters.
Fish needs it's own globbing implementation to support
tab-expansion of globbed parameters. Also provides recursive
wildcards using **.
*/
@@ -25,6 +27,19 @@
#include "reader.h"
#include "expand.h"
/**
This flag is set in the flags parameter of wildcard_expand if the
call is part of a recursiv wildcard search. It is used to make sure
that the contents of subdirectories are only searched once.
*/
#define WILDCARD_RECURSIVE 64
/**
The maximum length of a filename token. This is a fallback value,
an attempt to find the true value using patchconf is always made.
*/
#define MAX_FILE_LENGTH 1024
int wildcard_has( const wchar_t *str, int internal )
{
wchar_t prev=0;
@@ -55,7 +70,7 @@ int wildcard_has( const wchar_t *str, int internal )
\param str String to be matched.
\param wc The wildcard.
\param is_first Whether files beginning with dots should not be matched against wildcards.
\param is_first Whether files beginning with dots should not be matched against wildcards.
\param wc_unescaped Whether the unescaped special character ANY_CHAR abd ANY_STRING should be used instead of '?' and '*' for wildcard matching
*/
@@ -72,7 +87,9 @@ static int wildcard_match2( const wchar_t *str,
{
/* Ignore hidden file */
if( is_first && *str == L'.' )
{
return 0;
}
/* Try all submatches */
do
@@ -83,8 +100,16 @@ static int wildcard_match2( const wchar_t *str,
while( *(str++) != 0 );
return 0;
}
if( *wc == ANY_CHAR )
{
if( is_first && *str == L'.' )
{
return 0;
}
return wildcard_match2( str+1, wc+1, 0 );
}
if( *wc == *str )
return wildcard_match2( str+1, wc+1, 0 );
@@ -205,15 +230,13 @@ static wchar_t *make_path( const wchar_t *base_dir, const wchar_t *name )
int base_len = wcslen( base_dir );
if( !(long_name= malloc( sizeof(wchar_t)*(base_len+wcslen(name)+1) )))
{
return 0;
die_mem();
}
wcscpy( long_name, base_dir );
wcscpy(&long_name[base_len], name );
return long_name;
}
void get_desc( wchar_t *fn, string_buffer_t *sb, int is_cmd )
{
const wchar_t *desc;
@@ -282,6 +305,11 @@ void get_desc( wchar_t *fn, string_buffer_t *sb, int is_cmd )
}
}
/*
Test if the file specified by the given filename matches the
expansion flags specified. flags can be a combination of
EXECUTABLES_ONLY and DIRECTORIES_ONLY.
*/
static int test_flags( wchar_t *filename,
int flags )
{
@@ -289,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;
@@ -306,11 +337,37 @@ int wildcard_expand( const wchar_t *wc,
int flags,
array_list_t *out )
{
// debug( 3, L"WILDCARD_EXPAND %ls in %ls", wc, base_dir );
/* Points to the end of the current wildcard segment */
wchar_t *wc_end;
/* Variables for traversing a directory */
struct dirent *next;
DIR *dir;
/* The result returned */
int res = 0;
/* Length of the directory to search in */
int base_len;
/* Variables for testing for presense of recursive wildcards */
wchar_t *wc_recursive;
int is_recursive;
/* Sligtly mangled version of base_dir */
const wchar_t *dir_string;
/* Description for completions */
string_buffer_t sb_desc;
// debug( 3, L"WILDCARD_EXPAND %ls in %ls", wc, base_dir );
if( flags & ACCEPT_INCOMPLETE )
{
/* Avoid excessive number of returned matches for wc ending with a * */
/*
Avoid excessive number of returned matches for wc ending with a *
*/
int len = wcslen(wc);
if( len && (wc[len-1]==ANY_STRING) )
{
@@ -321,50 +378,58 @@ int wildcard_expand( const wchar_t *wc,
return res;
}
}
struct dirent *next;
wchar_t *wc_end = wcschr(wc,L'/');
DIR *dir;
int res = 0;
int base_len = wcslen( base_dir );
wchar_t *wc_recursive = wcschr( wc, ANY_STRING_RECURSIVE );
int is_recursive = is_recursive = ( wc_recursive && (!wc_end || wc_recursive < wc_end));
/*
Initialize various variables
*/
const wchar_t *dir_string = base_dir[0]==L'\0'?L".":base_dir;
string_buffer_t sb_desc;
sb_init( &sb_desc );
// if( accept_incomplete )
// wprintf( L"Glob %ls in '%ls'\n", wc, base_dir );//[0]==L'\0'?L".":base_dir );
/*
Test for recursive match string in current segment
*/
dir_string = base_dir[0]==L'\0'?L".":base_dir;
if( !(dir = wopendir( dir_string )))
{
// if( errno != EACCES && errno != ENOENT )
// wperror( L"opendir" );
return 0;
}
/*
Is this segment of the wildcard the last?
*/
if( wc_end == 0 )
wc_end = wcschr(wc,L'/');
base_len = wcslen( base_dir );
/*
Test for recursive match string in current segment
*/
wc_recursive = wcschr( wc, ANY_STRING_RECURSIVE );
is_recursive = ( wc_recursive && (!wc_end || wc_recursive < wc_end));
/*
This makes sure that the base
directory of the recursive search is
also searched for matching files.
*/
if( is_recursive && (wc_end==(wc+1)) && !(flags & WILDCARD_RECURSIVE ) )
{
wildcard_expand( wc_end + 1,
base_dir,
flags,
out );
}
if( flags & ACCEPT_INCOMPLETE )
sb_init( &sb_desc );
/*
Is this segment of the wildcard the last?
*/
if( !wc_end && !is_recursive )
{
/*
Wildcard segment is the last segment
Wildcard segment is the last segment,
Insert all matching files/directories
*/
if( wc[0]=='\0' )
{
/*
The last wildcard segment is empty. Insert everything if completing, the directory itself otherwise.
The last wildcard segment is empty. Insert everything if
completing, the directory itself otherwise.
*/
if( flags & ACCEPT_INCOMPLETE )
{
@@ -375,20 +440,10 @@ int wildcard_expand( const wchar_t *wc,
wchar_t *name = str2wcs(next->d_name);
if( name == 0 )
{
/* closedir( dir );*/
/* return -1; */
continue;
}
wchar_t *long_name = make_path( base_dir, name );
if( long_name == 0 )
{
wperror( L"malloc" );
closedir( dir );
free(name);
return 0;
}
if( test_flags( long_name, flags ) )
{
get_desc( long_name,
@@ -407,7 +462,7 @@ int wildcard_expand( const wchar_t *wc,
else
{
res = 1;
al_push( out, wcsdup( base_dir ) );
al_push_check( out, wcsdup( base_dir ) );
}
}
else
@@ -423,22 +478,13 @@ int wildcard_expand( const wchar_t *wc,
continue;
}
/* wprintf( L"Filen heter %s\n\n\n", next->d_name );*/
/* wprintf( L"Match %ls (%s) against %ls\n\n\n", name, "tjo", wc );*/
if( flags & ACCEPT_INCOMPLETE )
{
/* wprintf( L"match %ls to %ls\n", name, wc );*/
wchar_t *long_name = make_path( base_dir, name );
if( long_name == 0 )
{
wperror( L"malloc" );
closedir( dir );
free(name);
return 0;
}
/*
Test for matches before stating file, so as to minimize the number of stat calls
Test for matches before stating file, so as to minimize the number of calls to the much slower stat function
*/
if( wildcard_complete( name,
wc,
@@ -446,8 +492,6 @@ int wildcard_expand( const wchar_t *wc,
0,
0 ) )
{
if( test_flags( long_name, flags ) )
{
get_desc( long_name,
@@ -470,15 +514,8 @@ int wildcard_expand( const wchar_t *wc,
if( wildcard_match2( name, wc, 1 ) )
{
wchar_t *long_name = make_path( base_dir, name );
if( long_name == 0 )
{
wperror( L"malloc" );
closedir( dir );
free(name);
return 0;
}
al_push( out, long_name );
al_push_check( out, long_name );
res = 1;
}
}
@@ -489,34 +526,52 @@ int wildcard_expand( const wchar_t *wc,
else
{
/*
Wilcard segment is not the last segment.
Recursively call wildcard_expand for all matching subdirectories.
Wilcard segment is not the last segment. Recursively call
wildcard_expand for all matching subdirectories.
*/
/*
wc_str is the part of the wildcarded string from the
beginning to the first slash
*/
wchar_t *wc_str;
/*
new_dir is a scratch area containing the full path to a
file/directory we are iterating over
*/
wchar_t *new_dir;
static size_t ln=1024;
/*
The maximum length of a file element
*/
static size_t ln=MAX_FILE_LENGTH;
char * narrow_dir_string = wcs2str( dir_string );
if( narrow_dir_string )
{
ln = pathconf( narrow_dir_string, _PC_NAME_MAX ); /* Find out how long the filename can be in a worst case scenario */
/*
Find out how long the filename can be in a worst case
scenario
*/
ln = pathconf( narrow_dir_string, _PC_NAME_MAX );
/*
If not specified, use som large number as fallback
*/
if( ln < 0 )
ln = 1024;
ln = MAX_FILE_LENGTH;
free( narrow_dir_string );
}
new_dir= malloc( sizeof(wchar_t)*(base_len+ln+2) );
wc_str = wcsndup(wc, wc_end-wc);
wc_str = wc_end?wcsndup(wc, wc_end-wc):wcsdup(wc);
if( (!new_dir) || (!wc_str) )
{
if( new_dir )
free( new_dir );
if( wc_str )
free( wc_str );
wperror( L"malloc" );
closedir( dir );
return 0;
die_mem();
}
wcscpy( new_dir, base_dir );
while( (next=readdir(dir))!=0 )
@@ -526,56 +581,103 @@ int wildcard_expand( const wchar_t *wc,
{
continue;
}
/*
Test if the file/directory name matches the whole
wildcard element, i.e. regular matching.
*/
int whole_match = wildcard_match2( name, wc_str, 1 );
int partial_match = 0;
if( wildcard_match2( name, wc_str, 1 ) )
/*
If we are doing recursive matching, also check if this
directory matches the part up to the recusrive
wildcard, if so, then we can search all subdirectories
for matches.
*/
if( is_recursive )
{
wchar_t *end = wcschr( wc, ANY_STRING_RECURSIVE );
wchar_t *wc_sub = wcsndup( wc, end-wc+1);
partial_match = wildcard_match2( name, wc_sub, 1 );
free( wc_sub );
}
if( whole_match || partial_match )
{
int new_len;
struct stat buf;
wcscpy(&new_dir[base_len], name );
free(name);
char *dir_str = wcs2str( new_dir );
char *dir_str;
int stat_res;
if( !dir_str )
{
continue;
}
stat_res= stat( dir_str, &buf );
free( dir_str );
if( stat_res )
{
continue;
}
if( buf.st_mode & S_IFDIR )
wcscpy(&new_dir[base_len], name );
dir_str = wcs2str( new_dir );
if( dir_str )
{
new_len = wcslen( new_dir );
new_dir[new_len] = L'/';
new_dir[new_len+1] = L'\0';
switch( wildcard_expand( wc_end + 1, new_dir, flags, out ) )
stat_res = stat( dir_str, &buf );
free( dir_str );
if( !stat_res )
{
case 0:
break;
case 1:
res = 1;
break;
if( buf.st_mode & S_IFDIR )
{
new_len = wcslen( new_dir );
new_dir[new_len] = L'/';
new_dir[new_len+1] = L'\0';
/*
Regular matching
*/
if( whole_match )
{
res |= wildcard_expand( wc_end?wc_end + 1:L"",
new_dir,
flags,
out );
}
/*
Recursive matching
*/
if( partial_match )
{
res |= wildcard_expand( wcschr( wc, ANY_STRING_RECURSIVE ),
new_dir,
flags | WILDCARD_RECURSIVE,
out );
}
}
}
}
}
}
else
{
free(name);
}
free(name);
}
free( wc_str );
free( new_dir );
}
closedir( dir );
sb_destroy( &sb_desc );
if( flags & ACCEPT_INCOMPLETE )
sb_destroy( &sb_desc );
return res;
}
void al_push_check( array_list_t *l, const wchar_t *new )
{
int i;
for( i = 0; i < al_get_count(l); i++ )
{
if( !wcscmp( al_get(l, i), new ) )
{
free( (void *)new );
return;
}
}
al_push( l, new );
}

View File

@@ -1,8 +1,7 @@
/** \file wildcard.h
My own globbing implementation. Needed to implement this instead
of using libs globbing to support tab-expantion of globbed
of using libs globbing to support tab-expansion of globbed
paramaters.
*/
@@ -93,4 +92,10 @@ int wildcard_complete( const wchar_t *str,
const wchar_t *(*desc_func)(const wchar_t *),
array_list_t *out );
/**
Push string if not already in list
*/
void al_push_check( array_list_t *l, const wchar_t *str );
#endif

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;