Compare commits

..

139 Commits

Author SHA1 Message Date
axel
0768cf7e53 Bump version number
darcs-hash:20060729173243-ac50b-641e89defc78e0660cac6601acfb22c73c1cd32e.gz
2006-07-30 03:32:43 +10:00
axel
bdd83d338c Minor edit of comments
darcs-hash:20060729173159-ac50b-f126469f9a6f221d94696d6292ca9a6c79a7a6e6.gz
2006-07-30 03:31:59 +10:00
axel
db369a9ad7 Minor documentation edits
darcs-hash:20060729173123-ac50b-9b895afc355cf5dc342fca3c276cfbf10c286bc2.gz
2006-07-30 03:31:23 +10:00
axel
aa895c6740 Fix minor bug causing spurious warnings on commandline. Thanks to Netocrat for the bugreport.
darcs-hash:20060728135203-ac50b-07471a032a389a26789ee871bf0dc25c6a91bd7a.gz
2006-07-28 23:52:03 +10:00
axel
8e06805f2d Fix for recursive autoload loop on ls
darcs-hash:20060728131756-ac50b-034430a6a44bec83419438fc1be0c0e603eaad2d.gz
2006-07-28 23:17:56 +10:00
axel
00360d8fbc Reorder switches to msgfmt in makefile to make Solaris msgfmt happy. Thansk to Netocrat for the report.
darcs-hash:20060728130715-ac50b-84c09814f3c2cb859d3efc8593161186dff6fcc3.gz
2006-07-28 23:07:15 +10:00
axel
3b365d9f8d Use unsigned long instead of uint in string hashing algorithm. Portability fix, suggested by Netocrat.
darcs-hash:20060728125421-ac50b-f3cfc12852739fdc1d3c43c46ed91a57e119964a.gz
2006-07-28 22:54:21 +10:00
axel
3835000e9d Include unistd.h and stropts.h in common.c to fix Solaris problems reported by Netocrat
darcs-hash:20060728125057-ac50b-455d5a9a1671ad3bfee61a46266b420aff1adb49.gz
2006-07-28 22:50:57 +10:00
axel
9bbe19bfb8 Minor fix to code for detecting help switches to builtins
darcs-hash:20060724124845-ac50b-546662123d4d30c314acb1fb74d3c9503332172b.gz
2006-07-24 22:48:45 +10:00
axel
787e99d901 Fix rare crash bug in highlighting code
darcs-hash:20060724124629-ac50b-114944bc776f9451feeb967f4af68919d3ac404c.gz
2006-07-24 22:46:29 +10:00
axel
713748c782 Some minor steps towards making vi-mode work
darcs-hash:20060723205203-ac50b-8125e733ed92689ba847ccbb9076d05910e701ac.gz
2006-07-24 06:52:03 +10:00
axel
c9eb74fa4b Add missing Substitutions of prefix and optbindirs variables in share/fish.in
darcs-hash:20060723170402-ac50b-551cff33ca0e831505b5891fada0a017c3ea1370.gz
2006-07-24 03:04:02 +10:00
axel
b2d940c25a Drop the init and shutdown function for the completion code
darcs-hash:20060722101651-ac50b-45f840a5b2f7461d976a8f5b859aa99bfa472274.gz
2006-07-22 20:16:51 +10:00
axel
2a7bc8c04b Plug very small memory leak
darcs-hash:20060722101549-ac50b-244f449244272fc1fea9b7d019d7c259f4746533.gz
2006-07-22 20:15:49 +10:00
axel
013d3dbb89 Make sure that the builtin source command is used when reading the init files, and not an overloaded function
darcs-hash:20060722095507-ac50b-4c7c51bec3f2d7224178cdacd2c9ec4ea3b073c3.gz
2006-07-22 19:55:07 +10:00
axel
0aff94dd4c Automatically sort manuals for builtins and commands when generating manual
darcs-hash:20060722095326-ac50b-6d1cdefa7fb3e6f71368be2a205e9ed9e84a1624.gz
2006-07-22 19:53:26 +10:00
axel
431850b4ec Add PACKAGE_TARNAME variable to makefile to make Debian packages happy
darcs-hash:20060721223909-ac50b-d970c0e6104e9be4eb082030193dbc4a667d10c3.gz
2006-07-22 08:39:09 +10:00
axel
e280d10033 Minor code edits. Use CHECK instead of a few error messages, add a few comments, etc.
darcs-hash:20060721010831-ac50b-e9ad82a3885969f9a43e6219523e2bd1867e26ed.gz
2006-07-21 11:08:31 +10:00
axel
8c4708b51e Make error message for ${foo}-type errors nicer
darcs-hash:20060720233319-ac50b-a5ffbe91b3c7dceba9f0f5e67a6e044fc5508f47.gz
2006-07-21 09:33:19 +10:00
axel
4ba9ac28bb Minor documentation tweaks and additions
darcs-hash:20060720133319-ac50b-ea71dc172f0c60de0d6f1effa2092ebb8d8ca2d9.gz
2006-07-20 23:33:19 +10:00
axel
4664d65af7 Add a few casts to avoid warnings in fallback gettext and friends
darcs-hash:20060720133125-ac50b-f357c1e8dc9c8dfbafa3baa51fcfb47525d337ba.gz
2006-07-20 23:31:25 +10:00
axel
1b7157a03f Update dependencies - This is needed to make fish build, since old dependencies include removed files. Thansk to Netocreat for the notice.
darcs-hash:20060720133045-ac50b-a5f84ded2003a5cd9c8fe5d32b9773d5498763b0.gz
2006-07-20 23:30:45 +10:00
axel
e1dd17a7dd Move over fish_interactive.fish to be created by the Makefile, not by Autoconf
darcs-hash:20060720132850-ac50b-2f1a4815a2a67541d3461768d00e185168727b92.gz
2006-07-20 23:28:50 +10:00
axel
5c8d9bd13c Minor duplicate code removal
darcs-hash:20060720130246-ac50b-b41daebb302e1cbadf2a4cf812d936edbda85926.gz
2006-07-20 23:02:46 +10:00
axel
1c9a173b3d Make sure autoconf tells the Makefile whether gettext is installed
darcs-hash:20060720130148-ac50b-9aef2d0e708a1253187a215d0407764510ba0ff0.gz
2006-07-20 23:01:48 +10:00
axel
a0c40fcf8d Print help message when the case builtin is misused
darcs-hash:20060719232226-ac50b-c61b4b6d498dbfbe83ee1bc4c37766e1a9662630.gz
2006-07-20 09:22:26 +10:00
axel
f36811b7be Improve error message for attempts to use Posix variable assignments
darcs-hash:20060719232020-ac50b-1564ffffc2e119e90d711605247637e7aac9da96.gz
2006-07-20 09:20:20 +10:00
axel
40ed01f6f2 Move a few pieces of implementation-specific kludges related to different gettext implementations out of env.c and into fallback.c
darcs-hash:20060719231149-ac50b-c930a77ae76249b27f800f1d61146482c8f005c9.gz
2006-07-20 09:11:49 +10:00
axel
b2e2743195 Remove translate.c. The gettext fallback functionality is moved to fallback.c, the wide wrapper is moved to wutil.c
darcs-hash:20060719225549-ac50b-0a55e805b04f4fe0afa99ea580901d62f39cdef5.gz
2006-07-20 08:55:49 +10:00
axel
1dc033f71c Fix temporarily broken fish_function_path during startup
darcs-hash:20060719224433-ac50b-d7b4480d694cb8f71ecee75e21c7530700d3c609.gz
2006-07-20 08:44:33 +10:00
axel
ba4166d17d Fix for the autoconf-changes in the porevious patch. The LOCALEDIR macro should be a regular string, not a wide string
darcs-hash:20060719165803-ac50b-1b76c45b77469c0a7dbf47b866ab127bd48780e5.gz
2006-07-20 02:58:03 +10:00
axel
46c6f7880b Set value of install path macros like DATADIR from the Makefile, not automatically by Autoconf using AC_DEFINE. That way we get correct expansion of ${prefix} and friends to their install-time value. This fixes a bug reported by James Vega.
darcs-hash:20060719144104-ac50b-05001b151a54bf893ff4c5a82c5f040529e27f57.gz
2006-07-20 00:41:04 +10:00
axel
bef7fff383 Do not test universal variable functionality since it relies on fish to be installed
darcs-hash:20060718173711-ac50b-1feae98c4c283bfa5bbc8dfedec3eb4641316a8d.gz
2006-07-19 03:37:11 +10:00
axel
0811613fe9 Make sure no error message is printed when failing to start fishd
darcs-hash:20060718173547-ac50b-cf1edeb25838b2df6120efa68855316939fb3f0f.gz
2006-07-19 03:35:47 +10:00
axel
a09abea737 Make sure to only close fishd socket if it is open on shutdown
darcs-hash:20060718172756-ac50b-3f36ee03489427823a36161b920b280b3494c1fa.gz
2006-07-19 03:27:56 +10:00
axel
fd4e5e6777 Fix crash bug in fish_tests when fishd is unavailable
darcs-hash:20060718172702-ac50b-72805efd3c9c7927a9fe37b6c80ef0dd276cde5f.gz
2006-07-19 03:27:02 +10:00
axel
57b3965518 Initialize etc/fish and share/fish from the Makefile, not automatically by Autoconf. That way we get correct expansion of ${prefix} and friends to their install-time value. This fixes a bug reported by James Vega.
darcs-hash:20060718164155-ac50b-8ec6c63d9c4e52db2c1884fcffeab78333367773.gz
2006-07-19 02:41:55 +10:00
axel
3e843f8219 Two minor build fixes, thanks to Hiroshi Sakurai
darcs-hash:20060717134217-ac50b-e7ec4f4ef1a4267486e746dacee79749048e3afe.gz
2006-07-17 23:42:17 +10:00
axel
2343ce5a0c Don't check for presence of Doxygen in the configure script, since it's no longer needed to build fish
darcs-hash:20060716225329-ac50b-7e48abb063dd717adfd00c571c5550978790d2bc.gz
2006-07-17 08:53:29 +10:00
axel
0122e35cb6 Bump version number to 1.21.9
darcs-hash:20060715133812-ac50b-8178fc0baca9c476cae37ee8cde7a0cbb0857231.gz
2006-07-15 23:38:12 +10:00
axel
c96382152c Fixes for the tokenizer to correctly return error values on invalid input
darcs-hash:20060715124005-ac50b-a3f06a51b53573a07db44f9ce6796f253b2596e9.gz
2006-07-15 22:40:05 +10:00
axel
af0bd61fb5 Add fix for build error in fish_tests
darcs-hash:20060715123903-ac50b-b9facd514360e534ab655177c8cd9cee0e9aa914.gz
2006-07-15 22:39:03 +10:00
axel
4a87c9895d Add -q/--query switch to the functions builtin. Works just like the same switch to set does. Useful for checking for the existance of functions in a script
darcs-hash:20060712174655-ac50b-14a98a15751bb5ddddf4ffb41521b616bef5e40c.gz
2006-07-13 03:46:55 +10:00
axel
036cc4e0fa The begin builtin should not alter the exit status
darcs-hash:20060712173141-ac50b-8d21f9f22ef55581521ccf923411e3458bd8109c.gz
2006-07-13 03:31:41 +10:00
axel
9e304fa734 Overhaul of the script autoloader. This should make sure that old scripts are unloaded and new scripts are loaded when the fish_function_path and fish_complete_path variables change
darcs-hash:20060712142242-ac50b-3966a0e96a32facc8bc1164d6d0837fc551e4733.gz
2006-07-13 00:22:42 +10:00
axel
6d9631d0d0 Add french translation (Thanks to Xavier Douville)
darcs-hash:20060711200205-ac50b-e9755dc6f6042fef73bd075582c9f8706360c8e2.gz
2006-07-12 06:02:05 +10:00
axel
bb04df2ac9 Minor code tweaks: A few extra input validations, spelling corrections, etc
darcs-hash:20060710223956-ac50b-22d3b2adf570872564abf7ab68bb223d0c4a5308.gz
2006-07-11 08:39:56 +10:00
axel
746a602515 Make sure that the / is only printed once in prompt_pwd function when cwd is root
darcs-hash:20060710223848-ac50b-ddb52c414fd8b08bd7c515c99cc4e05a3c479c7d.gz
2006-07-11 08:38:48 +10:00
axel
a41fd8f759 Update of the Swedish translation
darcs-hash:20060710161229-ac50b-f5dcf7369a24c83538960c443b58441b5359b75f.gz
2006-07-11 02:12:29 +10:00
axel
ba9fbc67da Fix bug in completions for the cd builtin that caused missed completions when using relative search paths and CDPATH. Also move the completions function to it's own file.
darcs-hash:20060709235518-ac50b-36c59205edbecd5c8967d8784fd43e46729c3cdc.gz
2006-07-10 09:55:18 +10:00
axel
ac40a3bcd0 Fix use of hardcoded path in completions for the help completions causing missing completions and warnings
darcs-hash:20060709233249-ac50b-9dfb4a708a8ecb3ae2e1882a0a5146aed6286d37.gz
2006-07-10 09:32:49 +10:00
axel
942dcd7d54 Fix bug where fish refuses to complete inside som command substitutions
darcs-hash:20060707153638-ac50b-7a50df000b5af04004fcaf0069e658de5e67b9ea.gz
2006-07-08 01:36:38 +10:00
axel
9830bf985a Fix psub deadlocks by once again considering a job as completed whenever the last process in the pipeline is dead
darcs-hash:20060707153539-ac50b-76842c851c3a4247c086e3242f70361b9d2d396b.gz
2006-07-08 01:35:39 +10:00
axel
7bb070d817 Fix two crash bugs in highlighter/parser for malformed lines (Thanks to Netocrat for the bug report)
darcs-hash:20060703104647-ac50b-9eb649322611a3e7fd95ef5f80acdc25ce09d11a.gz
2006-07-03 20:46:47 +10:00
axel
d56ab1d365 Switch from die_mem function to DIE_MEM macro in order to be able to give a line and file for the OOM message
darcs-hash:20060703103957-ac50b-8d7a860d931fd087f6d1759bc1e934dba1cfefe2.gz
2006-07-03 20:39:57 +10:00
axel
38175cdd30 Fix spelling error (Thanks to Netocrat)
darcs-hash:20060703103537-ac50b-dac14e53588671bdf9c288fdab5e71feb1b03347.gz
2006-07-03 20:35:37 +10:00
axel
436b1e10c6 Fix infinite loop when trying to init history without setting history mode name first
darcs-hash:20060622001228-ac50b-caa00ff803b6b1673d7672d8364f68afe89cee18.gz
2006-06-22 10:12:28 +10:00
axel
e59cb1da5d Add setenv shellscript function for csh compatibility
darcs-hash:20060622001123-ac50b-22e783ec5f77120a6960f28d735893d58e1a7db4.gz
2006-06-22 10:11:23 +10:00
axel
e42198b7c8 Implement fallback version of futimes instead of testing for it's existance in reader.c
darcs-hash:20060621141544-ac50b-4726e3f63644b64b8bbb5cd829383c1fc6f8d86e.gz
2006-06-22 00:15:44 +10:00
axel
2076944268 Use the intern function to share the strings used to describe various key bindings. This saves both performance, code size and memory use, but there is a pathological case where the user continually changes key bindings, resulting in more allocated memory than needed.
darcs-hash:20060621140344-ac50b-c7eb89a94a96538215f9a6737f8e4bacd6a801fb.gz
2006-06-22 00:03:44 +10:00
axel
407c96e943 Even more input validation
darcs-hash:20060621100746-ac50b-8aa5648c05a656829a895669be27c6fa4f1d8458.gz
2006-06-21 20:07:46 +10:00
axel
bf333f2a84 Remove common_init and common_destroy. Use halloc instead.
darcs-hash:20060621095838-ac50b-e4349a0ab02696cead5397efce3792c9d56c2d15.gz
2006-06-21 19:58:38 +10:00
axel
3ddd5e5981 Check exit status of close and fclose in a few extra places
darcs-hash:20060621095430-ac50b-52afcee91b856f706d6df6bcf2e3a6bc7d746e40.gz
2006-06-21 19:54:30 +10:00
axel
b016438c08 Update input validation. Always use the magic CHECK macro, which prints an error message including instructions on how to report this problem.
darcs-hash:20060621004836-ac50b-a47f296634eda0c469eb39034603015b1ad7ab5c.gz
2006-06-21 10:48:36 +10:00
axel
7268a4a4e0 Various code polish, including minor rearangement of builtin code to export fewer functions, a few additional input checks, and removal of the unneeded, exported error_max variable
darcs-hash:20060620212016-ac50b-f76c10eea23fab14a648ea83ed0c83a171b8fef9.gz
2006-06-21 07:20:16 +10:00
axel
51c6c5ea49 Make sure failed tilde expansion doesn't result in evaluating null strings in highlighting code
darcs-hash:20060620211621-ac50b-3d57cc28272f5222fb42a72f0f98f89af1ec60de.gz
2006-06-21 07:16:21 +10:00
axel
5688035680 Large number of sourcecode comment edits, and some minor code polish
darcs-hash:20060620005010-ac50b-eaeae9a6242a37c1e34831e1a0b2ee2b4e7a012e.gz
2006-06-20 10:50:10 +10:00
axel
43b6b703ff Make braces expand right-to-left, to make syntax more consistent
darcs-hash:20060617142652-ac50b-3c6ca24e37ae723fea6e74d1e4a9c66fd2f60c50.gz
2006-06-18 00:26:52 +10:00
axel
e007a5c203 The syntax for 'function --on-job-exit caller' was flat out wrong in the docs. Fixed.
darcs-hash:20060617141426-ac50b-835a389b29243023739315f21135f19c5f010c5a.gz
2006-06-18 00:14:26 +10:00
axel
f836bd41c0 Write commant at beginning of .fishd file mentioning that the file should not be edited
darcs-hash:20060617140406-ac50b-c3987895fbc747212a70618acf8a18b42601e8a8.gz
2006-06-18 00:04:06 +10:00
axel
c9e98c2eef Update function wrapper for cd builtin, make sure a local variable is used
darcs-hash:20060617131145-ac50b-1cef97b5e774713f659962b7e33f889be3081a3d.gz
2006-06-17 23:11:45 +10:00
axel
e94803152c Update rpm spec file, doxygen is no longer rewuired at build time
darcs-hash:20060617131036-ac50b-44d240f648cc020ee5307cf44c64ec72c0ca806b.gz
2006-06-17 23:10:36 +10:00
axel
07ff8a6c03 Documentation updates. Fixes a few formating bugs, adds various minor missing api documentation, fixes a few typos. Also fixes a few tiny code issues, mostly missing consts, etc
darcs-hash:20060617130708-ac50b-cc2ec5aa3e4bfb8e28d7b86441bfb4661f1dd7e7.gz
2006-06-17 23:07:08 +10:00
axel
9f10dd377e Fix bugs in the highlighting code related to detection and display of non-existing paths to the cd builtin
darcs-hash:20060617104128-ac50b-c9adecc8b95ab460f0c98c860e7640cdb91b4bae.gz
2006-06-17 20:41:28 +10:00
axel
6e0e7e0996 Fix a bug in the function wrapper around the 'cd' builtin that caused cd to sometimes return with a non-zero exit status even though the command did not fail
darcs-hash:20060616151848-ac50b-001698980eca6fadf9e470d829a532c305c84e38.gz
2006-06-17 01:18:48 +10:00
axel
907b2f8462 Make the validator show the help for a block command missing an 'end'
darcs-hash:20060616125616-ac50b-b895cc14ce9f26ec99ac90523b2a52d0dce66dd9.gz
2006-06-16 22:56:16 +10:00
axel
d2869d5140 Remove tiny and unlikely memory leak
darcs-hash:20060615160327-ac50b-01b0514c922104a7d36e3a9a0426bb3a671581b2.gz
2006-06-16 02:03:27 +10:00
axel
587e91d0c1 Include fallback functions in set_color command
darcs-hash:20060615152419-ac50b-e3ff8cffb004f7f381ca6d8e4bd5c039b451835d.gz
2006-06-16 01:24:19 +10:00
axel
aad3249b79 The license agreement int the docs explicitly state GPL v2, while main.c mentions GPL v2 or later. Removed the latter to avoid ambiguity.
darcs-hash:20060615152306-ac50b-6f24ed875ade3ea25d3536de92a8f16ab26c5e6c.gz
2006-06-16 01:23:06 +10:00
axel
081ab955af Slightly improve build system - dont link in ncurses into mimedb or set_color
darcs-hash:20060615135200-ac50b-e39889a0f566306f3ae1c7a39f2a7dd5c387fa2c.gz
2006-06-15 23:52:00 +10:00
axel
9a9d84c58a Slightly improve accuracy of calculations of prompt width
darcs-hash:20060615135023-ac50b-36a70fb2cab4f03b96db95ed3f7694b354e0b0ac.gz
2006-06-15 23:50:23 +10:00
axel
94d1322fc1 Update the set_color command: Add underline support, make the command a bit more rubust to missing ferminal features, and update documentation and completions
darcs-hash:20060615134915-ac50b-de1092e56490bbf1c58cc3422c239a2997645b6b.gz
2006-06-15 23:49:15 +10:00
axel
eed8b61a9e Add entry about changing shell to the FAQ
darcs-hash:20060615110539-ac50b-c610d35384039575a74711114262333e0b7eb99c.gz
2006-06-15 21:05:39 +10:00
axel
40558c2eb9 Fix highlighting of search matches, broken by earlier patch for underlining potential paths
darcs-hash:20060615105919-ac50b-fd54a58e3f7bdc93fd36e52891bafc7366c6e401.gz
2006-06-15 20:59:19 +10:00
axel
d677b468db Provide fallback implementation of lrand48_r
darcs-hash:20060615105315-ac50b-155e1836d0bdc8f398776a816898718066adcdce.gz
2006-06-15 20:53:15 +10:00
axel
4e38d3bc8c Minor comment edits, reindentation and other code formating changes
darcs-hash:20060615103706-ac50b-ad9f7060e40f5a786877e95f027688c90f43b6ec.gz
2006-06-15 20:37:06 +10:00
axel
36ae253a29 Minor comment edits, reindentation and other code formating changes
darcs-hash:20060615103646-ac50b-d7cde4cfca0c776127e9e161daefb74ee6d027ba.gz
2006-06-15 20:36:46 +10:00
axel
f673b06dd2 Give the 'random' builtin it's own seed state, to keep other users of random data from creating a generating a non-deterministic sequence of numbers even if the user manually seeds
darcs-hash:20060615103556-ac50b-7865016b4561c7c69afb1ba77f85adeda1da691e.gz
2006-06-15 20:35:56 +10:00
axel
e9e0643817 Check the return value of the unescape call at all places
darcs-hash:20060615011154-ac50b-b9c8f31c39fda44080ef885764ce572b24866cd5.gz
2006-06-15 11:11:54 +10:00
axel
358f412abb Highlight invalid directories red for the cd builtin
darcs-hash:20060615010038-ac50b-30ada1c67dcb393390f67cf709e433dafc8801b7.gz
2006-06-15 11:00:38 +10:00
axel
a983798295 Fix segfault caused by a backslash followed by a null inside single quotes
darcs-hash:20060615005931-ac50b-4c6be7129dfd2c3a5759a811b605ad32fceff758.gz
2006-06-15 10:59:31 +10:00
axel
52a0149e4f Set default highligting for valid paths
darcs-hash:20060614142241-ac50b-4f8bd79e788b3886ab8a1e5288da5b4cb9c2cdc5.gz
2006-06-15 00:22:41 +10:00
axel
8fdc46a105 Add support for hishlighting potentially valid paths - default behaviour is to underline them
darcs-hash:20060614132240-ac50b-448a4f8c43007262876d1ab6b52480e46b0e2981.gz
2006-06-14 23:22:40 +10:00
axel
63b02e308d Minor typo in configure script
darcs-hash:20060613234036-ac50b-6ccced250383c11f7babbb321de925312bad9761.gz
2006-06-14 09:40:36 +10:00
axel
7c97095bca Remove unused variable, and make a few variables static
darcs-hash:20060613172337-ac50b-6cae5390acdd278dc8709cfd870edfedfc0ba556.gz
2006-06-14 03:23:37 +10:00
axel
b62beaf47d Use variable arrays if compiler supports C99, this saves a small amount of memory
darcs-hash:20060613172251-ac50b-1e19294700c9b9b72e2254f676004e7d9dceea44.gz
2006-06-14 03:22:51 +10:00
axel
b2b1ec27d8 Add more emacs keymappings (Thansk stew for the patch)
darcs-hash:20060613163009-ac50b-16730da83d7e8ff45a51d10097a018411b11754a.gz
2006-06-14 02:30:09 +10:00
axel
6aa682755d Minor documentation edits for mimedb and fishd
darcs-hash:20060613154409-ac50b-5d1c80d67ee92a073078404ed662510573f7f9b5.gz
2006-06-14 01:44:09 +10:00
axel
2bc49b3291 Change name of fishd log file to be in line with name of socket file
darcs-hash:20060613154126-ac50b-1e33bbe55075035f2a4522aadb9ae500a3d302aa.gz
2006-06-14 01:41:26 +10:00
axel
cea3dfd0cb Decrease verbosity of fishd
darcs-hash:20060613153940-ac50b-37f934432f0fb1dbc0be4d03155563da56295bbe.gz
2006-06-14 01:39:40 +10:00
axel
d7d2c82a82 Fix bug in help builtin that caused fish to show index page instead of command-specific help
darcs-hash:20060613152224-ac50b-d1841f7069e4fee2c569fb0ee079efd3cfe7de8a.gz
2006-06-14 01:22:24 +10:00
axel
58aa1e75c1 Add completions for the which command
darcs-hash:20060613144807-ac50b-a0819777ec904700e644508a3b97e98f8c2acaee.gz
2006-06-14 00:48:07 +10:00
axel
0361423469 Major restructuring of the buildsystem, meaning that the documentation doesn't needlessly rebuild itself, and the size of the fish binary drops slightly
darcs-hash:20060613134328-ac50b-05ae75eb5cc081b680f38e8866fac00a679cc266.gz
2006-06-13 23:43:28 +10:00
axel
9aee2b7c9c Drop most 'const's from function prototypes
darcs-hash:20060612214742-ac50b-9b0801e8a7c07d6ab3f0acf569e1d6eb1eeb3f0e.gz
2006-06-13 07:47:42 +10:00
axel
2c95e087b2 Minor updates to swedish translations
darcs-hash:20060612205455-ac50b-24d5c1f05ff1fd4bec0d5ad4fffff7ff3e1d3abd.gz
2006-06-13 06:54:55 +10:00
axel
5d5ee87a59 Minor code edits
darcs-hash:20060612205438-ac50b-4d7092740d5d35af3da06d0e6e99551d1cdfa123.gz
2006-06-13 06:54:38 +10:00
axel
c60b62de73 Minor addition for completions to the patch command
darcs-hash:20060612203328-ac50b-e06d8dd7f9325cc06f59f6386eaedb181f1bd881.gz
2006-06-13 06:33:28 +10:00
axel
2e5821c17d Do not change status when the 'exit' builtin is called with no argument
darcs-hash:20060612165137-ac50b-0281941e35c5f8b619460f67d24a89caec475815.gz
2006-06-13 02:51:37 +10:00
axel
f46145a6b3 Do not change status when the 'return' builtin is called with no argument
darcs-hash:20060612164854-ac50b-5f428c819e8dafb44b591150d1965c5158854781.gz
2006-06-13 02:48:54 +10:00
axel
c61f6ceea6 Minor update to english 'translation'
darcs-hash:20060612155743-ac50b-d7b5cabd2dfd90932b762f26d4ebf0602b78f67d.gz
2006-06-13 01:57:43 +10:00
axel
d32751df13 Use halloc in a few more places, including the highlight code
darcs-hash:20060612141233-ac50b-1c44411dd31cdc31d6ccb226f567c308c4fc0f55.gz
2006-06-13 00:12:33 +10:00
axel
038dcca143 Include user documentation with standard tarballs - this means you no longer need Doxygen to build fish, and should make life easier for packagers
darcs-hash:20060612110743-ac50b-0dcfea7ce14856840ee66afb2c70bb23fcbfee6f.gz
2006-06-12 21:07:43 +10:00
axel
d79e8c7f62 Documentation updates, mostly corrections and cla<rifications to the docs for a few builtins
darcs-hash:20060608235811-ac50b-76b4fd54cb0911dd00f19f4a7c761f188d6ca068.gz
2006-06-09 09:58:11 +10:00
axel
af8cb6fe87 Minor code edits - add a few braces, a few minor safety checks, etc.
darcs-hash:20060608235719-ac50b-bec405da5ae101ff50bb3390bb83ef8b0948e4e9.gz
2006-06-09 09:57:19 +10:00
axel
5855f78010 Edits to source code comments
darcs-hash:20060608235557-ac50b-052e5c8f2cceb554064d7408573f277275903e7b.gz
2006-06-09 09:55:57 +10:00
axel
f7118e769f Add more function input validation checks
darcs-hash:20060608235212-ac50b-25fd55f96356af65d4da1eec100cc954b4a9f81e.gz
2006-06-09 09:52:12 +10:00
axel
93ae00e8e5 Do input validation in various functions in function.c and complete.c
darcs-hash:20060608000145-ac50b-1088c3f5e3c1ad2759c13400e5dda2d21858fedc.gz
2006-06-08 10:01:45 +10:00
axel
d7eb084b9d Make sure that empty completion descriptions aren't translated to the gettext version information
darcs-hash:20060607235601-ac50b-7b8d4d01f4e30d0722c6e269f9d46fb354c5f4b6.gz
2006-06-08 09:56:01 +10:00
axel
6e1548b821 Remove period from end of completion descriptions for telnet command
darcs-hash:20060607233312-ac50b-cb10498f174b72fb53d7e47ab93fcd8af72676c9.gz
2006-06-08 09:33:12 +10:00
axel
5381c6cf93 Fix off-by-one error when reporting line number of function call in stack traces
darcs-hash:20060607233206-ac50b-d8dcddb8a12a080d3e6ec50e50c420d70eeb8401.gz
2006-06-08 09:32:06 +10:00
axel
20e5d298a0 Updates, bugfixing and minor edits on the test suite
darcs-hash:20060605133133-ac50b-e2ee5868f9f3ede147c7059d90c0f520ed905a5f.gz
2006-06-05 23:31:33 +10:00
axel
39e9974e71 Fix some typos and bad wording in hte faq
darcs-hash:20060605100434-ac50b-539b8cebf367ad1c1e05b78fb412389c9f78fc4b.gz
2006-06-05 20:04:34 +10:00
axel
d2bd3e4919 Fix minor typos in code comments
darcs-hash:20060605004201-ac50b-66c51908cd1f23307042991b32ccbed487685500.gz
2006-06-05 10:42:01 +10:00
axel
04b142208d Make it possible to specify scope of a variable to be erased or tested. Also make sure set exits with a non-zero exit status when erasing fails.
darcs-hash:20060604201451-ac50b-4ea0212c513b33be40559dfe8d65c1446c53f682.gz
2006-06-05 06:14:51 +10:00
axel
cf35a8e3a5 Add documentation about support for negative indices
darcs-hash:20060604094203-ac50b-6cf671235549eb79d3464a15398b6511057dedde.gz
2006-06-04 19:42:03 +10:00
axel
e7e3e8ee74 Add support for negative indices in arrays. Negative indices count from the end of an array, so -4 is the fourth index from the end
darcs-hash:20060604093532-ac50b-6e22b2f2ccfe94375fe4c32e41ccec08ca501744.gz
2006-06-04 19:35:32 +10:00
axel
6fd69bdda8 Many minor edits and clarifications to the documentation, including comments about the exit status of a few commands
darcs-hash:20060603231517-ac50b-03d252516eef21d4dd3a2ba0f5bb68e82525213b.gz
2006-06-04 09:15:17 +10:00
axel
a85f4cc1c4 Swedish translation updates
darcs-hash:20060603223800-ac50b-8170191f3d233eab438709c35c0f1c69c622756e.gz
2006-06-04 08:38:00 +10:00
axel
07af5f4832 Add english 'translation', which does nothing except change the type of quotes used
darcs-hash:20060603223731-ac50b-9e222fa36b0b71b5690dc5674905000eea9b11c1.gz
2006-06-04 08:37:31 +10:00
axel
446272eee6 Minor code tweaks, including making sure builtins are not run if an io redirection issue occurs and removing a lot commented debug code
darcs-hash:20060603223533-ac50b-204ff1fb1a4912565044e7bc4b86102a7eeba192.gz
2006-06-04 08:35:33 +10:00
axel
48ca253097 Minor spelling fixes
darcs-hash:20060603223228-ac50b-b4f7b190baf3c41bf23c224f5d68e8888dd4eaed.gz
2006-06-04 08:32:28 +10:00
axel
da2a757dff Add missing help message for a few errors in the set builtin
darcs-hash:20060603223150-ac50b-b2c731e724410a8a192655940064be307214c149.gz
2006-06-04 08:31:50 +10:00
axel
6fada015b6 Drop validation of function code on new function definition - the code has already been validated
darcs-hash:20060602021757-ac50b-02bad63baf4826801ec0433468ec78d9b4a4c0f7.gz
2006-06-02 12:17:57 +10:00
axel
a1a2773cbf Make sure code validation error output for e.g. the complete builtin can be redirected, and that it has the prefix 'complete', not 'fish'
darcs-hash:20060602021517-ac50b-5e566aefbd1c9bcb3a5f11f9fc1125d8c1d9e936.gz
2006-06-02 12:15:17 +10:00
axel
67f216fa55 Highlight invalid use of variable expansion operator
darcs-hash:20060601230438-ac50b-165ec1515e0e02674a992a1f0309a567aa6828de.gz
2006-06-02 09:04:38 +10:00
axel
8986e05b94 Minor code cleanup
darcs-hash:20060601224217-ac50b-5e82554d224ffd9f4f6b79fe365d855795058100.gz
2006-06-02 08:42:17 +10:00
axel
7c016c56e3 Only hide /private directories in pwd function under OS X
darcs-hash:20060601222300-ac50b-b08a9425d33cf41d60aa0a42edffa32f521fc2a3.gz
2006-06-02 08:23:00 +10:00
axel
0602044723 Add completions for 'cp'.
darcs-hash:20060601221808-ac50b-f9f8d90f6e53fe6bc41d124b00ded09c4979af6d.gz
2006-06-02 08:18:08 +10:00
axel
4ffd2afccd Fix some minor 64-bit uncleanlieness - thanks to James Anthill
darcs-hash:20060601194231-ac50b-a6b9b94379ba1d5bb6c61f7fad4652c8f748b25f.gz
2006-06-02 05:42:31 +10:00
112 changed files with 17924 additions and 2702 deletions

View File

@@ -93,7 +93,7 @@ DISABLE_INDEX = YES
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
GENERATE_LATEX = YES
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex

View File

@@ -23,7 +23,7 @@
#
# Makefile for the fish shell. Can build fish and associated
# applications, install them, recalculate dependencies and also create
# binary distributions in tar.bz2 tar.gz and rpm formats.
# binary distributions in tar.bz2, tar.gz and rpm formats.
#
#
@@ -36,10 +36,6 @@
CC := @CC@
INSTALL:=@INSTALL@
CFLAGS:=@CFLAGS@
CPPFLAGS=@CPPFLAGS@
LDFLAGS:= @LIBS@ @LDFLAGS@
# Installation directories
prefix = @prefix@
exec_prefix = @exec_prefix@
@@ -47,8 +43,17 @@ datadir = @datadir@
bindir = @bindir@
mandir = @mandir@
sysconfdir = @sysconfdir@
fishinputfile = @fishinputfile@
docdir = @docdir@
localedir = @localedir@
prefix = @prefix@
optbindirs = @optbindirs@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
MACROS=-DLOCALEDIR=\"$(localedir)\" -DPREFIX=L\"$(prefix)\" -DDATADIR=L\"$(datadir)\" -DSYSCONFDIR=L\"$(sysconfdir)\"
CFLAGS=@CFLAGS@ $(MACROS)
CPPFLAGS=@CPPFLAGS@
LDFLAGS= @LIBS@ @LDFLAGS@
#etc files to install
ETC_DIR_INSTALL = etc/fish_interactive.fish
@@ -56,49 +61,39 @@ ETC_DIR_INSTALL = etc/fish_interactive.fish
# Set to 1 if we have gettext
HAVE_GETTEXT=@HAVE_GETTEXT@
CORE_OBJS := util.o common.o halloc.o halloc_util.o fallback.o
#Additional .c files used by common.o. These also have a corresponding
#.h file.
COMMON_FILES := util.c halloc.c halloc_util.c fallback.c
# All objects used by fish, that are compiled from an ordinary .c file
# using an ordinary .h file.
COMMON_OBJS := function.o builtin.o complete.o env.o exec.o \
# All objects that the system needs to build fish, except main.o
FISH_OBJS := function.o builtin.o complete.o env.o exec.o \
expand.o highlight.o history.o kill.o parser.o proc.o reader.o \
sanity.o tokenizer.o wildcard.o wgetopt.o wutil.o input.o \
output.o intern.o env_universal.o env_universal_common.o \
input_common.o event.o signal.o io.o translate.o parse_util.o \
$(CORE_OBJS)
input_common.o event.o signal.o io.o parse_util.o common.o \
# builtin_help.h exists, but builtin_help.c is autogenerated
COMMON_OBJS_WITH_HEADER := builtin_help.o
# main.c exists, but main.h does not, etc.
COMMON_OBJS_WITH_CODE := builtin_set.o builtin_commandline.o \
builtin_ulimit.o builtin_complete.o builtin_jobs.o
# All objects that the system needs to build fish
FISH_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \
$(COMMON_OBJS_WITH_HEADER) main.o
# Additional files used by builtin.o
BUILTIN_FILES := builtin_help.c builtin_set.c builtin_commandline.c \
builtin_ulimit.c builtin_complete.c builtin_jobs.c
# All objects that the system needs to build fish_pager
FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \
tokenizer.o input_common.o env_universal.o env_universal_common.o \
translate.o $(CORE_OBJS)
common.o
# All objects that the system needs to build fish_tests
FISH_TESTS_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \
$(COMMON_OBJS_WITH_HEADER) fish_tests.o
FISH_TESTS_OBJS := $(FISH_OBJS) fish_tests.o
# All objects that the system needs to build fishd
FISHD_OBJS := fishd.o env_universal_common.o wutil.o \
doc_src/fishd.o $(CORE_OBJS)
doc_src/fishd.o common.o
# All objects needed to build mimedb
MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o $(CORE_OBJS)
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o common.o
#
# Files containing documentation for builtins. Should be listed
# alphabetically, since this is the order in which they will be written
# in the help file.
# Files containing documentation for builtins.
#
BUILTIN_DOC_SRC := doc_src/source.txt doc_src/and.txt \
doc_src/begin.txt doc_src/bg.txt doc_src/bind.txt \
@@ -119,9 +114,7 @@ BUILTIN_DOC_SRC := doc_src/source.txt doc_src/and.txt \
BUILTIN_DOC_HDR := $(BUILTIN_DOC_SRC:.txt=.doxygen)
#
# Files containing documentation for external commands. Should be listed
# alphabetically, since this is the order in which they will be written
# in the help file.
# Files containing documentation for external commands.
#
CMD_DOC_SRC := doc_src/contains.txt doc_src/count.txt doc_src/dirh.txt \
doc_src/dirs.txt doc_src/fish_pager.txt doc_src/fishd.txt \
@@ -150,14 +143,14 @@ DOC_SRC_DIR_FILES := doc_src/Doxyfile.in doc_src/doc.hdr \
$(BUILTIN_DOC_SRC) $(CMD_DOC_SRC) doc_src/fish.1.in
# Files in ./
MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
configure.ac config.h.in install-sh set_color.c count.c \
key_reader.c gen_hdr.sh gen_hdr2.c $(MIME_OBJS:.o=.h) \
$(MIME_OBJS:.o=.c) $(COMMON_OBJS_WITH_HEADER:.o=.h) \
$(COMMON_OBJS:.o=.h) $(COMMON_OBJS_WITH_CODE:.o=.c) \
$(COMMON_OBJS:.o=.c) builtin_help.hdr fish.spec.in INSTALL README \
user_doc.head.html xsel-0.9.6.tar ChangeLog config.sub \
config.guess fish_tests.c main.c fish_pager.c fishd.c seq.in
MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
configure.ac config.h.in install-sh set_color.c count.c \
key_reader.c gen_hdr.sh gen_hdr2.c $(MIME_OBJS:.o=.h) \
$(MIME_OBJS:.o=.c) $(FISH_OBJS:.o=.h) $(BUILTIN_FILES) \
$(COMMON_FILES) $(COMMON_FILES:.c=.h) $(FISH_OBJS:.o=.c) \
builtin_help.hdr fish.spec.in INSTALL README user_doc.head.html \
xsel-0.9.6.tar ChangeLog config.sub config.guess fish_tests.c \
main.c fish_pager.c fishd.c seq.in
# Files in ./etc/
ETC_DIR_FILES :=etc/fish.in etc/fish_inputrc \
@@ -192,7 +185,7 @@ TRANSLATIONS_SRC := $(wildcard po/*.po)
TRANSLATIONS := $(TRANSLATIONS_SRC:.po=.gmo)
#Make everything needed for installing fish
all: $(PROGRAMS) user_doc
all: $(PROGRAMS) user_doc etc/fish share/fish etc/fish_interactive.fish $(TRANSLATIONS)
@echo fish has now been built.
@echo Use \'make install\' to install fish.
.PHONY: all
@@ -204,12 +197,14 @@ Makefile: Makefile.in configure
./config.status
debug:
make fish CFLAGS="@CFLAGS@ -O0 -Wno-unused -Werror -g"
make fish CFLAGS="@CFLAGS@ $(MACROS) -O0 -Wno-unused -Werror -g"
.PHONY: debug
# User documentation, describing the features of the fish shell.
user_doc: doc.h Doxyfile.user user_doc.head.html
user_doc: doc_src/doc.hdr Doxyfile.user user_doc.head.html
$(MAKE) doc.h # Depend on the source (doc.hdr) and manually make the intermediate as needed
doxygen Doxyfile.user
touch user_doc
# Source code documentation. Also includes user documentation.
doc: *.h *.c doc.h Doxyfile builtin_help.c
@@ -240,11 +235,11 @@ xsel-0.9.6/xsel: xsel-0.9.6
doc.h:$(BUILTIN_DOC_SRC) $(CMD_DOC_SRC) doc_src/doc.hdr
cat doc_src/doc.hdr >doc.h;
echo "/** \page builtins Builtin commands" >>doc.h;
cat $(BUILTIN_DOC_SRC) >>doc.h;
cat `printf "%s\n" $(BUILTIN_DOC_SRC)|sort` >>doc.h;
echo "*/" >>doc.h
echo "/** \page commands External commands" >>doc.h;
echo "\c fish is shipped with commands which do not use any internal parts of the shell, and are therefore not written as builtins, but separate commands." >>doc.h
cat $(CMD_DOC_SRC) >>doc.h;
cat `printf "%s\n" $(CMD_DOC_SRC)|sort` >>doc.h;
echo "*/" >>doc.h
# This rule creates complete doxygen headers from each of the various
@@ -256,10 +251,14 @@ doc.h:$(BUILTIN_DOC_SRC) $(CMD_DOC_SRC) doc_src/doc.hdr
cat $*.txt >>$@;
echo "*/" >>$@
%: %.in Makefile
sed <$@.in >$@ -e "s,@sysconfdir\@,$(sysconfdir)," -e "s,@datadir\@,$(datadir)," -e "s,@docdir\@,$(docdir)," -e "s|@configure_input\@|$@, generated from $@.in by the Makefile. DO NOT MANUALLY EDIT THIS FILE!|" -e "s,@prefix\@,$(prefix)," -e "s,@optbindirs\@,$(optbindirs),"
#-e "s,@\@,$(),"
# Compile translation file
%.gmo:
if test $(HAVE_GETTEXT) = 1; then \
msgfmt $*.po -o $*.gmo; \
msgfmt -o $*.gmo $*.po; \
fi
# Update existing po file or copy messages.pot
@@ -283,6 +282,10 @@ messages.pot: *.c *.h etc/*.in share/fish share/completions/*.fish share/functio
fi; \
fi
builtin.o: $(BUILTIN_FILES)
common.o: $(COMMON_FILES)
# Generate the internal help functions by making doxygen create
# man-pages which are then converted into C code. The convertion path
# looks like this:
@@ -315,15 +318,24 @@ messages.pot: *.c *.h etc/*.in share/fish share/completions/*.fish share/functio
# Which is an awful, clunky and ugly way of producing
# documentation. There ought to be something simpler.
builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh builtin_help.hdr $(CMD_DOC_HDR)
cd doc_src; doxygen; cd ..;
doc_src/builtin_doc: $(BUILTIN_DOC_SRC) doc_src/count.txt builtin_help.hdr $(CMD_DOC_SRC)
for i in $(BUILTIN_DOC_SRC) $(CMD_DOC_SRC); do \
FILE=doc_src/`basename $$i .txt`.doxygen; \
echo "/** \page" `basename $$i .txt` >$$FILE; \
cat $$i >>$$FILE; \
echo "*/" >>$$FILE; \
done
cd doc_src; doxygen; cd ..;
touch doc_src/builtin_doc
builtin_help.c: doc_src/builtin_doc gen_hdr.sh
$(MAKE) gen_hdr2 # Don't depend on gen_hdr2, because then we would need to rebuild the docs whenever we use a fresh tarball
cp builtin_help.hdr builtin_help.c;
chmod 755 gen_hdr.sh
if ! test -x gen_hdr.sh; then chmod 755 gen_hdr.sh; fi
for i in $(BUILTIN_DOC_HDR) doc_src/count.doxygen ; do \
echo ' hash_put( &tbl, L"'`basename $$i .doxygen`'",' >>$@; \
echo ' hash_put( &tbl, L"'`basename $$i .doxygen`'",' >>$@; \
./gen_hdr.sh $$i >>$@; \
echo " );" >>$@; \
echo >>$@; \
printf " );\n\n" >>$@; \
done;
echo "}" >>builtin_help.c
@@ -332,7 +344,8 @@ builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh bui
# mimedb. Depends on builtin_help.c to make sure doxygen gets run to
# generate the man files.
#
%.c : %.doxygen gen_hdr2 builtin_help.c
%.c : %.doxygen
$(MAKE) gen_hdr2 builtin_help.c # These should really be filed as dependencis for %.c above instead, but that seems to confuse make
echo "// This file was automatically generated, do not edit" >$@
echo "#include <stdlib.h>" >>$@
echo "#include <stdio.h>" >>$@
@@ -478,8 +491,8 @@ uninstall-translations:
# The build rules for all the commands
#
fish: $(FISH_OBJS)
$(CC) $(FISH_OBJS) $(LDFLAGS) -o $@
fish: $(FISH_OBJS) main.o
$(CC) $(FISH_OBJS) main.o $(LDFLAGS) -o $@
fish_pager: $(FISH_PAGER_OBJS)
$(CC) $(FISH_PAGER_OBJS) $(LDFLAGS) -o $@
@@ -490,20 +503,24 @@ fishd: $(FISHD_OBJS)
fish_tests: $(FISH_TESTS_OBJS)
$(CC) $(FISH_TESTS_OBJS) $(LDFLAGS) -o $@
# mimedb does not need any libraries, so we don't use LDFLAGS here
mimedb: $(MIME_OBJS) doc_src/mimedb.o
$(CC) ${MIME_OBJS} doc_src/mimedb.o $(LDFLAGS) -o $@
$(CC) $(MIME_OBJS) doc_src/mimedb.o $(LDFLAGS) -o $@
set_color: set_color.o doc_src/set_color.o
$(CC) set_color.o doc_src/set_color.o $(LDFLAGS) -o $@
# count does not need any libraries, so we don't use LDFLAGS here
count: count.o
$(CC) count.o -o $@
set_color: set_color.o doc_src/set_color.o common.o
$(CC) set_color.o doc_src/set_color.o common.o $(LDFLAGS) -o $@
# Test program for the tokenizer library
tokenizer_test: tokenizer.c tokenizer.h util.o wutil.o common.o
$(CC) ${CFLAGS} tokenizer.c util.o wutil.o common.o -D TOKENIZER_TEST $(LDFLAGS) -o $@
tokenizer_test: tokenizer.c tokenizer.h wutil.o common.o
$(CC) $(CFLAGS) tokenizer.c wutil.o common.o -D TOKENIZER_TEST $(LDFLAGS) -o $@
# Neat little program to show output from terminal
key_reader: key_reader.o input_common.o $(CORE_OBJS) env_universal.o env_universal_common.o wutil.o
$(CC) key_reader.o input_common.o $(CORE_OBJS) env_universal.o env_universal_common.o wutil.o $(LDFLAGS) -o $@
key_reader: key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o
$(CC) key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o $(LDFLAGS) -o $@
#
# Update dependencies
@@ -519,10 +536,11 @@ depend:
#
# Uses install instead of mkdir so build won't fail if the directory
# exists
fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(ETC_DIR_FILES) $(TEST_DIR_FILES) $(SHARE_DIR_FILES) $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES) ChangeLog
fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(ETC_DIR_FILES) $(TEST_DIR_FILES) $(SHARE_DIR_FILES) $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES) ChangeLog user_doc doc_src/builtin_doc
rm -rf fish-@PACKAGE_VERSION@
$(INSTALL) -d fish-@PACKAGE_VERSION@
$(INSTALL) -d fish-@PACKAGE_VERSION@/doc_src
$(INSTALL) -d fish-@PACKAGE_VERSION@/user_doc
$(INSTALL) -d fish-@PACKAGE_VERSION@/etc
$(INSTALL) -d fish-@PACKAGE_VERSION@/share
$(INSTALL) -d fish-@PACKAGE_VERSION@/share/completions
@@ -537,6 +555,8 @@ fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(ETC_DIR_FIL
cp -f $(FUNCTIONS_DIR_FILES) fish-@PACKAGE_VERSION@/share/functions/
cp -f $(TESTS_DIR_FILES) fish-@PACKAGE_VERSION@/tests/
cp -f $(TRANSLATIONS_SRC) fish-@PACKAGE_VERSION@/po/
cp -rf user_doc fish-@PACKAGE_VERSION@/
cp -rf doc_src/builtin_doc fish-@PACKAGE_VERSION@/doc_src/
tar -c fish-@PACKAGE_VERSION@ >fish-@PACKAGE_VERSION@.tar
rm -rf fish-@PACKAGE_VERSION@
@@ -596,112 +616,111 @@ clean:
# DO NOT DELETE THIS LINE -- make depend depends on it.
builtin.o: config.h fallback.h common.h util.h wutil.h builtin.h function.h
builtin.o: complete.h proc.h io.h parser.h event.h reader.h env.h wgetopt.h
builtin.o: sanity.h tokenizer.h builtin_help.h wildcard.h input_common.h
builtin.o: input.h intern.h signal.h translate.h halloc.h halloc_util.h
builtin.o: parse_util.h expand.h
builtin_commandline.o: signal.h config.h fallback.h common.h util.h wutil.h
builtin_commandline.o: builtin.h wgetopt.h reader.h proc.h io.h parser.h
builtin_commandline.o: event.h tokenizer.h input_common.h input.h translate.h
builtin.o: config.h fallback.h util.h wutil.h builtin.h function.h complete.h
builtin.o: proc.h io.h parser.h event.h reader.h env.h common.h wgetopt.h
builtin.o: sanity.h tokenizer.h wildcard.h input_common.h input.h intern.h
builtin.o: signal.h halloc.h halloc_util.h parse_util.h expand.h
builtin.o: builtin_help.c builtin_set.c builtin_commandline.c
builtin.o: builtin_complete.c builtin_ulimit.c builtin_jobs.c
builtin_commandline.o: signal.h config.h fallback.h util.h wutil.h builtin.h
builtin_commandline.o: common.h wgetopt.h reader.h proc.h io.h parser.h
builtin_commandline.o: event.h tokenizer.h input_common.h input.h
builtin_commandline.o: parse_util.h
builtin_complete.o: signal.h config.h fallback.h common.h util.h wutil.h
builtin_complete.o: builtin.h complete.h wgetopt.h parser.h proc.h io.h
builtin_complete.o: event.h reader.h translate.h
builtin_help.o: config.h util.h common.h builtin_help.h
builtin_set.o: signal.h config.h fallback.h common.h util.h wutil.h builtin.h
builtin_set.o: env.h expand.h wgetopt.h proc.h io.h parser.h event.h
builtin_set.o: translate.h
builtin_ulimit.o: config.h fallback.h common.h util.h builtin.h wgetopt.h
builtin_ulimit.o: translate.h
common.o: config.h fallback.h common.h util.h wutil.h expand.h proc.h io.h
common.o: wildcard.h parser.h event.h
complete.o: signal.h config.h fallback.h common.h util.h tokenizer.h
complete.o: wildcard.h proc.h io.h parser.h event.h function.h complete.h
complete.o: builtin.h env.h exec.h expand.h reader.h history.h intern.h
complete.o: translate.h parse_util.h halloc_util.h wutil.h
env.o: config.h signal.h fallback.h common.h util.h wutil.h proc.h io.h env.h
builtin_complete.o: signal.h config.h fallback.h util.h wutil.h builtin.h
builtin_complete.o: common.h complete.h wgetopt.h parser.h proc.h io.h
builtin_complete.o: event.h reader.h
builtin_help.o: config.h util.h common.h halloc_util.h
builtin_jobs.o: config.h fallback.h util.h wutil.h builtin.h proc.h io.h
builtin_jobs.o: parser.h event.h common.h wgetopt.h
builtin_set.o: signal.h config.h fallback.h util.h wutil.h builtin.h env.h
builtin_set.o: expand.h common.h wgetopt.h proc.h io.h parser.h event.h
builtin_ulimit.o: config.h fallback.h util.h builtin.h common.h wgetopt.h
common.o: config.h fallback.h util.h wutil.h common.h expand.h proc.h io.h
common.o: wildcard.h parser.h event.h util.c halloc.c halloc.h halloc_util.c
common.o: fallback.c
complete.o: signal.h config.h fallback.h util.h tokenizer.h wildcard.h proc.h
complete.o: io.h parser.h event.h function.h complete.h builtin.h env.h
complete.o: exec.h expand.h common.h reader.h history.h intern.h parse_util.h
complete.o: halloc.h halloc_util.h wutil.h
env.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h env.h
env.o: sanity.h expand.h history.h reader.h parser.h event.h env_universal.h
env.o: env_universal_common.h input_common.h translate.h complete.h
env_universal.o: config.h signal.h fallback.h common.h util.h wutil.h
env.o: env_universal_common.h input_common.h complete.h
env_universal.o: config.h signal.h fallback.h util.h common.h wutil.h
env_universal.o: env_universal_common.h env_universal.h
env_universal_common.o: config.h signal.h fallback.h common.h util.h wutil.h
env_universal_common.o: config.h signal.h fallback.h util.h common.h wutil.h
env_universal_common.o: env_universal_common.h
event.o: signal.h config.h fallback.h common.h util.h wutil.h function.h
event.o: proc.h io.h parser.h event.h translate.h halloc_util.h
exec.o: signal.h config.h fallback.h common.h util.h wutil.h proc.h io.h
event.o: signal.h config.h fallback.h util.h wutil.h function.h proc.h io.h
event.o: parser.h event.h common.h halloc_util.h
exec.o: signal.h config.h fallback.h util.h common.h wutil.h proc.h io.h
exec.o: exec.h parser.h event.h builtin.h function.h env.h wildcard.h
exec.o: sanity.h expand.h env_universal.h env_universal_common.h translate.h
exec.o: halloc.h halloc_util.h parse_util.h
expand.o: signal.h config.h fallback.h common.h util.h wutil.h env.h proc.h
exec.o: sanity.h expand.h env_universal.h env_universal_common.h halloc.h
exec.o: halloc_util.h parse_util.h
expand.o: signal.h config.h fallback.h util.h common.h wutil.h env.h proc.h
expand.o: io.h parser.h event.h expand.h wildcard.h exec.h tokenizer.h
expand.o: complete.h translate.h parse_util.h halloc_util.h
fallback.o: config.h fallback.h common.h util.h
fishd.o: config.h signal.h fallback.h common.h util.h wutil.h
expand.o: complete.h parse_util.h halloc_util.h
fallback.o: config.h fallback.h util.h
fishd.o: config.h signal.h fallback.h util.h common.h wutil.h
fishd.o: env_universal_common.h
fish_pager.o: config.h signal.h fallback.h common.h util.h wutil.h complete.h
fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h
fish_pager.o: output.h input_common.h env_universal.h env_universal_common.h
fish_pager.o: halloc.h halloc_util.h
fish_tests.o: config.h signal.h fallback.h common.h util.h proc.h io.h
fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h
fish_tests.o: reader.h builtin.h function.h complete.h wutil.h env.h expand.h
fish_tests.o: parser.h event.h tokenizer.h output.h exec.h halloc_util.h
function.o: signal.h config.h wutil.h fallback.h common.h util.h function.h
function.o: proc.h io.h translate.h parser.h event.h intern.h reader.h
function.o: parse_util.h env.h expand.h
halloc.o: config.h fallback.h common.h util.h halloc.h
halloc_util.o: config.h fallback.h common.h util.h halloc.h
highlight.o: signal.h config.h fallback.h common.h util.h wutil.h highlight.h
function.o: signal.h config.h wutil.h fallback.h util.h function.h proc.h
function.o: io.h parser.h event.h common.h intern.h reader.h parse_util.h
function.o: env.h expand.h
halloc.o: config.h fallback.h util.h common.h halloc.h
halloc_util.o: config.h fallback.h util.h common.h halloc.h
highlight.o: signal.h config.h fallback.h util.h wutil.h highlight.h
highlight.o: tokenizer.h proc.h io.h parser.h event.h parse_util.h builtin.h
highlight.o: function.h env.h expand.h sanity.h complete.h output.h
history.o: config.h fallback.h common.h util.h wutil.h history.h reader.h
highlight.o: function.h env.h expand.h sanity.h common.h complete.h output.h
highlight.o: halloc.h halloc_util.h
history.o: config.h fallback.h util.h wutil.h history.h common.h reader.h
history.o: env.h sanity.h signal.h
input.o: config.h signal.h fallback.h common.h util.h wutil.h reader.h proc.h
input.o: io.h sanity.h input_common.h input.h parser.h event.h env.h expand.h
input.o: translate.h output.h
input_common.o: config.h fallback.h common.h util.h wutil.h input_common.h
input.o: config.h signal.h fallback.h util.h wutil.h reader.h proc.h io.h
input.o: common.h sanity.h input_common.h input.h parser.h event.h env.h
input.o: expand.h output.h intern.h
input_common.o: config.h fallback.h util.h common.h wutil.h input_common.h
input_common.o: env_universal.h env_universal_common.h
intern.o: config.h fallback.h common.h util.h wutil.h intern.h
io.o: config.h fallback.h common.h util.h wutil.h exec.h proc.h io.h
io.o: translate.h halloc.h
key_reader.o: fallback.h common.h util.h input_common.h
kill.o: signal.h config.h fallback.h common.h util.h wutil.h kill.h proc.h
kill.o: io.h sanity.h env.h exec.h parser.h event.h
main.o: config.h signal.h fallback.h common.h util.h reader.h builtin.h
intern.o: config.h fallback.h util.h wutil.h common.h intern.h
io.o: config.h fallback.h util.h wutil.h exec.h proc.h io.h common.h halloc.h
key_reader.o: config.h fallback.h input_common.h
kill.o: signal.h config.h fallback.h util.h wutil.h kill.h proc.h io.h
kill.o: sanity.h common.h env.h exec.h parser.h event.h halloc.h
main.o: config.h signal.h fallback.h util.h common.h reader.h builtin.h
main.o: function.h complete.h wutil.h env.h sanity.h proc.h io.h parser.h
main.o: event.h expand.h intern.h exec.h output.h translate.h halloc_util.h
main.o: history.h
mimedb.o: config.h xdgmime.h fallback.h common.h util.h
output.o: config.h signal.h fallback.h common.h util.h wutil.h expand.h
main.o: event.h expand.h intern.h exec.h output.h halloc_util.h history.h
mimedb.o: config.h xdgmime.h fallback.h util.h
output.o: config.h signal.h fallback.h util.h wutil.h expand.h common.h
output.o: output.h halloc_util.h highlight.h
parser.o: signal.h config.h fallback.h common.h util.h wutil.h proc.h io.h
parser.o: signal.h config.h fallback.h util.h common.h wutil.h proc.h io.h
parser.o: parser.h event.h tokenizer.h exec.h wildcard.h function.h builtin.h
parser.o: builtin_help.h env.h expand.h reader.h sanity.h env_universal.h
parser.o: env_universal_common.h translate.h intern.h parse_util.h halloc.h
parser.o: halloc_util.h
parse_util.o: config.h fallback.h common.h util.h wutil.h tokenizer.h
parser.o: env.h expand.h reader.h sanity.h env_universal.h
parser.o: env_universal_common.h intern.h parse_util.h halloc.h halloc_util.h
parse_util.o: config.h fallback.h util.h wutil.h common.h tokenizer.h
parse_util.o: parse_util.h expand.h intern.h exec.h proc.h io.h env.h
parse_util.o: wildcard.h halloc_util.h
proc.o: config.h signal.h fallback.h common.h util.h wutil.h proc.h io.h
proc.o: reader.h sanity.h env.h parser.h event.h translate.h halloc.h
proc.o: halloc_util.h output.h
reader.o: config.h signal.h fallback.h common.h util.h wutil.h highlight.h
reader.o: reader.h proc.h io.h parser.h event.h complete.h history.h sanity.h
proc.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h
proc.o: reader.h sanity.h env.h parser.h event.h halloc.h halloc_util.h
proc.o: output.h
reader.o: config.h signal.h fallback.h util.h wutil.h highlight.h reader.h
reader.o: proc.h io.h parser.h event.h complete.h history.h common.h sanity.h
reader.o: env.h exec.h expand.h tokenizer.h kill.h input_common.h input.h
reader.o: function.h output.h translate.h parse_util.h
refcount.o: config.h fallback.h common.h util.h wutil.h refcount.h
sanity.o: signal.h config.h fallback.h common.h util.h sanity.h proc.h io.h
sanity.o: history.h reader.h kill.h wutil.h translate.h
set_color.o: config.h
reader.o: function.h output.h parse_util.h
sanity.o: signal.h config.h fallback.h util.h common.h sanity.h proc.h io.h
sanity.o: history.h reader.h kill.h wutil.h
set_color.o: config.h fallback.h
signal.o: config.h signal.h common.h util.h fallback.h wutil.h event.h
signal.o: reader.h proc.h io.h translate.h
tokenizer.o: config.h fallback.h common.h util.h wutil.h tokenizer.h
tokenizer.o: wildcard.h translate.h
translate.o: config.h common.h util.h fallback.h halloc_util.h
util.o: config.h fallback.h common.h util.h wutil.h
wgetopt.o: config.h wgetopt.h wutil.h fallback.h common.h util.h translate.h
wildcard.o: config.h fallback.h common.h util.h wutil.h complete.h wildcard.h
wildcard.o: reader.h expand.h translate.h
wutil.o: config.h fallback.h common.h util.h wutil.h
signal.o: reader.h proc.h io.h
test.o: stringtab.h
tokenizer.o: config.h fallback.h util.h wutil.h tokenizer.h common.h
tokenizer.o: wildcard.h
util.o: config.h fallback.h util.h common.h wutil.h
wgetopt.o: config.h wgetopt.h wutil.h fallback.h
wildcard.o: config.h fallback.h util.h wutil.h complete.h common.h wildcard.h
wildcard.o: reader.h expand.h
wutil.o: config.h fallback.h util.h common.h wutil.h halloc.h halloc_util.h
xdgmimealias.o: xdgmimealias.h xdgmime.h xdgmimeint.h
xdgmime.o: xdgmime.h xdgmimeint.h xdgmimeglob.h xdgmimemagic.h xdgmimealias.h
xdgmime.o: xdgmimeparent.h

257
builtin.c
View File

@@ -15,7 +15,7 @@
4). Add an entry to the BUILTIN_DOC_SRC variable of Makefile.in. Note that the entries should be sorted alphabetically!
5). Add an entry to the manual at the builtin-overview subsection. Note that the entries should be sorted alphabetically!
5). Add an entry to the manual at the builtin-overview subsection of doc_src/doc.hdr. Note that the entries should be sorted alphabetically!
6). Use 'darcs add doc_src/NAME.txt' to start tracking changes to the documentation file.
@@ -54,19 +54,20 @@
#include "wgetopt.h"
#include "sanity.h"
#include "tokenizer.h"
#include "builtin_help.h"
#include "wildcard.h"
#include "input_common.h"
#include "input.h"
#include "intern.h"
#include "event.h"
#include "signal.h"
#include "translate.h"
#include "halloc.h"
#include "halloc_util.h"
#include "parse_util.h"
#include "expand.h"
/**
The default prompt for the read command
*/
@@ -83,10 +84,22 @@
*/
#define FG_MSG _( L"Send job %d, '%ls' to foreground\n" )
/**
Datastructure to describe a builtin.
*/
typedef struct builtin_data
{
/**
Name of the builtin
*/
const wchar_t *name;
/**
Function pointer tothe builtin implementation
*/
int (*func)(wchar_t **argv);
/**
Description of what the builtin does
*/
const wchar_t *desc;
}
builtin_data_t;
@@ -121,7 +134,11 @@ static int builtin_stdin;
*/
static hash_table_t *desc=0;
int builtin_count_args( wchar_t **argv )
/**
Counts the number of non null pointers in the specified array
*/
static int builtin_count_args( wchar_t **argv )
{
int argc = 1;
while( argv[argc] != 0 )
@@ -131,8 +148,13 @@ int builtin_count_args( wchar_t **argv )
return argc;
}
/**
This function works like wperror, but it prints its result into
the sb_err string_buffer_t instead of to stderr. Used by the builtin
commands.
*/
void builtin_wperror( const wchar_t *s)
static void builtin_wperror( const wchar_t *s)
{
if( s != 0 )
{
@@ -147,6 +169,9 @@ void builtin_wperror( const wchar_t *s)
}
}
/**
Count the number of times the specified character occurs in the specified string
*/
static int count_char( const wchar_t *str, wchar_t c )
{
int res = 0;
@@ -157,23 +182,18 @@ static int count_char( const wchar_t *str, wchar_t c )
return res;
}
/*
Here follows the definition of all builtin commands. The function
names are all on the form builtin_NAME where NAME is the name of the
builtin. so the function name for the builtin 'jobs' is
'builtin_jobs'.
/**
Print help for the specified builtin. If \c b is sb_err, also print
the line information
Two builtins, 'command' and 'builtin' are not defined here as they
are part of the parser. (They are not parsed as commands, instead
they only slightly alter the parser state)
If \c b is the buffer representing standard error, and the help
message is about to be printed to an interactive screen, it may be
shortened to fit the screen.
If \c b is the buffer representing standard error, and the help
message is about to be printed to an interactive screen, it may be
shortened to fit the screen.
*/
void builtin_print_help( wchar_t *cmd, string_buffer_t *b )
static void builtin_print_help( wchar_t *cmd, string_buffer_t *b )
{
const char *h;
@@ -236,6 +256,35 @@ void builtin_print_help( wchar_t *cmd, string_buffer_t *b )
free( str );
}
}
/*
Here follows the definition of all builtin commands. The function
names are all on the form builtin_NAME where NAME is the name of the
builtin. so the function name for the builtin 'fg' is
'builtin_fg'.
A few builtins, including 'while', 'command' and 'builtin' are not
defined here as they are handled directly by the parser. (They are
not parsed as commands, instead they only alter the parser state)
The builtins 'break' and 'continue' are so closely related that they
share the same implementation, namely 'builtin_break_continue.
Several other builtins, including jobs, ulimit and set are so big
that they have been given their own file. These files are all named
'builtin_NAME.c', where NAME is the name of the builtin.
*/
#include "builtin_help.c"
#include "builtin_set.c"
#include "builtin_commandline.c"
#include "builtin_complete.c"
#include "builtin_ulimit.c"
#include "builtin_jobs.c"
/**
The bind builtin, used for setting character sequences
*/
@@ -432,7 +481,7 @@ static int builtin_block( wchar_t **argv )
event_block_t *eb = malloc( sizeof( event_block_t ) );
if( !eb )
die_mem();
DIE_MEM();
eb->type = type;
@@ -725,6 +774,7 @@ static int builtin_functions( wchar_t **argv )
int list=0;
int show_hidden=0;
int res = 0;
int query = 0;
woptind=0;
@@ -751,6 +801,10 @@ static int builtin_functions( wchar_t **argv )
L"help", no_argument, 0, 'h'
}
,
{
L"query", no_argument, 0, 'q'
}
,
{
0, 0, 0, 0
}
@@ -763,7 +817,7 @@ static int builtin_functions( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"ed:nah",
L"ed:nahq",
long_options,
&opt_index );
if( opt == -1 )
@@ -803,6 +857,10 @@ static int builtin_functions( wchar_t **argv )
builtin_print_help( argv[0], sb_out );
return 0;
case 'q':
query = 1;
break;
case '?':
builtin_print_help( argv[0], sb_err );
@@ -813,9 +871,9 @@ static int builtin_functions( wchar_t **argv )
}
/*
Erase, desc and list are mutually exclusive
Erase, desc, query and list are mutually exclusive
*/
if( (erase + (desc!=0) + list) > 1 )
if( (erase + (desc!=0) + list + query) > 1 )
{
sb_printf( sb_err,
_( L"%ls: Invalid combination of options\n" ),
@@ -902,22 +960,25 @@ static int builtin_functions( wchar_t **argv )
return 0;
}
switch( argc - woptind )
{
case 0:
{
sb_append( sb_out, _( L"Current function definitions are:\n\n" ) );
al_init( &names );
function_get_names( &names, show_hidden );
sort_list( &names );
for( i=0; i<al_get_count( &names ); i++ )
if( !query )
{
functions_def( (wchar_t *)al_get( &names, i ) );
sb_append( sb_out, _( L"Current function definitions are:\n\n" ) );
al_init( &names );
function_get_names( &names, show_hidden );
sort_list( &names );
for( i=0; i<al_get_count( &names ); i++ )
{
functions_def( (wchar_t *)al_get( &names, i ) );
}
al_destroy( &names );
}
al_destroy( &names );
break;
}
@@ -929,8 +990,11 @@ static int builtin_functions( wchar_t **argv )
res++;
else
{
functions_def( argv[i] );
}
if( !query )
{
functions_def( argv[i] );
}
}
}
break;
@@ -1063,7 +1127,7 @@ static int builtin_function( wchar_t **argv )
e = halloc( current_block, sizeof(event_t));
if( !e )
die_mem();
DIE_MEM();
e->type = EVENT_SIGNAL;
e->param1.signal = sig;
e->function_name=0;
@@ -1087,7 +1151,7 @@ static int builtin_function( wchar_t **argv )
e = halloc( current_block, sizeof(event_t));
if( !e )
die_mem();
DIE_MEM();
e->type = EVENT_VARIABLE;
e->param1.variable = halloc_wcsdup( current_block, woptarg );
e->function_name=0;
@@ -1104,7 +1168,7 @@ static int builtin_function( wchar_t **argv )
e = halloc( current_block, sizeof(event_t));
if( !e )
die_mem();
DIE_MEM();
if( ( opt == 'j' ) &&
( wcscasecmp( woptarg, L"caller" ) == 0 ) )
@@ -1277,6 +1341,8 @@ static int builtin_function( wchar_t **argv )
static int builtin_random( wchar_t **argv )
{
static int seeded=0;
static struct drand48_data seed_buffer;
int argc = builtin_count_args( argv );
woptind=0;
@@ -1337,18 +1403,22 @@ static int builtin_random( wchar_t **argv )
case 0:
{
long res;
if( !seeded )
{
seeded=1;
srand( time( 0 ) );
srand48_r(time(0), &seed_buffer);
}
sb_printf( sb_out, L"%d\n", rand()%32767 );
lrand48_r( &seed_buffer, &res );
sb_printf( sb_out, L"%d\n", res%32767 );
break;
}
case 1:
{
int foo;
long foo;
wchar_t *end=0;
errno=0;
@@ -1363,7 +1433,7 @@ static int builtin_random( wchar_t **argv )
return 1;
}
seeded=1;
srand( foo );
srand48_r( foo, &seed_buffer);
break;
}
@@ -1899,7 +1969,11 @@ static int builtin_exit( wchar_t **argv )
switch( argc )
{
case 1:
{
ec = proc_get_last_status();
break;
}
case 2:
{
wchar_t *end;
@@ -1918,13 +1992,15 @@ static int builtin_exit( wchar_t **argv )
}
default:
{
sb_printf( sb_err,
BUILTIN_ERR_TOO_MANY_ARGUMENTS,
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
}
}
reader_exit( 1, 0 );
return ec;
@@ -1933,7 +2009,7 @@ static int builtin_exit( wchar_t **argv )
/**
Helper function for builtin_cd, used for seting the current working directory
*/
static int set_pwd(wchar_t *env)
static int set_pwd( wchar_t *env)
{
wchar_t dir_path[4096];
wchar_t *res = wgetcwd( dir_path, 4096 );
@@ -1957,7 +2033,9 @@ static int builtin_cd( wchar_t **argv )
wchar_t *dir_in;
wchar_t *dir;
int res=0;
void *context = halloc( 0, 0 );
if( argv[1] == 0 )
{
dir_in = env_get( L"HOME" );
@@ -1971,7 +2049,7 @@ static int builtin_cd( wchar_t **argv )
else
dir_in = argv[1];
dir = parser_cdpath_get( dir_in );
dir = parser_cdpath_get( context, dir_in );
if( !dir )
{
@@ -1980,36 +2058,36 @@ static int builtin_cd( wchar_t **argv )
argv[0],
dir_in );
if( !is_interactive )
{
sb_append2( sb_err,
parser_current_line(),
(void *)0 );
return 1;
}
res = 1;
}
if( wchdir( dir ) != 0 )
else if( wchdir( dir ) != 0 )
{
sb_printf( sb_err,
_( L"%ls: '%ls' is not a directory\n" ),
argv[0],
dir );
if( !is_interactive )
{
sb_append2( sb_err,
parser_current_line(),
(void *)0 );
}
free( dir );
return 1;
res = 1;
}
if (!set_pwd(L"PWD"))
else if( !set_pwd(L"PWD") )
{
res=1;
sb_printf( sb_err, _( L"%ls: Could not set PWD variable\n" ), argv[0] );
}
free( dir );
halloc_free( context );
return res;
}
@@ -2113,7 +2191,9 @@ static void make_first( job_t *j )
if( curr == j )
{
if( prev == 0 )
{
return;
}
else
{
prev->next = curr->next;
@@ -2134,12 +2214,16 @@ static int builtin_fg( wchar_t **argv )
if( argv[1] == 0 )
{
/*
Select last constructed job (I.e. first job in the job que) that is possible to put in the foreground
Select last constructed job (I.e. first job in the job que)
that is possible to put in the foreground
*/
for( j=first_job; j; j=j->next )
{
if( j->constructed && (!job_is_completed(j)) && ( (job_is_stopped(j) || !j->fg) && (j->job_control)))
if( j->constructed && (!job_is_completed(j)) &&
( (job_is_stopped(j) || !j->fg) && (j->job_control) ) )
{
break;
}
}
if( !j )
{
@@ -2185,7 +2269,7 @@ static int builtin_fg( wchar_t **argv )
if( *end )
{
sb_printf( sb_err,
_( L"%ls: Argument must be a number: %ls\n" ),
_( L"%ls: Argument '%ls' is not a number\n" ),
argv[0],
argv[1] );
builtin_print_help( argv[0], sb_err );
@@ -2302,9 +2386,11 @@ static int builtin_bg( wchar_t **argv )
for( j=first_job; j; j=j->next )
{
if( job_is_stopped(j) && j->job_control && (!job_is_completed(j)) )
{
break;
}
}
if( !j )
{
sb_printf( sb_err,
@@ -2405,7 +2491,7 @@ static int builtin_begin( wchar_t **argv )
{
parser_push_block( BEGIN );
current_block->tok_pos = parser_get_pos();
return 0;
return proc_get_last_status();
}
@@ -2458,7 +2544,7 @@ static int builtin_end( wchar_t **argv )
case SUBST:
case BEGIN:
/*
Nothing special happens at the end of these. The scope just ends.
Nothing special happens at the end of these commands. The scope just ends.
*/
break;
@@ -2482,10 +2568,6 @@ static int builtin_end( wchar_t **argv )
kill_block = 0;
parser_set_pos( current_block->tok_pos );
/*
fwprintf( stderr,
L"jump to %d\n",
current_block->tok_pos ); */
}
break;
}
@@ -2499,17 +2581,12 @@ static int builtin_end( wchar_t **argv )
*/
wchar_t *def = wcsndup( parser_get_buffer()+current_block->tok_pos,
parser_get_job_pos()-current_block->tok_pos );
//fwprintf( stderr, L"Function: %ls\n", def );
if( !is_interactive || !parser_test( def, 1 ) )
{
function_add( current_block->param1.function_name,
def,
current_block->param2.function_description,
current_block->param4.function_events,
current_block->param3.function_is_binding );
}
function_add( current_block->param1.function_name,
def,
current_block->param2.function_description,
current_block->param4.function_events,
current_block->param3.function_is_binding );
free(def);
}
@@ -2615,7 +2692,7 @@ static int builtin_break_continue( wchar_t **argv )
static int builtin_return( wchar_t **argv )
{
int argc = builtin_count_args( argv );
int status = 0;
int status = proc_get_last_status();
block_t *b = current_block;
@@ -2637,7 +2714,6 @@ static int builtin_return( wchar_t **argv )
builtin_print_help( argv[0], sb_err );
return 1;
}
// fwprintf( stderr, L"Return with status %d\n", status );
break;
}
default:
@@ -2756,6 +2832,9 @@ static int builtin_case( wchar_t **argv )
Below are functions for handling the builtin commands
*/
/**
Data about all the builtin commands in fish
*/
const static builtin_data_t builtin_data[]=
{
{
@@ -2866,6 +2945,10 @@ const static builtin_data_t builtin_data[]=
L"ulimit", &builtin_ulimit, N_( L"Set or get the shells resource usage limits" )
}
,
{
L"begin", &builtin_begin, N_( L"Create a block of code" )
}
,
/*
Builtins that are handled directly by the parser. They are
@@ -2900,10 +2983,6 @@ const static builtin_data_t builtin_data[]=
L"exec", &builtin_generic, N_( L"Run command in current process" )
}
,
{
L"begin", &builtin_begin, N_( L"Create a block of code" )
}
,
/*
This is not a builtin, but fish handles it's help display
@@ -2934,8 +3013,6 @@ void builtin_init()
hash_put( &builtin, builtin_data[i].name, builtin_data[i].func );
intern_static( builtin_data[i].name );
}
builtin_help_init();
}
void builtin_destroy()
@@ -2949,11 +3026,12 @@ void builtin_destroy()
al_destroy( &io_stack );
hash_destroy( &builtin );
builtin_help_destroy();
}
int builtin_exists( wchar_t *cmd )
{
CHECK( cmd, 0 );
/*
Count is not a builtin, but it's help is handled internally by
fish, so it is in the hash_table_t.
@@ -2984,6 +3062,10 @@ static int internal_help( wchar_t *cmd )
int builtin_run( wchar_t **argv )
{
int (*cmd)(wchar_t **argv)=0;
CHECK( argv, 1 );
CHECK( argv[0], 1 );
cmd = (int (*)(wchar_t **))hash_get( &builtin, argv[0] );
if( argv[1] != 0 && !internal_help(argv[0]) )
@@ -3000,8 +3082,6 @@ int builtin_run( wchar_t **argv )
int status;
status = cmd(argv);
// fwprintf( stderr, L"Builtin: Set status of %ls to %d\n", argv[0], status );
return status;
}
@@ -3015,12 +3095,15 @@ int builtin_run( wchar_t **argv )
void builtin_get_names( array_list_t *list )
{
CHECK( list, );
hash_get_keys( &builtin, list );
}
const wchar_t *builtin_get_desc( const wchar_t *b )
{
CHECK( b, 0 );
if( !desc )
{
int i;
@@ -3039,7 +3122,7 @@ const wchar_t *builtin_get_desc( const wchar_t *b )
return _( hash_get( desc, b ));
}
void builtin_push_io( int in)
void builtin_push_io( int in )
{
if( builtin_stdin != -1 )
{

View File

@@ -62,6 +62,9 @@ enum
*/
#define BUILTIN_FOR_ERR_IN _( L"%ls: Second argument must be 'in'\n" )
/**
Error message when too many arguments are supplied to a builtin
*/
#define BUILTIN_ERR_TOO_MANY_ARGUMENTS _( L"%ls: Too many arguments\n" )
/**
@@ -133,55 +136,22 @@ void builtin_pop_io();
*/
const wchar_t *builtin_get_desc( const wchar_t *b );
/**
Counts the number of non null pointers in the specified array
*/
int builtin_count_args( wchar_t **argv );
/**
Print help for the specified builtin. If \c b is sb_err, also print
the line information
Slightly kludgy function used with 'complete -C' in order to make
the commandline builtin operate on the string to complete instead
of operating on whatever is to be completed.
*/
void builtin_print_help( wchar_t *cmd, string_buffer_t *b );
/**
The set builtin, used for setting variables. Defined in
builtin_set.c.
*/
int builtin_set(wchar_t **argv);
/**
The commandline builtin, used for setting and getting the contents
of the commandline. Defined in builtin_commandline.c.
*/
int builtin_commandline(wchar_t **argv);
/**
The ulimit builtin, used for setting resource limits. Defined in
builtin_ulimit.c.
*/
int builtin_ulimit(wchar_t **argv);
/**
The complete builtin. Used for specifying programmable
tab-completions. Calls the functions in complete.c for any heavy
lifting. Defined in builtin_complete.c
*/
int builtin_complete(wchar_t **argv);
/**
The jobs builtin. Used fopr printing running jobs. Defined in builtin_jobs.c.
*/
int builtin_jobs(wchar_t **argv);
const wchar_t *builtin_complete_get_temporary_buffer();
/**
This function works like wperror, but it prints its result into
the sb_err string_buffer_t instead of to stderr. Used by the builtin
commands.
/**
Return the help text for the specified builtin command. Use
non-wide characters since wide characters have some issues with
string formating escape sequences sometimes.
\param cmd The command for which to obtain help text
*/
void builtin_wperror( const wchar_t *s);
char *builtin_help_get( const wchar_t *cmd );
#endif

View File

@@ -26,7 +26,7 @@ Functions used for implementing the commandline builtin.
#include "tokenizer.h"
#include "input_common.h"
#include "input.h"
#include "translate.h"
#include "parse_util.h"
/**
@@ -63,6 +63,9 @@ static const wchar_t *get_buffer()
return buff;
}
/**
Returns the position of the cursor
*/
static int get_cursor_pos()
{
const wchar_t *buff = builtin_complete_get_temporary_buffer();
@@ -195,7 +198,7 @@ static void write_part( const wchar_t *begin,
The commandline builtin. It is used for specifying a new value for
the commandline.
*/
int builtin_commandline( wchar_t **argv )
static int builtin_commandline( wchar_t **argv )
{
int buffer_part=0;
@@ -461,13 +464,13 @@ int builtin_commandline( wchar_t **argv )
buffer_part = STRING_MODE;
}
const wchar_t *begin, *end;
wchar_t *begin, *end;
switch( buffer_part )
{
case STRING_MODE:
{
begin = get_buffer();
begin = (wchar_t *)get_buffer();
end = begin+wcslen(begin);
break;
}

View File

@@ -23,16 +23,25 @@ Functions used for implementing the complete builtin.
#include "wgetopt.h"
#include "parser.h"
#include "reader.h"
#include "translate.h"
/**
Internal storage for the builtin_get_temporary_buffer() function.
*/
const static wchar_t *temporary_buffer;
/*
builtin_complete_* are a set of rather silly looping functions that
make sure that all the proper combinations of complete_add or
complete_remove get called.
complete_remove get called. This is needed since complete allows you
to specify multiple switches on a single commandline, like 'complete
-s a -s b -s c', but the complete_add function only accepts one
short switch and one long switch.
*/
/**
Silly function
*/
static void builtin_complete_add2( const wchar_t *cmd,
int cmd_type,
const wchar_t *short_opt,
@@ -104,6 +113,9 @@ static void builtin_complete_add2( const wchar_t *cmd,
}
}
/**
Silly function
*/
static void builtin_complete_add( array_list_t *cmd,
array_list_t *path,
const wchar_t *short_opt,
@@ -147,6 +159,9 @@ static void builtin_complete_add( array_list_t *cmd,
}
/**
Silly function
*/
static void builtin_complete_remove3( wchar_t *cmd,
int cmd_type,
wchar_t short_opt,
@@ -163,6 +178,9 @@ static void builtin_complete_remove3( wchar_t *cmd,
}
}
/**
Silly function
*/
static void builtin_complete_remove2( wchar_t *cmd,
int cmd_type,
const wchar_t *short_opt,
@@ -211,6 +229,9 @@ static void builtin_complete_remove2( wchar_t *cmd,
}
/**
Silly function
*/
static void builtin_complete_remove( array_list_t *cmd,
array_list_t *path,
const wchar_t *short_opt,
@@ -246,7 +267,12 @@ const wchar_t *builtin_complete_get_temporary_buffer()
return temporary_buffer;
}
int builtin_complete( wchar_t **argv )
/**
The complete builtin. Used for specifying programmable
tab-completions. Calls the functions in complete.c for any heavy
lifting. Defined in builtin_complete.c
*/
static int builtin_complete( wchar_t **argv )
{
int res=0;
int argc=0;
@@ -355,7 +381,7 @@ int builtin_complete( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"a:c:p:s:l:o:d:frxeun:C:h",
L"a:c:p:s:l:o:d:frxeun:C::h",
long_options,
&opt_index );
if( opt == -1 )
@@ -392,12 +418,20 @@ int builtin_complete( wchar_t **argv )
break;
case 'p':
al_push( &cmd, unescape( woptarg, 1));
break;
case 'c':
al_push( &cmd, unescape( woptarg, 1) );
{
wchar_t *a = unescape( woptarg, 1);
if( a )
{
al_push( (opt=='p'?&path:&cmd), a );
}
else
{
sb_printf( sb_err, L"%ls: Invalid token '%ls'\n", argv[0], woptarg );
res = 1;
}
break;
}
case 'd':
desc = woptarg;
@@ -455,14 +489,14 @@ int builtin_complete( wchar_t **argv )
{
if( condition && wcslen( condition ) )
{
if( parser_test( condition, 0 ) )
if( parser_test( condition, 0, 0 ) )
{
sb_printf( sb_err,
L"%ls: Condition '%ls' contained a syntax error\n",
argv[0],
condition );
parser_test( condition, 1 );
parser_test( condition, sb_err, argv[0] );
res = 1;
}
@@ -473,14 +507,14 @@ int builtin_complete( wchar_t **argv )
{
if( comp && wcslen( comp ) )
{
if( parser_test_args( comp, 0 ) )
if( parser_test_args( comp, 0, 0 ) )
{
sb_printf( sb_err,
L"%ls: Completion '%ls' contained a syntax error\n",
argv[0],
comp );
parser_test_args( comp, 1 );
parser_test_args( comp, sb_err, argv[0] );
res = 1;
}
@@ -514,7 +548,7 @@ int builtin_complete( wchar_t **argv )
sb_printf( sb_out, L"%ls\n", next );
}
al_foreach( &comp, (void (*)(const void *))&free );
al_foreach( &comp, &free );
al_destroy( &comp );
recursion_level--;
}
@@ -566,8 +600,8 @@ int builtin_complete( wchar_t **argv )
}
}
al_foreach( &cmd, (void (*)(const void *))&free );
al_foreach( &path, (void (*)(const void *))&free );
al_foreach( &cmd, &free );
al_foreach( &path, &free );
al_destroy( &cmd );
al_destroy( &path );

View File

@@ -1,32 +0,0 @@
/** \file builtin_help.h
Prototypes for functions for printing usage information of builtin commands. The
corresponding .c file is automatically generated by combining the
builtin_help.hdr file with doxygen output.
*/
#ifndef FISH_BUILTIN_HELP_H
#define FISH_BUILTIN_HELP_H
#include <wchar.h>
/**
Return the help text for the specified builtin command. Use
non-wide characters since wide characters have some issues with
string formating escape sequences sometimes.
\param cmd The command for which to obtain help text
*/
char *builtin_help_get( wchar_t *cmd );
/**
Initialize builtin help data
*/
void builtin_help_init();
/**
Destory builtin help data
*/
void builtin_help_destroy();
#endif

View File

@@ -14,24 +14,31 @@
#include "config.h"
#include "util.h"
#include "common.h"
#include "builtin_help.h"
#include "halloc_util.h"
/**
Hashtable storing the help text
*/
static hash_table_t tbl;
char *builtin_help_get( wchar_t *cmd )
static void builtin_help_init();
char *builtin_help_get( const wchar_t *cmd )
{
builtin_help_init();
return (char *)hash_get( &tbl, (void *)cmd );
}
void builtin_help_destroy()
{
hash_destroy( &tbl );
}
void builtin_help_init()
/**
Initialize help hash table. Don't invoke it manually,
it is called by builtin_help_get automatically.
*/
static void builtin_help_init()
{
static int is_help_init = 0;
if( is_help_init )
return;
is_help_init=1;
halloc_register_function( global_context, (void (*)(void *))&hash_destroy, &tbl );
hash_init( &tbl, &hash_wcs_func, &hash_wcs_cmp );

View File

@@ -24,7 +24,7 @@
#include "parser.h"
#include "common.h"
#include "wgetopt.h"
#include "translate.h"
/**
Print modes for the jobs builtin
@@ -158,7 +158,10 @@ static void builtin_jobs_print( job_t *j, int mode, int header )
int builtin_jobs( wchar_t **argv )
/**
The jobs builtin. Used fopr printing running jobs. Defined in builtin_jobs.c.
*/
static int builtin_jobs( wchar_t **argv )
{
int argc=0;
int found=0;

View File

@@ -24,7 +24,7 @@ Functions used for implementing the set builtin.
#include "wgetopt.h"
#include "proc.h"
#include "parser.h"
#include "translate.h"
/**
Error message for invalid path operations
@@ -159,6 +159,13 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
retcode=1;
break;
}
case ENV_INVALID:
{
sb_printf( sb_err, _(L"%ls: Unknown error"), L"set" );
retcode=1;
break;
}
}
sb_destroy( &sb );
@@ -172,12 +179,14 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
\param indexes the list to insert the new indexes into
\param src the source string to parse
\param name the name of the element. Return null if the name in \c src does not match this name
\param var_count the number of elements in the array to parse.
\return the number of indexes parsed, or -1 on error
\return the total number of indexes parsed, or -1 on error
*/
static int parse_index( array_list_t *indexes,
const wchar_t *src,
const wchar_t *name )
const wchar_t *name,
int var_count )
{
int len;
@@ -224,13 +233,20 @@ static int parse_index( array_list_t *indexes,
{
wchar_t *end;
long l_ind = wcstol(src, &end, 10);
int *ind;
if (end == src)
{
sb_printf(sb_err, _(L"%ls: Invalid index starting at '%ls'\n"), L"set", src);
return 0;
}
if( l_ind < 0 )
{
l_ind = var_count+l_ind+1;
}
int *ind = (int *) calloc(1, sizeof(int));
ind = (int *) calloc(1, sizeof(int));
*ind = (int) l_ind;
al_push(indexes, ind);
src = end;
@@ -248,8 +264,7 @@ static int parse_index( array_list_t *indexes,
indexes. The previous entries at the specidied position will be
free'd.
\return The number of elements in the list after the modifications
have been made
\return 0 if the operation was successfull, non-zero otherwise
*/
static int update_values( array_list_t *list,
array_list_t *indexes,
@@ -262,11 +277,16 @@ static int update_values( array_list_t *list,
{
int ind = *(int *) al_get(indexes, i) - 1;
void *new = (void *) al_get(values, i);
if( ind <= 0 )
{
return 1;
}
free((void *) al_get(list, ind));
al_set(list, ind, new != 0 ? wcsdup(new) : wcsdup(L""));
}
return al_get_count(list);
return 0;
}
@@ -362,7 +382,7 @@ static void print_variables(int include_values, int esc, int scope)
The set builtin. Creates, updates and erases environment variables
and environemnt variable arrays.
*/
int builtin_set( wchar_t **argv )
static int builtin_set( wchar_t **argv )
{
/**
@@ -563,13 +583,13 @@ int builtin_set( wchar_t **argv )
if( query )
{
/*
Query mode. Return the number variables that do not exist
Query mode. Return the number of variables that do not exist
out of the specified variables.
*/
int i;
for( i=woptind; i<argc; i++ )
{
if( !env_exist( argv[i] ) )
if( !env_exist( argv[i], scope ) )
{
retcode++;
}
@@ -608,10 +628,10 @@ int builtin_set( wchar_t **argv )
print_variables(0, 0, scope);
return 0;
}
if( !(dest = wcsdup(argv[woptind])))
{
die_mem();
DIE_MEM();
}
if( wcschr( dest, L'[' ) )
@@ -624,9 +644,17 @@ int builtin_set( wchar_t **argv )
{
free( dest );
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
}
if( slice && erase && (scope != ENV_USER) )
{
free( dest );
sb_printf( sb_err, _(L"%ls: Can not specify scope when erasing array slice\n"), argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
}
/*
set assignment can work in two modes, either using slices or
@@ -642,14 +670,19 @@ int builtin_set( wchar_t **argv )
int idx_count, val_count;
array_list_t values;
array_list_t indexes;
array_list_t result;
al_init(&values);
al_init(&indexes);
al_init(&result);
tokenize_variable_array( env_get(dest), &result );
for( ; woptind<argc; woptind++ )
{
if( !parse_index( &indexes, argv[woptind], dest ) )
if( !parse_index( &indexes, argv[woptind], dest, al_get_count( &result ) ) )
{
builtin_print_help( argv[0], sb_err );
retcode = 1;
break;
}
@@ -662,6 +695,7 @@ int builtin_set( wchar_t **argv )
if( val_count < idx_count )
{
sb_printf( sb_err, _(BUILTIN_SET_ARG_COUNT), argv[0] );
builtin_print_help( argv[0], sb_err );
retcode=1;
break;
}
@@ -679,10 +713,6 @@ int builtin_set( wchar_t **argv )
Slice indexes have been calculated, do the actual work
*/
array_list_t result;
al_init(&result);
tokenize_variable_array( env_get(dest), &result );
if( erase )
{
erase_values(&result, &indexes);
@@ -698,9 +728,14 @@ int builtin_set( wchar_t **argv )
al_push(&value, argv[woptind++]);
}
update_values( &result,
&indexes,
&value );
if( update_values( &result,
&indexes,
&value ) )
{
sb_printf( sb_err, L"%ls: ", argv[0] );
sb_printf( sb_err, ARRAY_BOUNDS_ERR );
sb_append( sb_err, L"\n" );
}
my_env_set(dest,
&result,
@@ -709,11 +744,12 @@ int builtin_set( wchar_t **argv )
al_destroy( &value );
}
al_foreach( &result, (void (*)(const void *))&free );
al_destroy( &result );
}
al_foreach( &indexes, (void (*)(const void *))&free );
al_foreach( &result, &free );
al_destroy( &result );
al_foreach( &indexes, &free );
al_destroy(&indexes);
al_destroy(&values);
@@ -733,11 +769,12 @@ int builtin_set( wchar_t **argv )
_(L"%ls: Values cannot be specfied with erase\n%ls\n"),
argv[0],
parser_current_line() );
builtin_print_help( argv[0], sb_err );
retcode=1;
}
else
{
env_remove( dest, ENV_USER );
retcode = env_remove( dest, scope );
}
}
else

View File

@@ -20,7 +20,7 @@ Functions used for implementing the ulimit builtin.
#include "builtin.h"
#include "common.h"
#include "wgetopt.h"
#include "translate.h"
/**
Struct describing a resource limit
@@ -257,7 +257,11 @@ static int set_all( int hard, int soft, rlim_t value )
return res;
}
int builtin_ulimit( wchar_t ** argv )
/**
The ulimit builtin, used for setting resource limits. Defined in
builtin_ulimit.c.
*/
static int builtin_ulimit( wchar_t ** argv )
{
int hard=0;
int soft=0;

292
common.c
View File

@@ -7,6 +7,12 @@ parts of fish.
#include "config.h"
#include <unistd.h>
#ifdef HAVE_STROPTS
#include <stropts.h>
#endif
#include <stdlib.h>
#include <termios.h>
#include <wchar.h>
@@ -61,6 +67,11 @@ parts of fish.
#include "wildcard.h"
#include "parser.h"
#include "util.c"
#include "halloc.c"
#include "halloc_util.c"
#include "fallback.c"
/**
The number of milliseconds to wait between polls when attempting to acquire
a lockfile
@@ -69,8 +80,6 @@ parts of fish.
struct termios shell_modes;
int error_max=1;
wchar_t ellipsis_char;
char *profile=0;
@@ -89,27 +98,13 @@ static struct winsize termsize;
*/
static string_buffer_t *setlocale_buff=0;
void common_destroy()
{
if( setlocale_buff )
{
sb_destroy( setlocale_buff );
free( setlocale_buff );
}
}
void common_init()
{
}
wchar_t **list_to_char_arr( array_list_t *l )
{
wchar_t ** res = malloc( sizeof(wchar_t *)*(al_get_count( l )+1) );
int i;
if( res == 0 )
{
die_mem();
DIE_MEM();
}
for( i=0; i<al_get_count( l ); i++ )
{
@@ -126,12 +121,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
wchar_t *buff = *b;
/*
This is a kludge: We block SIGCHLD while reading, since I can't
get getwc to perform reliably when signals are flying. Even when
watching for EINTR errors, bytes are lost.
*/
while( 1 )
{
/* Reallocate the buffer if necessary */
@@ -141,7 +130,7 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
buff = realloc( buff, sizeof(wchar_t)*new_len );
if( buff == 0 )
{
die_mem();
DIE_MEM();
}
else
{
@@ -213,7 +202,7 @@ wchar_t *str2wcs( const char *in )
if( !out )
{
die_mem();
DIE_MEM();
}
return str2wcs_internal( in, out );
@@ -225,8 +214,13 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out )
int in_pos=0;
int out_pos = 0;
mbstate_t state;
size_t len = strlen(in);
size_t len;
CHECK( in, 0 );
CHECK( out, 0 );
len = strlen(in);
memset( &state, 0, sizeof(state) );
while( in[in_pos] )
@@ -237,12 +231,12 @@ wchar_t *str2wcs_internal( const char *in, wchar_t *out )
{
case (size_t)(-2):
case (size_t)(-1):
{
out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
in_pos++;
memset( &state, 0, sizeof(state) );
break;
}
{
out[out_pos] = ENCODE_DIRECT_BASE + (unsigned char)in[in_pos];
in_pos++;
memset( &state, 0, sizeof(state) );
break;
}
case 0:
{
@@ -270,7 +264,7 @@ char *wcs2str( const wchar_t *in )
if( !out )
{
die_mem();
DIE_MEM();
}
return wcs2str_internal( in, out );
@@ -282,6 +276,10 @@ char *wcs2str_internal( const wchar_t *in, char *out )
int in_pos=0;
int out_pos = 0;
mbstate_t state;
CHECK( in, 0 );
CHECK( out, 0 );
memset( &state, 0, sizeof(state) );
while( in[in_pos] )
@@ -322,7 +320,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++ )
@@ -336,7 +334,7 @@ char **wcsv2strv( const wchar_t **in )
wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b )
{
return wcsdupcat2( a, b, 0 );
return wcsdupcat2( a, b, (void *)0 );
}
wchar_t *wcsdupcat2( const wchar_t *a, ... )
@@ -357,7 +355,7 @@ wchar_t *wcsdupcat2( const wchar_t *a, ... )
wchar_t *res = malloc( sizeof(wchar_t)*(len +1 ));
if( res == 0 )
{
die_mem();
DIE_MEM();
}
wcscpy( res, a );
@@ -383,7 +381,7 @@ wchar_t **strv2wcsv( const char **in )
wchar_t **res = malloc( sizeof( wchar_t *)*(count+1));
if( res == 0 )
{
die_mem();
DIE_MEM();
}
for( i=0; i<count; i++ )
@@ -408,6 +406,11 @@ wchar_t *wcsvarname( wchar_t *str )
return 0;
}
int wcsvarchr( wchar_t chr )
{
return ( (iswalnum(chr)) || (chr == L'_' ));
}
/**
The glibc version of wcswidth seems to hang on some strings. fish uses this replacement.
@@ -428,26 +431,28 @@ int my_wcswidth( const wchar_t *c )
return res;
}
const wchar_t *quote_end( const wchar_t *pos )
wchar_t *quote_end( const wchar_t *pos )
{
wchar_t c = *pos;
while( 1 )
{
pos++;
if( !*pos )
return 0;
if( *pos == L'\\')
{
pos++;
if( !*pos )
return 0;
}
else
{
if( *pos == c )
{
return pos;
return (wchar_t *)pos;
}
}
}
@@ -475,8 +480,7 @@ const wchar_t *wsetlocale(int category, const wchar_t *locale)
if( !setlocale_buff )
{
setlocale_buff = malloc( sizeof(string_buffer_t) );
sb_init( setlocale_buff);
setlocale_buff = sb_halloc( global_context);
}
sb_clear( setlocale_buff );
@@ -491,11 +495,7 @@ int contains_str( const wchar_t *a, ... )
va_list va;
int res = 0;
if( !a )
{
debug( 1, L"Warning: Called contains_str with null argument. This is a bug." );
return 0;
}
CHECK( a, 0 );
va_start( va, a );
while( (arg=va_arg(va, wchar_t *) )!= 0 )
@@ -524,24 +524,14 @@ int read_blocked(int fd, void *buf, size_t count)
return res;
}
void die_mem()
{
/*
Do not translate this message, and do not send it through the
usual channels. This increases the odds that the message gets
through correctly, even if we are out of memory.
*/
fwprintf( stderr, L"Out of memory, shutting down fish.\n" );
exit(1);
}
void debug( int level, const wchar_t *msg, ... )
{
va_list va;
string_buffer_t sb;
string_buffer_t sb2;
CHECK( msg, );
if( level > debug_level )
return;
@@ -568,6 +558,9 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
int tok_width = 0;
int screen_width = common_get_width();
CHECK( msg, );
CHECK( buff, );
if( screen_width )
{
start = pos = msg;
@@ -636,8 +629,10 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
Break on end of string
*/
if( !*pos )
{
break;
}
start=pos;
}
}
@@ -651,10 +646,20 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
wchar_t *escape( const wchar_t *in,
int escape_all )
{
wchar_t *out = malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1));
wchar_t *pos=out;
wchar_t *out;
wchar_t *pos;
if( !in )
{
debug( 0, L"%s called with null input", __func__ );
exit(1);
}
out = malloc( sizeof(wchar_t)*(wcslen(in)*4 + 1));
pos = out;
if( !out )
die_mem();
DIE_MEM();
while( *in != 0 )
{
@@ -678,74 +683,80 @@ wchar_t *escape( const wchar_t *in,
else
{
switch( *in )
{
case L'\t':
*(pos++) = L'\\';
*(pos++) = L't';
break;
switch( *in )
{
case L'\t':
*(pos++) = L'\\';
*(pos++) = L't';
break;
case L'\n':
*(pos++) = L'\\';
*(pos++) = L'n';
break;
case L'\n':
*(pos++) = L'\\';
*(pos++) = L'n';
break;
case L'\b':
*(pos++) = L'\\';
*(pos++) = L'b';
break;
case L'\b':
*(pos++) = L'\\';
*(pos++) = L'b';
break;
case L'\r':
*(pos++) = L'\\';
*(pos++) = L'r';
break;
case L'\r':
*(pos++) = L'\\';
*(pos++) = L'r';
break;
case L'\e':
*(pos++) = L'\\';
*(pos++) = L'e';
break;
case L'\e':
*(pos++) = L'\\';
*(pos++) = L'e';
break;
case L'\\':
case L'&':
case L'$':
case L' ':
case L'#':
case L'^':
case L'<':
case L'>':
case L'(':
case L')':
case L'[':
case L']':
case L'{':
case L'}':
case L'?':
case L'*':
case L'|':
case L';':
case L':':
case L'\'':
case L'"':
case L'%':
case L'~':
if( escape_all )
*pos++ = L'\\';
*pos++ = *in;
break;
default:
if( *in < 32 )
case L'\\':
case L'&':
case L'$':
case L' ':
case L'#':
case L'^':
case L'<':
case L'>':
case L'(':
case L')':
case L'[':
case L']':
case L'{':
case L'}':
case L'?':
case L'*':
case L'|':
case L';':
case L':':
case L'\'':
case L'"':
case L'%':
case L'~':
{
int tmp = (*in)%16;
*pos++ = L'\\';
*pos++ = L'x';
*pos++ = ((*in>15)? L'1' : L'0');
*pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
}
else
if( escape_all )
*pos++ = L'\\';
*pos++ = *in;
break;
}
break;
}
default:
{
if( *in < 32 )
{
int tmp = (*in)%16;
*pos++ = L'\\';
*pos++ = L'x';
*pos++ = ((*in>15)? L'1' : L'0');
*pos++ = tmp > 9? L'a'+(tmp-10):L'0'+tmp;
}
else
{
*pos++ = *in;
}
break;
}
}
}
in++;
@@ -759,13 +770,19 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
{
int mode = 0;
int in_pos, out_pos, len = wcslen( orig );
int in_pos, out_pos, len;
int c;
int bracket_count=0;
wchar_t prev=0;
wchar_t *in = wcsdup(orig);
wchar_t *in;
CHECK( orig, 0 );
len = wcslen( orig );
in = wcsdup( orig );
if( !in )
die_mem();
DIE_MEM();
for( in_pos=0, out_pos=0;
in_pos<len;
@@ -1273,13 +1290,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;
}
@@ -1306,6 +1323,9 @@ int acquire_lock_file( const char *lockfile, const int timeout, int force )
debug( 1, L"acquire_lock_file: open: %s", strerror( errno ) );
goto done;
}
/*
Don't need to check exit status of close on read-only file descriptors
*/
close( fd );
if( stat( linkfile, &statbuf ) != 0 )
{
@@ -1414,7 +1434,7 @@ void tokenize_variable_array( const wchar_t *val, array_list_t *out )
if( !cpy )
{
die_mem();
DIE_MEM();
}
for( start=pos=cpy; *pos; pos++ )

View File

@@ -51,11 +51,6 @@ extern struct termios shell_modes;
*/
extern wchar_t ellipsis_char;
/**
The maximum number of charset convertion errors to report
*/
extern int error_max;
/**
The verbosity of fish
*/
@@ -72,6 +67,45 @@ extern char *profile;
*/
extern wchar_t *program_name;
/**
This macro is used to check that an input argument is not null. It
is a bit lika a non-fatal form of assert. Instead of exit-ing on
failiure, the current function is ended at once. The second
parameter is the exit status of the current function on failiure.
*/
#define CHECK( arg, retval ) \
if( !(arg) ) \
{ \
debug( 1, \
L"function %s called with null value for argument %s. " \
L"This is a bug. " \
L"If you can reproduce it, please send a bug report to %s.", \
__func__, \
#arg, \
PACKAGE_BUGREPORT ); \
return retval; \
} \
/**
Exit program at once, leaving an error message about running out of memory
*/
#define DIE_MEM() \
{ \
fwprintf( stderr, L"fish: Out of memory on line %d of file %s, shutting down fish\n", __LINE__, __FILE__ ); \
exit(1); \
} \
/**
Shorthand for wgettext call
*/
#define _(wstr) wgettext(wstr)
/**
Noop, used to tell xgettext that a string should be translated, even though it is not directly sent to wgettext.
*/
#define N_(wstr) wstr
/**
Take an array_list_t containing wide strings and converts them to a
single null-terminated wchar_t **. The array is allocated using
@@ -95,24 +129,47 @@ 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 an array_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
This function encodes illegal character sequences in a reversible
way using the private use area.
*/
wchar_t *str2wcs( const char *in );
/**
Converts the narrow character string \c in into it's wide
equivalent, stored in \c out. \c out must have enough space to fit
the entire string.
This function encodes illegal character sequences in a reversible
way using the private use area.
*/
wchar_t *str2wcs_internal( const char *in, wchar_t *out );
/**
Returns a newly allocated multibyte character string equivalent of
the specified wide character string
This function decodes illegal character sequences in a reversible
way using the private use area.
*/
char *wcs2str( const wchar_t *in );
/**
Converts the wide character string \c in into it's narrow
equivalent, stored in \c out. \c out must have enough space to fit
the entire string.
This function decodes illegal character sequences in a reversible
way using the private use area.
*/
char *wcs2str_internal( const wchar_t *in, char *out );
/**
@@ -151,6 +208,14 @@ wchar_t *wcsdupcat2( const wchar_t *a, ... );
wchar_t *wcsvarname( wchar_t *str );
/**
Test if the given string is valid in a variable name
\return 1 if this is a valid name, 0 otherwise
*/
int wcsvarchr( wchar_t chr );
/**
A wcswidth workalike. Fish uses this since the regular wcswidth seems flaky.
@@ -164,7 +229,7 @@ int my_wcswidth( const wchar_t *c );
\param in the position of the opening quote
*/
const wchar_t *quote_end( const wchar_t *in );
wchar_t *quote_end( const wchar_t *in );
/**
A call to this function will reset the error counter. Some
@@ -199,20 +264,6 @@ int contains_str( const wchar_t *needle, ... );
*/
int read_blocked(int fd, void *buf, size_t count);
/**
Exit program at once, leaving an error message about running out of memory
*/
void die_mem();
/**
Create global_context using halloc
*/
void common_init();
/**
Free global_context using halloc_free
*/
void common_destroy();
/**
Issue a debug message with printf-style string formating and

View File

@@ -39,8 +39,9 @@
#include "reader.h"
#include "history.h"
#include "intern.h"
#include "translate.h"
#include "parse_util.h"
#include "halloc.h"
#include "halloc_util.h"
#include "wutil.h"
@@ -152,6 +153,14 @@
*/
#define CC_FALSE L"false"
/**
The special cased translation macro for completions. The empty
string needs to be special cased, since it can occur, and should
not be translated. (Gettext returns the version information as the
response)
*/
#define C_(wstr) ((wstr==L"")?L"":wgettext(wstr))
/**
Struct describing a completion option entry.
@@ -225,6 +234,50 @@ static hash_table_t *condition_cache=0;
static string_buffer_t *get_desc_buff=0;
static void complete_free_entry( complete_entry *c );
static void clear_hash_entry( void *key, void *data );
/**
Destroys various structures used for tab-completion and free()s the memory used by them.
*/
static void complete_destroy()
{
complete_entry *i=first_entry, *prev;
while( i )
{
prev = i;
i=i->next;
complete_free_entry( prev );
}
first_entry = 0;
if( suffix_hash )
{
hash_foreach( suffix_hash, &clear_hash_entry );
hash_destroy( suffix_hash );
free( suffix_hash );
suffix_hash=0;
}
parse_util_load_reset( L"fish_complete_path", 0 );
}
/**
Make sure complete_destroy is called on exit
*/
static void complete_init()
{
static int is_init = 0;
if( !is_init )
{
is_init = 1;
halloc_register_function_void( global_context, &complete_destroy );
}
}
/**
This command clears the cache of condition tests created by \c condition_test().
*/
@@ -259,7 +312,7 @@ static int condition_test( const wchar_t *condition )
condition_cache = malloc( sizeof( hash_table_t ) );
if( !condition_cache )
{
die_mem();
DIE_MEM();
}
@@ -315,40 +368,12 @@ static void complete_free_entry( complete_entry *c )
/**
Free hash key and hash value
*/
static void clear_hash_entry( const void *key, const void *data )
static void clear_hash_entry( void *key, void *data )
{
free( (void *)key );
free( (void *)data );
}
void complete_init()
{
}
void complete_destroy()
{
complete_entry *i=first_entry, *prev;
while( i )
{
prev = i;
i=i->next;
complete_free_entry( prev );
}
first_entry = 0;
if( suffix_hash )
{
hash_foreach( suffix_hash, &clear_hash_entry );
hash_destroy( suffix_hash );
free( suffix_hash );
suffix_hash=0;
}
parse_util_load_reset(L"fish_complete_path");
}
/**
Search for an exactly matching completion entry
*/
@@ -377,15 +402,20 @@ void complete_add( const wchar_t *cmd,
const wchar_t *comp,
const wchar_t *desc )
{
complete_entry *c =
complete_find_exact_entry( cmd, cmd_type );
complete_entry *c;
complete_entry_opt *opt;
CHECK( cmd, );
complete_init();
c = complete_find_exact_entry( cmd, cmd_type );
if( c == 0 )
{
if( !(c = malloc( sizeof(complete_entry) )))
{
die_mem();
DIE_MEM();
}
c->next = first_entry;
@@ -400,7 +430,7 @@ void complete_add( const wchar_t *cmd,
if( !(opt = malloc( sizeof( complete_entry_opt ) )))
{
die_mem();
DIE_MEM();
}
opt->next = c->first_option;
@@ -445,6 +475,8 @@ void complete_remove( const wchar_t *cmd,
{
complete_entry *e, *eprev=0, *enext=0;
CHECK( cmd, );
for( e = first_entry; e; e=enext )
{
enext=e->next;
@@ -536,18 +568,19 @@ void complete_remove( const wchar_t *cmd,
}
/**
Find the full path and commandname from a command string. the
result of \c pathp must be freed by the caller, the result of \c
cmdp must not be freed by the caller.
Find the full path and commandname from a command string. Both
pointers are allocated using halloc and will be free'd when\c
context is halloc_free'd.
*/
static void parse_cmd_string( const wchar_t *str,
static void parse_cmd_string( void *context,
const wchar_t *str,
wchar_t **pathp,
wchar_t **cmdp )
{
wchar_t *cmd, *path;
/* Get the path of the command */
path = get_filename( str );
path = parser_get_filename( context, str );
if( path == 0 )
{
/**
@@ -590,6 +623,11 @@ int complete_is_valid_option( const wchar_t *str,
int gnu_opt_len=0;
char *short_validated;
void *context;
CHECK( str, 0 );
CHECK( opt, 0 );
/*
Check some generic things like -- and - options.
*/
@@ -625,11 +663,15 @@ int complete_is_valid_option( const wchar_t *str,
return 0;
}
if( !(short_validated = malloc( wcslen( opt ) )))
context = halloc( 0, 0 );
if( !(short_validated = halloc( context, wcslen( opt ) )))
{
die_mem();
DIE_MEM();
}
memset( short_validated, 0, wcslen( opt ) );
hash_init( &gnu_match_hash,
@@ -650,7 +692,7 @@ int complete_is_valid_option( const wchar_t *str,
}
}
parse_cmd_string( str, &path, &cmd );
parse_cmd_string( context, str, &path, &cmd );
/*
Make sure completions are loaded for the specified command
@@ -749,7 +791,6 @@ int complete_is_valid_option( const wchar_t *str,
}
}
}
free( path );
if( authorative )
{
@@ -803,8 +844,9 @@ int complete_is_valid_option( const wchar_t *str,
}
hash_destroy( &gnu_match_hash );
free( short_validated );
halloc_free( context );
return (authorative && found_match)?opt_found:1;
}
@@ -836,7 +878,7 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
{
suffix_hash = malloc( sizeof( hash_table_t) );
if( !suffix_hash )
die_mem();
DIE_MEM();
hash_init( suffix_hash, &hash_wcs_func, &hash_wcs_cmp );
}
@@ -883,7 +925,7 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
}
}
al_foreach( &l, (void (*)(const void *))&free );
al_foreach( &l, &free );
al_destroy( &l );
}
@@ -907,8 +949,11 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
{
struct stat buf;
CHECK( filename, 0 );
if( !get_desc_buff )
{
complete_init();
get_desc_buff = sb_halloc( global_context);
}
else
@@ -1182,11 +1227,14 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
hash_destroy( &lookup );
al_foreach( &list,
(void(*)(const void *))&free );
&free );
al_destroy( &list );
free( lookup_cmd );
}
/**
Returns a description for the specified function
*/
static const wchar_t *complete_function_desc( const wchar_t *fn )
{
const wchar_t *res = function_get_desc( fn );
@@ -1413,7 +1461,7 @@ static void complete_from_args( const wchar_t *str,
copy_strings_with_prefix( comp_out, str, desc, 0, &possible_comp );
al_foreach( &possible_comp, (void (*)(const void *))&free );
al_foreach( &possible_comp, &free );
al_destroy( &possible_comp );
}
@@ -1507,6 +1555,14 @@ static int short_ok( wchar_t *arg,
return 1;
}
/**
This is an event handler triggered when the definition of a
specifiec function is changed. It automatcally removes the
specified function.
This is to make sure that the function disappears if the file is
removed or if ti contains a syntax error.
*/
static void complete_load_handler( const wchar_t *cmd )
{
complete_remove( cmd, COMMAND, 0, 0 );
@@ -1514,7 +1570,10 @@ static void complete_load_handler( const wchar_t *cmd )
void complete_load( const wchar_t *name, int reload )
{
parse_util_load( name, L"fish_complete_path", &complete_load_handler, reload );
parse_util_load( name,
L"fish_complete_path",
&complete_load_handler,
reload );
}
/**
@@ -1534,13 +1593,14 @@ static int complete_param( wchar_t *cmd_orig,
wchar_t *cmd, *path;
int use_common=1, use_files=1;
parse_cmd_string( cmd_orig, &path, &cmd );
void *context = halloc( 0, 0 );
parse_cmd_string( context, cmd_orig, &path, &cmd );
complete_load( cmd, 1 );
al_init( &matches );
for( i=first_entry; i; i=i->next )
{
wchar_t *match = i->cmd_type?path:cmd;
@@ -1560,7 +1620,7 @@ static int complete_param( wchar_t *cmd_orig,
{
use_common &= ((o->result_mode & NO_COMMON )==0);
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( arg, o->comp, _(o->desc), comp_out );
complete_from_args( arg, o->comp, C_(o->desc), comp_out );
}
}
@@ -1584,7 +1644,7 @@ static int complete_param( wchar_t *cmd_orig,
found_old = 1;
use_common &= ((o->result_mode & NO_COMMON )==0);
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( str, o->comp, _(o->desc), comp_out );
complete_from_args( str, o->comp, C_(o->desc), comp_out );
}
}
}
@@ -1610,7 +1670,7 @@ static int complete_param( wchar_t *cmd_orig,
{
use_common &= ((o->result_mode & NO_COMMON )==0);
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( str, o->comp, _(o->desc), comp_out );
complete_from_args( str, o->comp, C_(o->desc), comp_out );
}
}
@@ -1634,7 +1694,7 @@ static int complete_param( wchar_t *cmd_orig,
if( (o->short_opt == L'\0' ) && (o->long_opt[0]==L'\0'))
{
use_files &= ((o->result_mode & NO_FILES )==0);
complete_from_args( str, o->comp, _(o->desc), comp_out );
complete_from_args( str, o->comp, C_(o->desc), comp_out );
}
if( wcslen(str) > 0 )
@@ -1645,11 +1705,11 @@ static int complete_param( wchar_t *cmd_orig,
if( o->short_opt != L'\0' &&
short_ok( str, o->short_opt, i->short_opt_str ) )
{
const wchar_t *desc = _(o->desc );
const wchar_t *desc = C_(o->desc );
wchar_t *next_opt =
malloc( sizeof(wchar_t)*(3 + wcslen(desc)));
if( !next_opt )
die_mem();
DIE_MEM();
next_opt[0]=o->short_opt;
next_opt[1]=COMPLETE_SEP;
@@ -1663,11 +1723,10 @@ static int complete_param( wchar_t *cmd_orig,
*/
if( o->long_opt[0] != L'\0' )
{
string_buffer_t whole_opt;
sb_init( &whole_opt );
sb_append2( &whole_opt, o->old_mode?L"-":L"--", o->long_opt, (void *)0 );
string_buffer_t *whole_opt = sb_halloc( context );
sb_append2( whole_opt, o->old_mode?L"-":L"--", o->long_opt, (void *)0 );
if( wcsncmp( str, (wchar_t *)whole_opt.buff, wcslen(str) )==0)
if( wcsncmp( str, (wchar_t *)whole_opt->buff, wcslen(str) )==0)
{
/*
If the option requires arguments, add
@@ -1680,29 +1739,30 @@ static int complete_param( wchar_t *cmd_orig,
if( o->old_mode || !(o->result_mode & NO_COMMON ) )
{
al_push( comp_out,
wcsdupcat2( &((wchar_t *)whole_opt.buff)[wcslen(str)],
wcsdupcat2( &((wchar_t *)whole_opt->buff)[wcslen(str)],
COMPLETE_SEP_STR,
_(o->desc),
C_(o->desc),
(void *)0) );
}
if( !o->old_mode && ( wcslen(o->comp) || (o->result_mode & NO_COMMON ) ) )
{
al_push( comp_out,
wcsdupcat2( &((wchar_t *)whole_opt.buff)[wcslen(str)],
wcsdupcat2( &((wchar_t *)whole_opt->buff)[wcslen(str)],
L"=",
COMPLETE_SEP_STR,
_(o->desc),
C_(o->desc),
(void *)0) );
}
}
sb_destroy( &whole_opt );
}
}
}
}
}
free( path );
halloc_free( context );
return use_files;
}
@@ -1723,12 +1783,12 @@ static void complete_param_expand( wchar_t *str,
{
comp_str = str;
}
/*
debug( 3,
L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );",
comp_str,
do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
*/
expand_string( 0,
wcsdup(comp_str),
comp_out,
@@ -1913,20 +1973,23 @@ static int try_complete_user( const wchar_t *cmd,
void complete( const wchar_t *cmd,
array_list_t *comp )
{
const wchar_t *begin, *end, *prev_begin, *prev_end;
wchar_t *begin, *end, *prev_begin, *prev_end;
wchar_t *buff;
tokenizer tok;
wchar_t *current_token=0, *current_command=0, *prev_token=0;
int on_command=0;
int pos;
int old_error_max = error_max;
int done=0;
int cursor_pos;
int cursor_pos = wcslen(cmd );
CHECK( cmd, );
CHECK( comp, );
error_max=0;
complete_init();
// debug( 1, L"Complete '%ls'", cmd );
cursor_pos = wcslen(cmd );
/**
If we are completing a variable name or a tilde expansion user
@@ -2024,7 +2087,7 @@ void complete( const wchar_t *cmd,
prev_token = prev_begin ? wcsndup( prev_begin, prev_end - prev_begin ): wcsdup(L"");
// fwprintf( stderr, L"on_command: %d, %ls %ls\n", on_command, current_compmand, current_token );
// debug( 0, L"on_command: %d, %ls %ls\n", on_command, current_command, current_token );
if( !had_cmd )
{
on_command=1;
@@ -2076,7 +2139,6 @@ void complete( const wchar_t *cmd,
free( current_command );
free( prev_token );
error_max=old_error_max;
condition_cache_clear();
}
@@ -2141,7 +2203,7 @@ void complete_print( string_buffer_t *out )
append_switch( out,
L"description",
_(o->desc) );
C_(o->desc) );
append_switch( out,
L"arguments",

View File

@@ -1,10 +1,12 @@
/** \file complete.h
Prototypes for functions related to tab-completion.
These functions are used for storing and retrieving tab-completion data, as well as for performing tab-completion.
These functions are used for storing and retrieving tab-completion
data, as well as for performing tab-completion.
*/
#ifndef FISH_COMPLETE_H
/**
Header guard
*/
@@ -14,41 +16,56 @@
#include "util.h"
/** Use all completions */
/**
Use all completions
*/
#define SHARED 0
/** Do not use file completion */
/**
Do not use file completion
*/
#define NO_FILES 1
/** Require a parameter after completion */
/**
Require a parameter after completion
*/
#define NO_COMMON 2
/** Only use the argument list specifies with completion after option. This is the same as (NO_FILES & NO_COMMON) */
/**
Only use the argument list specifies with completion after
option. This is the same as (NO_FILES & NO_COMMON)
*/
#define EXCLUSIVE 3
/** Command is a path */
/**
Command is a path
*/
#define PATH 1
/** Command is not a path */
/**
Command is not a path
*/
#define COMMAND 0
/** Separateor between completion and description*/
/**
Separator between completion and description
*/
#define COMPLETE_SEP L'\004'
/** Separateor between completion and description*/
/**
Separator between completion and description
*/
#define COMPLETE_SEP_STR L"\004"
/**
Separator between completion items in fish_pager. This is used for
completion grouping, e.g. when putting completions with the same
descriptions on the same line.
*/
#define COMPLETE_ITEM_SEP L'\uf500'
/**
Character that separates the completion and description on programmable completions
Character that separates the completion and description on
programmable completions
*/
#define PROG_COMPLETE_SEP L'\t'
/**
Initializes various structures used for tab-completion.
*/
void complete_init();
/**
Destroys various structures used for tab-completion and free()s the memory used by them.
*/
void complete_destroy();
/**

View File

@@ -1,5 +1,5 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(fish,1.21.8,fish-users@lists.sf.net)
AC_INIT(fish,1.21.10,fish-users@lists.sf.net)
# If needed, run autoconf to regenerate the configure file
AC_MSG_CHECKING([if autoconf needs to be run])
@@ -82,15 +82,6 @@ AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
# Check for doxygen, which is needed to build
AC_CHECK_PROG( has_doxygen, [doxygen], "true")
if ! test "$has_doxygen" = "true"; then
AC_MSG_ERROR( [cannot find the Doxygen program in your path.
This program is needed to build fish.
Please install it and try again.])
fi
# Check for seq command. If missing, make sure fallback shellscript
# implementation is installed
AC_CHECK_PROG( SEQ_FALLBACK, seq, [ ], [seq])
@@ -221,17 +212,11 @@ fi
# it can make sure the fish installation directory is in the path
# during startup.
if [[ "$prefix" = NONE ]]; then
AC_DEFINE_UNQUOTED( [PREFIX], L"/usr/local", [Installation directory])
AC_SUBST( PREFIX, /usr/local)
export prefix=/usr/local
AC_SUBST( prefix, /usr/local)
else
AC_DEFINE_UNQUOTED( [PREFIX], L"$prefix", [Installation directory])
AC_SUBST( PREFIX, [$prefix])
AC_SUBST( prefix, [$prefix])
fi
AC_DEFINE_UNQUOTED( SYSCONFDIR, [L"$(eval echo $sysconfdir)"], [System configuration directory] )
AC_DEFINE_UNQUOTED( DATADIR, [L"$(eval echo $datadir)"], [System configuration directory] )
AC_SUBST( SYSCONFDIR, ["$(eval echo $sysconfdir)"] )
AC_SUBST( DATADIR, ["$(eval echo $datadir)"] )
# Set up the directory where the documentation files should be
@@ -239,16 +224,14 @@ AC_SUBST( DATADIR, ["$(eval echo $datadir)"] )
AC_ARG_VAR( [docdir], [Documentation direcotry] )
if test -z $docdir; then
AC_SUBST(docdir,[$datadir/doc/fish])
AC_SUBST(docdir, [$datadir/doc/fish] )
else
AC_SUBST(docdir, [$docdir])
fi
AC_DEFINE_UNQUOTED( DOCDIR, [L"$(eval echo $docdir)"], [Documentation directory] )
# Set up locale directory. This is where the .po files will be
# installed.
AC_DEFINE_UNQUOTED( [LOCALEDIR], "$(eval echo $datadir)/locale", [Locale directory])
AC_SUBST( [LOCALEDIR], [$datadir/locale])
AC_SUBST( [localedir], [$datadir/locale])
# See if Linux procfs is present. This is used to get extra
# information about running processes.
@@ -261,22 +244,25 @@ AC_DEFINE([HAVE_TRANSLATE_H], [1],
[Define to 1 if the wgettext function should be used for translating strings.])
# Check for presense of various libraries
AC_SEARCH_LIBS( gettext, intl, AC_SUBST( HAVE_GETTEXT, [1] ), AC_SUBST( HAVE_GETTEXT, [0] ) )
AC_SEARCH_LIBS( gettext, intl,,)
AC_SEARCH_LIBS( connect, socket, , [AC_MSG_ERROR([Cannot find the socket library, needed to build this package.] )] )
AC_SEARCH_LIBS( nanosleep, rt, , [AC_MSG_ERROR([Cannot find the rt library, needed to build this package.] )] )
AC_SEARCH_LIBS( setupterm, [ncurses curses], , [AC_MSG_ERROR([Could not find a curses implementation, needed to build fish])] )
# Check for presense of various header files
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h term.h ncurses/term.h libintl.h ncurses.h curses.h])
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h term.h ncurses/term.h libintl.h ncurses.h curses.h stropts.h])
AC_CHECK_HEADER([regex.h],
[AC_DEFINE([HAVE_REGEX_H], [1], [Define to 1 if you have the <regex.h> header file.])],
[AC_MSG_ERROR([Could not find the header regex.h, needed to build fish])])
# Check for presense of various functions
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp gettext fwprintf )
AC_CHECK_FUNCS( gettext wcsdup wcsndup wcslen wcscasecmp wcsncasecmp fwprintf )
AC_CHECK_FUNCS( futimes wcwidth wcswidth getopt_long wcstok fputwc fgetwc )
AC_CHECK_FUNCS( wcstol dcgettext wcslcat wcslcpy )
AC_CHECK_FUNCS( wcstol dcgettext wcslcat wcslcpy lrand48_r)
# The Makefile also needs to know if we have gettext, so it knows if the translations should be installed.
AC_CHECK_FUNC( gettext, AC_SUBST( HAVE_GETTEXT, 1 ), AC_SUBST( HAVE_GETTEXT, 0 ) )
# Here follows a list of small programs used to test for various
# features that Autoconf doesn't tell us about
@@ -357,8 +343,8 @@ case $target_os in
esac
# Tell the world what we know
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile etc/fish etc/fish_interactive.fish share/fish seq])
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile seq])
AC_OUTPUT
echo "fish is now configured."
echo "Use 'make' and 'make install' to built and install fish."
echo "Use 'make' and 'make install' to build and install fish."

View File

@@ -2,16 +2,23 @@
\section and and - Conditionally execute a command
\subsection and-synopsis Synopsis
<tt>COMMAND1; and COMMAND2</tt>
<tt>COMMAND1; and COMMAND2</tt>
\subsection and-description Description
The \c and builtin is used to execute a command if the current exit status (as set by the last previous command) is zero
The \c and builtin is used to execute a command if the current exit
status (as set by the last previous command) is zero
The and command does not change the current exit status.
\subsection and-example Example
The following code runs the \c make command to build a program, and if it succeeds, it runs <tt>make install</tt>, which installs the program.
The following code runs the \c make command to build a program, if the
build succceds, the program is installed. If either step fails,
<tt>make clean</tt> is run, which removes the files created by the
build process
<pre>
make; and make install
make; and make install; or make clean
</pre>

View File

@@ -7,11 +7,14 @@
\subsection begin-description Description
The \c begin builtin is used to create a new block of code. The block
is unconditionally executed. Begin is equivalent to <tt>if
true</tt>. The begin command is used to group any number of commands
into a block. The reason for this is usually either to introduce a new
variable scope or to redirect the input to output of this set of
commands as a group.
is unconditionally executed. <code>begin; ...; end</tt> is equivalent
to <tt>if true; ...; end</tt>. The begin command is used to group any
number of commands into a block. The reason for doing so is usually
either to introduce a new variable scope, to redirect the input or
output of a set of commands as a group, or to specify precedence when
using the conditional commands like \c and.
The \c begin command does not change the current exit status.
\subsection begin-example Example
@@ -28,3 +31,17 @@ end
# the block and was killed
echo $PIRATE
</pre>
In the following code, all output is redirected to the file out.html.
<pre>
begin
echo $xml_header
echo $html_header
if test -e $file
...
end
...
end &gt; out.html
</pre>

View File

@@ -6,7 +6,7 @@
\subsection count-description Description
<tt>count</tt> returns the number of arguments that were passed to
<tt>count</tt> prints the number of arguments that were passed to
it. This is usually used to find out how many elements an environment
variable array contains, but this is not the only potential usage for
the count command.
@@ -18,6 +18,9 @@ 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 expansion, it will be passed on to the count program.
Count exits with a non-zero exit status if no arguments where passed
to it, with zero otherwise.
\subsection count-example Example
<pre>

View File

@@ -261,20 +261,36 @@ the example above, these are simply passed on to the ls command. For
more information on functions, see the documentation for the <a
href='builtin.html#function'>function</a> builtin.
Functions can be defined on the commandline or in a configuration
file, but they can also be automatically loaded. Fish automatically
searches through any directories in the array variable
\$fish_function_path, and any functions defined are automatically
loaded when needed. A function definition file must have a filename
consisting of the name of the function plus the suffix '.fish'.
\subsubsection Autoloading functions
The default value for \$fish_function_path is ~/.fish.d/functions,
/etc/fish.d/functions /usr/share/fish/functions. The exact path to the
last two of these may be slighly different depending on what install
path prefix was chosen at configuration time. The rationale behind
having three different directories is that the first one is for user
specific functions, the second one is for system-wide additional
functions and the last one is for default fish functions.
Functions can be defined on the commandline or in a configuration
file, but they can also be automatically loaded. This method of
defining functions has several advantages. An autoloaded function
becomes avaialble automatically to all running shells, if the function
definition is changed, all running shells will automatically reload
the altered version, startup time and memory usage is improved, etc.
Fish automatically searches through any directories in the array
variable \$fish_function_path, and any functions defined are
automatically loaded when needed. A function definition file must have
a filename consisting of the name of the function plus the suffix
'.fish'.
The default value for \$fish_function_path is \c ~/.fish.d/functions
\c /etc/fish.d/functions \c /usr/share/fish/functions. The exact path
to the last two of these may be slighly different depending on what
install path prefix was chosen at configuration time. The rationale
behind having three different directories is that the first one is for
user specific functions, the second one is for system-wide additional
functions and the last one is for default fish functions. The path
list is searched in order, meaning that by default, the system
administrator can override default fish functions, and the user can
override functions defined by the system administrator.
It is very important that function definition files only contain the
definition for the specified function and nothing else, otherwise it
is possible that autoloading a function files requires that the
function already be loaded, i.e. a circular dependency.
\subsection syntax-words Some common words
@@ -541,7 +557,6 @@ a string is expanded into a process id. The following expansions are
performed:
- If the string is the entire word \c self, the shells pid is the result
- When inside a command substitution, if the string is the entire word \c caller, the job number (not the pid) of the job the created the command substitution is the result
- Otherwise, if the string is the id of a job, the result is the process
group id of the job.
- Otherwise, if any child processes match the specified string, their
@@ -620,8 +635,8 @@ Variables can be explicitly set to be universal with the \c -U or \c
local with the \c -l or \c --local switch. The scoping rules when
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 explicitly set to either universal, global or local, that setting will be honored. If a variable of the same name exists in a different scope, that variable will not be changed.
-# 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 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.
@@ -697,9 +712,9 @@ Variables can be explicitly set to be exported with the \c -x or \c
switch. The exporting rules when creating or updating a variable are
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 before been defined, the variable will not be exported
-# 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 before been defined, the variable will not be exported.
\subsection variables-arrays Arrays
@@ -747,6 +762,10 @@ set -e smurf[1]
echo $smurf
</pre>
If you specify a negative index when expanding or assigning to an
array variable, the index will be calculated from the end of the
array. For example, the index -1 means the last index of an array.
\subsection variables-special Special variables
The user can change the settings of \c fish by changing the values of
@@ -783,7 +802,7 @@ the string __FISH or __fish. These should be ignored by the user.
The colors used by fish for syntax highlighting can be configured by
changing the values of a various variables. The value of these
variables can be one of the colors accepted by the <a
href='commands.html#set_color'>\c set_color</a> command. The \c --bold
href='commands.html#set_color'>set_color</a> command. The \c --bold
or \c -b switches accepted by \c set_color are also accepted.
The following variables are available to change the highligting colors
@@ -815,7 +834,7 @@ Example:
To make errors highlighted and red, use:
<code>set fish_color_error red --bold</code>D
<code>set fish_color_error red --bold</code>
\subsection variables-locale Locale variables
@@ -839,7 +858,7 @@ Many other shells have a large library of builtin commands. Most of
these commands are also available as standalone commands, but have
been implemented in the shell anyway for whatever reason. To avoid
code duplication, and to avoid the confusion of subtly differing
versions of the same command, \c fish only implementing builtins for
versions of the same command, \c fish only implements builtins for
actions which cannot be performed by a regular command.
\section bundle Commands bundled with fish
@@ -1232,7 +1251,7 @@ href='fish-users@lists.sf.net'>fish-users@lists.sf.net</a>.
- Complete vi-mode key bindings
- More completions (for example xterm, vim,
konsole, gnome-terminal, dcop, cron,
rlogin, telnet, rsync, arch, finger, nice, locate,
rlogin, rsync, arch, finger, nice, locate,
bibtex, aspell, xpdf,
compress, wine, xmms, dig, wine, batch, cron,
g++, javac, java, gcj, lpr, doxygen, whois, find)
@@ -1281,9 +1300,6 @@ 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
to have this problem.
*/
/** \page design Design document
@@ -2437,14 +2453,15 @@ DAMAGES.
- <a href='#faq-cd-autocomplete'>Why does the cd command autocompletion list the subdirectories of my home directory as completions?</a>
- <a href='#faq-cd-implicit'>I accidentally entered a directory path and fish changed directory. What happened?</a>
- <a href='#faq-open'>The open command doesn't work.</a>
- <a href='#faq-default'>How do I make fish my default shell?</a>
<hr>
\section faq-cwd-symlink Why does cd, pwd and other fish commands always resolve symlinked directories to their canonical path?
\section faq-cwd-symlink Why does cd, $PWD and and various fish commands always resolve symlinked directories to their canonical path?
<i>
For example if I have the directory ~/images which is a symlink to
~/Documents,/Images if I write 'cd doc', my prompt will say
~/D/Images, not ~/images.
For example if ~/images is a symlink to ~/Documents/Images, if I write
'cd images', my prompt will say ~/D/Images, not ~/images.
</i>
Because it is impossible to consistently keep symlinked directories
@@ -2475,9 +2492,9 @@ silently fails in shells that don't resolve symlinked paths.
Because they are completions. In fish, if you specify a relative
directory to the cd command, i.e. any path that does not start with
'.' or '/', the environment variable CD_PATH will be examined, and any
either './' or '/', the environment variable CDPATH will be examined, and any
directories in this path is used as a base direcotry. To disable this
feature, use the command <code>set CD_PATH .</code>.
feature, write <code>set CDPATH .</code> on the commandline.
<hr>
@@ -2501,5 +2518,25 @@ in a nonstandard location. Please contact the <a
href='mailto:fish-users@lists.sf.net'>fish mailing list</a>, and
hopefully this can be resolved.
\section faq-default How do I make fish my default shell?
If you installed fish manually (e.g. by compiling it, not by using a
package manager), you first need to add fish to the list of shells by
executing the following command (assuming you installed fish in
/usr/local) as root:
<code>echo /usr/local/bin/fish >>/etc/shells</code>
If you installed a prepackaged version of fish, the package manager
should have already done this for you.
In order to change your default shell, type:
<code>chsh -s /usr/bin/fish</code>
You may need to adjust the above path to e.g. /usr/local/bin/fish.
You will need to log out and back in again for the change to take
effect.
*/

View File

@@ -5,9 +5,12 @@
if CONDITION; COMMAND_TRUE [else; COMMAND_FALSE] end
while CONDITION; COMMANDS; end
switch VALUE; [case [WILDCARD...]; [COMMANDS...];...] end
begin; [COMMANDS...] end
</pre>
\subsection end-description Description
<tt>end</tt> ends a block of commands. For more information, read the
documentation for the block constructs, such as \c if, \c for and \
documentation for the block constructs, such as \c if, \c for and \c
while.
The \c end command does not change the current exit status.

View File

@@ -7,8 +7,8 @@
The <tt>exit</tt> builtin causes fish to exit. If <tt>STATUS</tt> is
supplied, it will be converted to an integer and used as the exit
code. Otherwise the exit code will be 0.
code. Otherwise the exit code will be that of the last command executed.
If exit is called while sourcing a file (using the <a
href="#source">.</a> builtin) the rest of the file will be skipped,
but the shell will not exit.
but the shell itself will not exit.

View File

@@ -20,6 +20,12 @@ When no clients are connected, fishd will automatically shut down.
~/.fishd.HOSTNAME permanent storage location for universal variable
data. The data is stored as a set of \c set and \c set_export commands
such as would be parsed by fishd. If an instance of fishd is running
such as would be parsed by fishd. If an instance of fishd is running
(which is generally the case), manual modifications to ~/.fishd.HOSTNAME
will be lost.
will be lost. Do NOT edit this file manually!
/tmp/fishd.socket.USERNAME the socket which fishd uses to communicate
with all clients.
/tmp/fishd.log.USERNAME the fishd log file

View File

@@ -1,18 +1,18 @@
\section function function - create a function
\subsection function-synopsis Synopsis
<tt>function [OPTIONS] NAME; BODY; end </tt>
<code>function [OPTIONS] NAME; BODY; end </code>
\subsection function-description Description
- \c -b or \c --key-binding specifies that the function is a key biding. Key binding functions work exactly like regular functions except that they can not be tab-completed, and may contain the '-' character.
- <tt>-d DESCRIPTION</tt> or \c --description=DESCRIPTION is a description of what the function does, suitable as a completion description
- <tt>-j PID</tt> or <tt> --on-job-exit PID</tt> tells fish to run this function when the job with group id PID exits
- <tt>-p PID</tt> or <tt> --on-process-exit PID</tt> tells fish to run this function when the fish child process with process id PID exits
- <tt>-s</tt> or <tt>--on-signal SIGSPEC</tt> tells fish to run this function when the signal SIGSPEC is delivered. SIGSPEC can be a signal number, or the signal name, such as SIGHUP (or just HUP)
- <tt>-v</tt> or <tt>--on-variable VARIABLE_NAME</tt> tells fish to run this function when the variable VARIABLE_NAME changes value
- <code>-d DESCRIPTION</code> or \c --description=DESCRIPTION is a description of what the function does, suitable as a completion description
- <code>-j PID</code> or <code> --on-job-exit PID</code> tells fish to run this function when the job with group id PID exits. Instead of PID, the string 'caller' can be specified. This is only legal when in a command substitution, and will result in the handler being triggered by the exit of the job which created this command substitution.
- <code>-p PID</code> or <code> --on-process-exit PID</code> tells fish to run this function when the fish child process with process id PID exits
- <code>-s</code> or <code>--on-signal SIGSPEC</code> tells fish to run this function when the signal SIGSPEC is delivered. SIGSPEC can be a signal number, or the signal name, such as SIGHUP (or just HUP)
- <code>-v</code> or <code>--on-variable VARIABLE_NAME</code> tells fish to run this function when the variable VARIABLE_NAME changes value
This builtin command is used to create a new function. A Function is a
This builtin command is used to create a new function. A function is a
list of commands that will be executed when the name of the function
is entered. The function
@@ -22,10 +22,10 @@ function hi
end
</pre>
will write <tt>hello</tt> whenever the user enters \c hi.
will write <code>hello</code> whenever the user enters \c hi.
If the user enters any additional arguments after the function, they
are inserted into the environment variable <a href="index.html#variables-arrays">array</a> argv.
are inserted into the environment <a href="index.html#variables-arrays">variable array</a> argv.
\subsection function-example Example

View File

@@ -1,17 +1,27 @@
\section functions functions - print or erase functions
\subsection function-synopsis Synopsis
<tt>functions [-e] FUNCTIONS...</tt>
<code>functions [-e] FUNCTIONS...</code>
\subsection functions-description Description
This builtin command is used to print or erase functions.
- <tt>-e</tt> or <tt>--erase</tt> causes the specified functions to be erased.
- <tt>-n</tt> or <tt>--names</tt> List only the names of all defined functions
- <code>-a</code> or <code>--all</code> list all functions, even those whose name start with an underscore.
- <code>-d DESCRIPTION</code> or <code>--description=DESCRIPTION</code> change the description of this function
- <code>-e</code> or <code>--erase</code> causes the specified functions to be erased.
- <code>-h</code> or <code>--help</code> display a help message and exit
- <code>-n</code> or <code>--names</code> list only the names of all defined functions
- <code>-q</code> or <code>--query</code> test if the specified functions exist. Does not output anything, but the builtins exit status is the number of functions specified that were not defined.
If \c functions is called with no arguments, the names and definition
of all functions are printed, otherwise, the specified function
definitions will be printed.
The default behavior of \c functions when called with no arguments,
is to print the names and definitions of all defined functions. If any
non-switch parameters are given, only the definition of the specified
functions are printed.
Automatically loaded functions can not be removed using functions
-e. Either remove the definition file or change the
$fish_function_path variable to remove autoloaded functions.
The exit status of the functions builtin is the number functions
specified in the argument list that do not exist.

View File

@@ -1,18 +1,19 @@
\section jobs jobs - print currently running jobs
\subsection jobs-synopsis
<tt>jobs [OPTIONS] [PID]</tt>
<code>jobs [OPTIONS] [PID]</code>
\subsection jobs-description Description
The <tt>jobs</tt> builtin causes fish to print a list of the currently
The <code>jobs</code> builtin causes fish to print a list of the currently
running jobs and their status.
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 process id for each process in all jobs
- <code>-c</code> or <code>--command</code> print the command name for each process in jobs
- <code>-g</code> or <code>--group</code> only print the group id of each job
- <code>-h</code> or <code>--help</code> display a help message and exit
- <code>-l</code> or <code>--last</code> only the last job to be started is printed
- <code>-p</code> or <code>--pid</code> print the process 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

View File

@@ -14,6 +14,13 @@
- \c -f, \c --output-description the output will be the description of each mimetype
- \c -a, \c --output-action the output will be the default action of each mimetype
- \c -l, \c --launch launch the default action for the specified file(s)
- \c -h, \c --help Display a help message and exit
- \c -v, \c --version Display version number and exit
- \c -h, \c --help display a help message and exit
- \c -v, \c --version display version number and exit
The mimedb command is used to query the mimetype database and the
.desktop files installed on the system in order to find information on
a file. The information that mimedb can retrive includes the mimetype
for a file, a description of the type and what its default action
is. mimedb can also be used to launch the default action for this
file.

View File

@@ -8,10 +8,16 @@
The \c or builtin is used to execute a command if the current exit status (as set by the last previous command) is non-zero
The or command does not change the current exit status.
\subsection or-example Example
The following code runs the \c make command to build a program, or if it fails, it runs <tt>make clean</tt>, which removes the files created by the build process
The following code runs the \c make command to build a program, if the
build succceds, the program is installed. If either step fails,
<tt>make clean</tt> is run, which removes the files created by the
build process
<pre>
make; or make clean
make; and make install; or make clean
</pre>

View File

@@ -2,18 +2,21 @@
\section return return - Stop the innermost currently evaluated function
\subsection return-synopsis Synopsis
<tt>function NAME; [COMMANDS...] break [STATUS]; [COMMANDS...] end</tt>
<tt>function NAME; [COMMANDS...] return [STATUS]; [COMMANDS...] end</tt>
\subsection return-description Description The \c return builtin is
used to halt a currently running function. It is usually added inside
of a conditional block such as an <a href="#if">if</a> statement or a
<a href="#switch">switch</a> statement to conditionally stop the
executing function and return to the caller.
\subsection return-description Description
- \c STATUS is the return status of the function. If unspecified, the status is set to 0.
The \c return builtin is used to halt a currently running function. It
is usually added inside of a conditional block such as an <a
href="#if">if</a> statement or a <a href="#switch">switch</a>
statement to conditionally stop the executing function and return to
the caller, but it can also be used to specify the exit status of a
function.
- \c STATUS is the return status of the function. If unspecified, the status is unchanged.
\subsection return-example Example
The following code is an implementation of the false program as a fish builtin
The following code is an implementation of the false command as a fish function
<p>
<pre>function false
return 1

View File

@@ -1,22 +1,23 @@
\section set set - Handle environment variables.
\subsection set-synopsis Synopsis
<code>set [OPTIONS] [VARIABLE_NAME [VALUES...]]</code>
or
<code>set [OPTIONS] [VARIABLE_NAME[INDICES]... [VALUES...]]</code>
<pre>set [SCOPE_OPTIONS]
set [OPTIONS] VARIABLE_NAME VALUES...
set [OPTIONS] VARIABLE_NAME[INDICES]... VALUES...
set (-q | --query) [SCOPE_OPTIONS] VARIABLE_NAMES...
set (-e | --erase) [SCOPE_OPTIONS] VARIABLE_NAME
set (-e | --erase) [SCOPE_OPTIONS] VARIABLE_NAME[INDICES]... </pre>
The <code>set</code> builtin causes fish to assign the variable <code>VARIABLE_NAME</code> the values <code>VALUES...</code>.
\subsection set-description Description
- <code>-e</code> or <code>--erase</code> causes the specified environment variable to be erased
- <code>-g</code> or <code>--global</code> causes the specified environment variable to be made global. If this option is not supplied, the specified variable will disappear when the current block ends
- <code>-l</code> or <code>--local</code> forces the specified environment variable to be made local to the current block, even if the variable already exists and is non-local
- <code>-l</code> or <code>--local</code> forces the specified environment variable to be given a scope that is local to the current block, even if a variable with the given name exists and is non-local
- <code>-g</code> or <code>--global</code> causes the specified environment variable to be given a global scope. Non-global variables disappear when the block they belong to ends
- <code>-U</code> or <code>--universal</code> causes the specified environment variable to be given a universal scope. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
- <code>-n</code> or <code>--names</code> List only the names of all defined variables
- <code>-q</code> or <code>--query</code> test if the specified variable names are defined. Does not output anything, but the builtins exit status is the number of variables specified that were not defined.
- <code>-u</code> or <code>--unexport</code> causes the specified environment not to be exported to child processes
- <code>-U</code> or <code>--universal</code> causes the specified environment variable to be made universal. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
- <code>-x</code> or <code>--export</code> causes the specified environment variable to be exported to child processes
If set is called with no arguments, the names and values of all
@@ -24,9 +25,6 @@ environment variables are printed. If some of the scope or export
flags have been given, only the variables matching the specified scope
are printed.
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. If a variable is set to zero
elements, it will become an array with zero elements.
@@ -35,13 +33,46 @@ If the variable name is one or more array elements, such as
<code>PATH[1 3 7]</code>, only those array elements specified will be
changed. When array indices are specified to set, multiple arguments
may be used to specify additional indexes, e.g. <code>set PATH[1]
PATH[4] /bin /sbin</code>.
PATH[4] /bin /sbin</code>. If you specify a negative index when
expanding or assigning to an array variable, the index will be
calculated from the end of the array. For example, the index -1 means
the last index of an array.
The scoping rules when 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 of the same name exists in a different scope, that variable will not be changed.
-# If a variable is not explicitly set to be either universal, global or local, but has been previously defined, the previos variable scope is used.
-# 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.
The exporting rules when creating or updating a variable are 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 before been defined, the variable will not be exported.
In query mode, the scope to be examined can be specified.
In erase mode, if variable indices are specified, only the specified
slices of the array variable will be erased. When erasing an entire
variable (i.e. no slicing), the scope of the variable to be erased can
be specified. That way, a global variable can be erased even if a
local variable with the same name exists. Scope can not be specified
when erasing a slice of an array. The innermost scope is always used.
The set command requires all switch arguments to come before any
non-switch arguments. For example, <code>set flags -l</code> will have
the effect of setting the value of the variable <code>flags</code> to
'-l', not making the variable local.
In assignment mode, set exits with an exit status of zero it the
variable assignments where sucessfully performed, with a non-zero exit
status otherwise. In query mode, the exit status is the number of
variables that where not found. In erase mode, set exits with a zero
exit status in case of success, with a non-zero exit status if the
commandline was invalid, if the variable was write-protected or if the
variable did not exist.
\subsection set-example Example
<code>set -xg</code> will print all global, exported variables.

View File

@@ -10,10 +10,11 @@ Change the foreground and/or background color of the terminal.
COLOR is one of black, red, green, brown, yellow, blue, magenta,
purple, cyan, white and normal.
- \c -c, \c --print-colors Prints a list of all valid color names
- \c -b, \c --background Set the background color
- \c -o, \c --bold Set bold or extra bright mode
- \c -c, \c --print-colors Prints a list of all valid color names
- \c -h, \c --help Display help message and exit
- \c -o, \c --bold Set bold or extra bright mode
- \c -u, \c --underline Set underlined mode
- \c -v, \c --version Display version and exit
@@ -25,3 +26,6 @@ color set. On such terminals, <code>set_color white</code> will result
in a grey font color, while <code>set_color --bold white</code> will
result in a white font color.
Not all terminal emulators support all these features. This is not a
bug in set_color but a missing feature in the terminal emulator.

View File

@@ -15,6 +15,9 @@ With no options, indicate how each name would be interpreted if used as a comman
- \c -p or \c --path either return the name of the disk file that would be executed if name were specified as a command name, or nothing if 'type -t name' would not return 'file'
- \c -P or \c --force-path either return the name of the disk file that would be executed if name were specified as a command name, or nothing no file with the specified name could be found in the PATH
\c type returns a zero exit status if the specified command was found,
otherwise the exit status is one.
\subsection type-example Example
<tt>type fg</tt> outputs the string 'fg is a shell builtin'.

214
env.c
View File

@@ -31,6 +31,10 @@
#include <ncurses/term.h>
#endif
#if HAVE_LIBINTL_H
#include <libintl.h>
#endif
#include <errno.h>
@@ -49,13 +53,13 @@
#include "env_universal.h"
#include "input_common.h"
#include "event.h"
#include "translate.h"
#include "complete.h"
/**
Command used to start fishd
*/
#define FISHD_CMD L"if which fishd >/dev/null; fishd ^/tmp/fishd.%s.log; end"
#define FISHD_CMD L"if which fishd 2>/dev/null >/dev/null; fishd ^/tmp/fishd.log.%s; end"
/**
Value denoting a null string
@@ -104,7 +108,11 @@ typedef struct env_node
typedef struct var_entry
{
int export; /**< Whether the variable should be exported */
#if __STDC_VERSION__ < 199901L
wchar_t val[1]; /**< The value of the variable */
#else
wchar_t val[]; /**< The value of the variable */
#endif
}
var_entry_t;
@@ -188,7 +196,7 @@ static const wchar_t *locale_variable[] =
/**
Free hash key and hash value
*/
static void clear_hash_entry( const void *key, const void *data )
static void clear_hash_entry( void *key, void *data )
{
var_entry_t *entry = (var_entry_t *)data;
if( entry->export )
@@ -301,21 +309,19 @@ static void handle_locale()
if( wcscmp( wsetlocale( LC_MESSAGES, (void *)0 ), old ) != 0 )
{
/* Try to make change known to gettext. */
#ifdef HAVE__NL_MSG_CAT_CNTR
{
extern int _nl_msg_cat_cntr;
++_nl_msg_cat_cntr;
}
#elif HAVE_DCGETTEXT
dcgettext("fish","Changing language to English",LC_MESSAGES);
#endif
/*
Try to make change known to gettext. Both changing
_nl_msg_cat_cntr and calling dcgettext might potentially
tell some gettext implementation that the translation
strings should be reloaded. We do both and hope for the
best.
*/
extern int _nl_msg_cat_cntr;
++_nl_msg_cat_cntr;
dcgettext( "fish", "Changing language to English", LC_MESSAGES );
if( is_interactive )
{
complete_destroy();
complete_init();
debug( 0, _(L"Changing language to English") );
}
}
@@ -435,14 +441,14 @@ static void setup_path()
sb_destroy( &b );
al_foreach( &l, (void (*)(const void *))&free );
al_foreach( &l, &free );
path = env_get( L"PATH" );
al_truncate( &l, 0 );
tokenize_variable_array( path, &l );
}
}
al_foreach( &l, (void (*)(const void *))&free );
al_foreach( &l, &free );
al_destroy( &l );
}
@@ -623,6 +629,8 @@ int env_set( const wchar_t *key,
event_t ev;
int is_universal = 0;
CHECK( key, ENV_INVALID );
if( (var_mode & ENV_USER ) &&
hash_get( &env_read_only, key ) )
{
@@ -757,7 +765,7 @@ int env_set( const wchar_t *key,
if( !done )
{
void *k, *v;
hash_remove( &node->env, key, (const void **)&k, (const void **)&v );
hash_remove( &node->env, key, &k, &v );
free( k );
free( v );
@@ -822,10 +830,12 @@ int env_set( const wchar_t *key,
\return zero if the variable was not found, non-zero otherwise
*/
static int try_remove( env_node_t *n,
const wchar_t *key )
const wchar_t *key,
int var_mode )
{
const void *old_key_void, *old_val_void;
void *old_key_void, *old_val_void;
wchar_t *old_key, *old_val;
if( n == 0 )
return 0;
@@ -850,44 +860,72 @@ static int try_remove( env_node_t *n,
return 1;
}
if( var_mode & ENV_LOCAL )
return 0;
if( n->new_scope )
return try_remove( global_env, key );
return try_remove( global_env, key, var_mode );
else
return try_remove( n->next, key );
return try_remove( n->next, key, var_mode );
}
void env_remove( const wchar_t *key, int var_mode )
int env_remove( const wchar_t *key, int var_mode )
{
env_node_t *first_node;
int erased = 0;
CHECK( key, 1 );
if( (var_mode & ENV_USER ) &&
hash_get( &env_read_only, key ) )
{
return;
return 2;
}
if( try_remove( top, key ) )
{
event_t ev;
ev.type=EVENT_VARIABLE;
ev.param1.variable=key;
ev.function_name=0;
al_init( &ev.arguments );
al_push( &ev.arguments, L"VARIABLE" );
al_push( &ev.arguments, L"ERASE" );
al_push( &ev.arguments, key );
event_fire( &ev );
al_destroy( &ev.arguments );
}
else
first_node = top;
if( ! (var_mode & ENV_UNIVERSAL ) )
{
env_universal_remove( key );
if( var_mode & ENV_GLOBAL )
{
first_node = global_env;
}
if( try_remove( first_node, key, var_mode ) )
{
event_t ev;
ev.type=EVENT_VARIABLE;
ev.param1.variable=key;
ev.function_name=0;
al_init( &ev.arguments );
al_push( &ev.arguments, L"VARIABLE" );
al_push( &ev.arguments, L"ERASE" );
al_push( &ev.arguments, key );
event_fire( &ev );
al_destroy( &ev.arguments );
erased = 1;
}
}
if( !erased &&
!(var_mode & ENV_GLOBAL) &&
!(var_mode & ENV_LOCAL) )
{
erased = !env_universal_remove( key );
}
if( is_locale( key ) )
{
handle_locale();
}
return !erased;
}
@@ -897,6 +935,8 @@ wchar_t *env_get( const wchar_t *key )
env_node_t *env = top;
wchar_t *item;
CHECK( key, 0 );
if( wcscmp( key, L"history" ) == 0 )
{
wchar_t *current;
@@ -989,40 +1029,62 @@ wchar_t *env_get( const wchar_t *key )
return item;
}
int env_exist( const wchar_t *key )
int env_exist( const wchar_t *key, int mode )
{
var_entry_t *res;
env_node_t *env = top;
wchar_t *item;
if( hash_get( &env_read_only, key ) || hash_get( &env_electric, key ) )
{
return 1;
}
while( env != 0 )
env_node_t *env;
wchar_t *item=0;
CHECK( key, 0 );
/*
Read only variables all exist, and they are all global. A local
version can not exist.
*/
if( ! (mode & ENV_LOCAL) && ! (mode & ENV_UNIVERSAL) )
{
res = (var_entry_t *) hash_get( &env->env,
key );
if( res != 0 )
if( hash_get( &env_read_only, key ) || hash_get( &env_electric, key ) )
{
return 1;
}
if( env->new_scope )
env = global_env;
else
env = env->next;
}
if( !proc_had_barrier)
}
if( ! (mode & ENV_UNIVERSAL) )
{
proc_had_barrier=1;
env_universal_barrier();
env = (mode & ENV_GLOBAL)?global_env:top;
while( env != 0 )
{
res = (var_entry_t *) hash_get( &env->env,
key );
if( res != 0 )
{
return 1;
}
if( mode & ENV_LOCAL )
break;
if( env->new_scope )
env = global_env;
else
env = env->next;
}
}
item = env_universal_get( key );
if( ! (mode & ENV_LOCAL) && ! (mode & ENV_GLOBAL) )
{
if( !proc_had_barrier)
{
proc_had_barrier=1;
env_universal_barrier();
}
item = env_universal_get( key );
}
return item != 0;
}
/**
@@ -1104,8 +1166,8 @@ void env_pop()
Function used with hash_foreach to insert keys of one table into
another
*/
static void add_key_to_hash( const void *key,
const void *data,
static void add_key_to_hash( void *key,
void *data,
void *aux )
{
var_entry_t *e = (var_entry_t *)data;
@@ -1119,7 +1181,7 @@ static void add_key_to_hash( const void *key,
/**
Add key to hashtable
*/
static void add_to_hash( const void *k, void *aux )
static void add_to_hash( void *k, void *aux )
{
hash_put( (hash_table_t *)aux,
k,
@@ -1129,8 +1191,8 @@ static void add_to_hash( const void *k, void *aux )
/**
Add key to list
*/
static void add_key_to_list( const void * key,
const void * val,
static void add_key_to_list( void * key,
void * val,
void *aux )
{
al_push( (array_list_t *)aux, key );
@@ -1146,6 +1208,8 @@ void env_get_names( array_list_t *l, int flags )
hash_table_t names;
env_node_t *n=top;
CHECK( l, );
get_names_show_exported =
flags & ENV_EXPORT|| (!(flags & ENV_UNEXPORT));
get_names_show_unexported =
@@ -1214,7 +1278,7 @@ void env_get_names( array_list_t *l, int flags )
/**
Function used by env_export_arr to iterate over hashtable of variables
*/
static void export_func1( const void *k, const void *v, void *aux )
static void export_func1( void *k, void *v, void *aux )
{
var_entry_t *val_entry = (var_entry_t *)v;
if( val_entry->export )
@@ -1230,7 +1294,7 @@ static void export_func1( const void *k, const void *v, void *aux )
/**
Function used by env_export_arr to iterate over hashtable of variables
*/
static void export_func2( const void *k, const void *v, void *aux )
static void export_func2( void *k, void *v, void *aux )
{
wchar_t *key = (wchar_t *)k;
wchar_t *val = (wchar_t *)v;
@@ -1244,7 +1308,7 @@ static void export_func2( const void *k, const void *v, void *aux )
if( !ks || !vs )
{
die_mem();
DIE_MEM();
}
/*
@@ -1267,7 +1331,7 @@ static void export_func2( const void *k, const void *v, void *aux )
free( vs );
}
char **env_export_arr( int recalc)
char **env_export_arr( int recalc )
{
if( recalc && !proc_had_barrier)
{

20
env.h
View File

@@ -44,7 +44,12 @@
/**
Error code for trying to alter read-only variable
*/
#define ENV_PERM 1
enum{
ENV_PERM = 1,
ENV_INVALID
}
;
/**
Initialize environment variable data
@@ -71,7 +76,7 @@ void env_destroy();
The current error codes are:
* ENV_PERM, can only be returned when setting as a user, e.g. ENV_USER is set. This means that the user tried to change a read-only variable.
* ENV_INVALID, the variable name or mode was invalid
*/
int env_set( const wchar_t *key,
@@ -91,16 +96,21 @@ wchar_t *env_get( const wchar_t *key );
/**
Returns 1 if the specified key exists. This can't be reliable done
using env_get, since env_get returns null for 0-element arrays
\param key The name of the variable to remove
\param mode the scope to search in. All scopes are searched if unset
*/
int env_exist( const wchar_t *key );
int env_exist( const wchar_t *key, int mode );
/**
Remove environemnt variable
\param key The name of the variable to remove
\param mode should be ENV_USER if this is a remove request from the user, 0 otherwise. If this is a user request, read-only variables can not be removed.
\param mode should be ENV_USER if this is a remove request from the user, 0 otherwise. If this is a user request, read-only variables can not be removed. The mode may also specify the scope of the variable that should be erased.
\return zero if the variable existed, and non-zero if the variable did not exist
*/
void env_remove( const wchar_t *key, int mode );
int env_remove( const wchar_t *key, int mode );
/**
Push the variable stack. Used for implementing local variables for functions and for-loops.

View File

@@ -182,7 +182,12 @@ static void check_connection()
if( env_universal_server.killme )
{
debug( 3, L"Lost connection to universal variable server." );
close( env_universal_server.fd );
if( close( env_universal_server.fd ) )
{
wperror( L"close" );
}
env_universal_server.fd = -1;
env_universal_server.killme=0;
sb_clear( &env_universal_server.input );
@@ -251,8 +256,13 @@ void env_universal_destroy()
wperror( L"fcntl" );
}
try_send_all( &env_universal_server );
if( close( env_universal_server.fd ) )
{
wperror( L"close" );
}
}
close( env_universal_server.fd );
env_universal_server.fd =-1;
q_destroy( &env_universal_server.unsent );
sb_destroy( &env_universal_server.input );
@@ -295,16 +305,20 @@ wchar_t *env_universal_get( const wchar_t *name )
{
if( !init)
return 0;
if( !name )
return 0;
CHECK( name, 0 );
debug( 3, L"env_universal_get( \"%ls\" )", name );
return env_universal_common_get( name );
}
int env_universal_get_export( const wchar_t *name )
{
if( !init)
return 0;
CHECK( name, 0 );
debug( 3, L"env_universal_get_export()" );
return env_universal_common_get_export( name );
}
@@ -377,7 +391,9 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
if( !init )
return;
CHECK( name, );
debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name, value );
msg = create_message( export?SET_EXPORT:SET,
@@ -395,11 +411,17 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
env_universal_barrier();
}
void env_universal_remove( const wchar_t *name )
int env_universal_remove( const wchar_t *name )
{
int res;
message_t *msg;
if( !init )
return;
return 1;
CHECK( name, 1 );
res = !env_universal_common_get( name );
debug( 3,
L"env_universal_remove( \"%ls\" )",
@@ -409,12 +431,17 @@ void env_universal_remove( const wchar_t *name )
msg->count=1;
q_put( &env_universal_server.unsent, msg );
env_universal_barrier();
return res;
}
void env_universal_get_names( array_list_t *l,
int show_exported,
int show_unexported )
{
if( !init )
return;
env_universal_common_get_names( l,
show_exported,
show_unexported );

View File

@@ -40,8 +40,10 @@ int env_universal_get_export( const wchar_t *name );
void env_universal_set( const wchar_t *name, const wchar_t *val, int export );
/**
Erase a universal variable
\return zero if the variable existed, and non-zero if the variable did not exist
*/
void env_universal_remove( const wchar_t *name );
int env_universal_remove( const wchar_t *name );
/**
Read all available messages from the server.

View File

@@ -116,8 +116,8 @@ void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const w
/**
Free both key and data
*/
static void erase( const void *key,
const void *data )
static void erase( void *key,
void *data )
{
free( (void *)key );
free( (void *)data );
@@ -205,8 +205,8 @@ static void remove_entry( wchar_t *name )
void *k, *v;
hash_remove( &env_universal_var,
name,
(const void **)&k,
(const void **)&v );
&k,
&v );
free( k );
free( v );
}
@@ -261,7 +261,7 @@ static void parse_message( wchar_t *msg,
var_uni_entry_t *entry =
malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) );
if( !entry )
die_mem();
DIE_MEM();
entry->export=export;
wcscpy( entry->val, val );
@@ -433,7 +433,7 @@ message_t *create_message( int type,
msg = malloc( sizeof( message_t ) + sz );
if( !msg )
die_mem();
DIE_MEM();
strcpy( msg->body, (type==SET?SET_MBS:SET_EXPORT_MBS) );
strcat( msg->body, " " );
@@ -453,7 +453,7 @@ message_t *create_message( int type,
msg = malloc( sizeof( message_t ) + sz );
if( !msg )
die_mem();
DIE_MEM();
strcpy( msg->body, ERASE_MBS " " );
strcat( msg->body, key );
@@ -466,7 +466,7 @@ message_t *create_message( int type,
msg = malloc( sizeof( message_t ) +
strlen( BARRIER_MBS ) +2);
if( !msg )
die_mem();
DIE_MEM();
strcpy( msg->body, BARRIER_MBS "\n" );
break;
}
@@ -476,7 +476,7 @@ message_t *create_message( int type,
msg = malloc( sizeof( message_t ) +
strlen( BARRIER_REPLY_MBS ) +2);
if( !msg )
die_mem();
DIE_MEM();
strcpy( msg->body, BARRIER_REPLY_MBS "\n" );
break;
}
@@ -498,8 +498,8 @@ message_t *create_message( int type,
Function used with hash_foreach to insert keys of one table into
another
*/
static void add_key_to_hash( const void *key,
const void *data,
static void add_key_to_hash( void *key,
void *data,
void *aux )
{
var_uni_entry_t *e = (var_uni_entry_t *)data;
@@ -546,8 +546,8 @@ int env_universal_common_get_export( const wchar_t *name )
\param v the variable value
\param q the queue to add the message to
*/
static void enqueue( const void *k,
const void *v,
static void enqueue( void *k,
void *v,
void *q)
{
const wchar_t *key = (const wchar_t *)k;

View File

@@ -7,8 +7,8 @@
# Set default search paths for completions and shellscript functions
#
set -g fish_function_path ~/.fish.d/functions @SYSCONFDIR@/fish.d/functions @DATADIR@/fish/functions
set -g fish_complete_path ~/.fish.d/completions @SYSCONFDIR@/fish.d/completions @DATADIR@/fish/completions
set -g fish_function_path ~/.fish.d/functions @sysconfdir@/fish.d/functions @datadir@/fish/functions
set -g fish_complete_path ~/.fish.d/completions @sysconfdir@/fish.d/completions @datadir@/fish/completions
#
# Set default field separators

View File

@@ -30,10 +30,10 @@ end
# 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.
# @sysconfdir@/fish_inputrc.
#
for i in ~/.fish_inputrc @SYSCONFDIR@/fish_inputrc ~/.inputrc /etc/inputrc
for i in ~/.fish_inputrc @sysconfdir@/fish_inputrc ~/.inputrc /etc/inputrc
if test -f $i
set -xg INPUTRC $i
break
@@ -73,6 +73,7 @@ set_default fish_color_error red --bold
set_default fish_color_escape cyan
set_default fish_color_operator cyan
set_default fish_color_quote brown
set_default fish_color_valid_path --underline
set_default fish_color_cwd green

40
event.c
View File

@@ -23,7 +23,7 @@
#include "common.h"
#include "event.h"
#include "signal.h"
#include "translate.h"
#include "halloc_util.h"
/**
@@ -140,7 +140,7 @@ static event_t *event_copy( event_t *event, int copy_arguments )
{
event_t *e = malloc( sizeof( event_t ) );
if( !e )
die_mem();
DIE_MEM();
memcpy( e, event, sizeof(event_t));
if( e->function_name )
@@ -196,6 +196,9 @@ static int event_is_blocked( event_t *e )
const wchar_t *event_get_desc( event_t *e )
{
CHECK( e, 0 );
if( !get_desc_buff )
{
get_desc_buff=sb_halloc( global_context );
@@ -253,6 +256,8 @@ void event_add_handler( event_t *event )
{
event_t *e;
CHECK( event, );
e = event_copy( event, 0 );
if( !events )
@@ -272,6 +277,8 @@ void event_remove( event_t *criterion )
array_list_t *new_list=0;
event_t e;
CHECK( criterion, );
/*
Because of concurrency issues (env_remove could remove an event
that is currently being executed), env_remove does not actually
@@ -282,7 +289,7 @@ void event_remove( event_t *criterion )
*/
if( !events )
return;
return;
for( i=0; i<al_get_count( events); i++ )
{
@@ -330,6 +337,8 @@ int event_get( event_t *criterion, array_list_t *out )
if( !events )
return 0;
CHECK( criterion, 0 );
for( i=0; i<al_get_count( events); i++ )
{
@@ -382,9 +391,9 @@ static int event_is_killed( event_t *e )
/**
Perform the specified event. Since almost all event firings will
not match a single event handler, we make sureto optimize the 'no
matches' path. This means that nothing is allocated/initialized
unless that is needed.
not be matched by even a single event handler, we make sure to
optimize the 'no matches' path. This means that nothing is
allocated/initialized unless needed.
*/
static void event_fire_internal( event_t *event )
{
@@ -464,7 +473,7 @@ static void event_fire_internal( event_t *event )
/*
Event handlers are not part of the main flow of code, so
they are marked as non-interactive and as a subshell
they are marked as non-interactive
*/
proc_push_interactive(0);
parser_push_block( EVENT );
@@ -501,6 +510,13 @@ static void event_fire_delayed()
int i;
/*
If is_event is one, we are running the event-handler non-recursively.
When the event handler has called a piece of code that triggers
another event, we do not want to fire delayed events because of
concurrency problems.
*/
if( blocked && is_event==1)
{
array_list_t *new_blocked = 0;
@@ -585,7 +601,7 @@ void event_fire( event_t *event )
/*
This means we are in a signal handler. We must be very
careful not do do anything that could cause a memory
allocation or something else that might be illegal in a
allocation or something else that might be bad when in a
signal handler.
*/
if( sig_list[active_list].count < SIG_UNHANDLED_MAX )
@@ -627,7 +643,7 @@ void event_destroy()
if( events )
{
al_foreach( events, (void (*)(const void *))&event_free );
al_foreach( events, (void (*)(void *))&event_free );
al_destroy( events );
free( events );
events=0;
@@ -635,7 +651,7 @@ void event_destroy()
if( killme )
{
al_foreach( killme, (void (*)(const void *))&event_free );
al_foreach( killme, (void (*)(void *))&event_free );
al_destroy( killme );
free( killme );
killme=0;
@@ -644,10 +660,12 @@ void event_destroy()
void event_free( event_t *e )
{
CHECK( e, );
/*
When apropriate, we clear the argument vector
*/
al_foreach( &e->arguments, (void (*)(const void *))&free );
al_foreach( &e->arguments, &free );
al_destroy( &e->arguments );
free( (void *)e->function_name );

129
exec.c
View File

@@ -39,7 +39,7 @@
#include "expand.h"
#include "signal.h"
#include "env_universal.h"
#include "translate.h"
#include "halloc.h"
#include "halloc_util.h"
#include "parse_util.h"
@@ -86,9 +86,10 @@ void exec_close( int fd )
{
debug( 1, FD_ERROR, fd );
wperror( L"close" );
break;
}
}
if( open_fds )
{
for( i=0; i<al_get_count( open_fds ); i++ )
@@ -260,7 +261,11 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
switch( io->io_mode )
{
case IO_CLOSE:
close(io->fd);
if( close(io->fd) )
{
debug( 0, _(L"Failed to close file descriptor %d"), io->fd );
wperror( L"close" );
}
break;
case IO_FILE:
{
@@ -283,8 +288,12 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
}
else if( tmp != io->fd)
{
/*
This call will sometimes fail, but that is ok,
this is just a precausion.
*/
close(io->fd);
if(dup2( tmp, io->fd ) == -1 )
{
debug( 1,
@@ -307,6 +316,10 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
case IO_FD:
{
/*
This call will sometimes fail, but that is ok,
this is just a precausion.
*/
close(io->fd);
if( dup2( io->param1.old_fd, io->fd ) == -1 )
@@ -332,6 +345,10 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
{
int fd_to_dup = io->fd;
/*
This call will sometimes fail, but that is ok,
this is just a precausion.
*/
close(io->fd);
if( dup2( io->param1.pipe_fd[fd_to_dup?1:0], io->fd ) == -1 )
@@ -478,7 +495,7 @@ static io_data_t *io_transmogrify( io_data_t * in )
out = malloc( sizeof( io_data_t ) );
if( !out )
die_mem();
DIE_MEM();
out->fd = in->fd;
out->io_mode = IO_FD;
@@ -652,6 +669,8 @@ void exec( job_t *j )
*/
int exec_error=0;
CHECK( j, );
if( no_exec )
return;
@@ -668,7 +687,7 @@ void exec( job_t *j )
signal_block();
/*
setup_child_process make sure signals are properly set
setup_child_process makes sure signals are properly set
up. It will also call signal_unblock
*/
if( !setup_child_process( j, 0 ) )
@@ -757,22 +776,12 @@ void exec( job_t *j )
break;
}
/* fwprintf( stderr,
L"Make pipe from %ls to %ls using fds %d and %d\n",
p->actual_cmd,
p->next->actual_cmd,
mypipe[0],
mypipe[1] );
*/
memcpy( pipe_write.param1.pipe_fd, mypipe, sizeof(int)*2);
}
else
{
/*
This is the last element of the pipeline.
*/
/*
Remove the io redirection for pipe output.
*/
j->io = io_remove( j->io, &pipe_write );
@@ -785,7 +794,6 @@ void exec( job_t *j )
{
wchar_t * def = halloc_register( j, wcsdup( function_get_definition( p->argv[0] )));
//fwprintf( stderr, L"run function %ls\n", argv[0] );
if( def == 0 )
{
debug( 0, _( L"Unknown function '%ls'" ), p->argv[0] );
@@ -803,7 +811,6 @@ void exec( job_t *j )
if( p->next )
{
// fwprintf( stderr, L"Function %ls\n", def );
io_buffer = io_buffer_create();
j->io = io_add( j->io, io_buffer );
}
@@ -820,7 +827,6 @@ void exec( job_t *j )
{
if( p->next )
{
// fwprintf( stderr, L"Block %ls\n", p->argv[0] );
io_buffer = io_buffer_create();
j->io = io_add( j->io, io_buffer );
}
@@ -848,11 +854,6 @@ void exec( job_t *j )
case IO_FD:
{
builtin_stdin = in->param1.old_fd;
/* fwprintf( stderr,
L"Input redirection for builtin '%ls' from fd %d\n",
p->argv[0],
in->old_fd );
*/
break;
}
case IO_PIPE:
@@ -863,11 +864,6 @@ void exec( job_t *j )
case IO_FILE:
{
/*
fwprintf( stderr,
L"Input redirection for builtin from file %ls\n",
in->filename);
*/
builtin_stdin=wopen( in->param1.filename,
in->param2.flags, 0777 );
if( builtin_stdin == -1 )
@@ -907,40 +903,37 @@ void exec( job_t *j )
exec_error=1;
break;
}
else
{
builtin_push_io( builtin_stdin );
/*
Since this may be the foreground job, and since a
builtin may execute another foreground job, we need to
pretend to suspend this job while running the builtin.
*/
builtin_out_redirect = has_fd( j->io, 1 );
builtin_err_redirect = has_fd( j->io, 2 );
fg = j->fg;
j->fg = 0;
signal_unblock();
p->status = builtin_run( p->argv );
signal_block();
/*
Restore the fg flag, which is temporarily set to
false during builtin execution so as not to confuse
some job-handling builtins.
*/
j->fg = fg;
}
builtin_push_io( builtin_stdin );
/*
Since this may be the foreground job, and since a
builtin may execute another foreground job, we need to
pretend to suspend this job while running the builtin.
*/
builtin_out_redirect = has_fd( j->io, 1 );
builtin_err_redirect = has_fd( j->io, 2 );
fg = j->fg;
j->fg = 0;
signal_unblock();
p->status = builtin_run( p->argv );
signal_block();
/*
Restore the fg flag, which is temporarily set to
false during builtin execution so as not to confuse
some job-handling builtins.
*/
j->fg = fg;
/* if( is_interactive )
fwprintf( stderr, L"Builtin '%ls' finished\n", j->command );
*/
if( close_stdin )
{
// fwprintf( stderr, L"Close builtin_stdin\n" );
exec_close( builtin_stdin );
}
break;
@@ -1059,7 +1052,6 @@ void exec( job_t *j )
( sb_out->used ) &&
( buffer_stdout ) )
{
// fwprintf( stderr, L"Skip fork of %ls\n", j->command );
char *res = wcs2str( (wchar_t *)sb_out->buff );
b_append( io->param2.out_buffer, res, strlen( res ) );
skip_fork = 1;
@@ -1082,9 +1074,13 @@ void exec( job_t *j )
pid = fork();
if( pid == 0 )
{
/*
This is the child process.
This is the child process. Setup redirections,
print correct output to stdout and stderr, and
then exit.
*/
p->pid = getpid();
setup_child_process( j, p );
if( sb_out->used )
@@ -1106,7 +1102,7 @@ void exec( job_t *j )
{
/*
This is the parent process. Store away
information on the child, and possibly fice
information on the child, and possibly give
it control over the terminal.
*/
p->pid = pid;
@@ -1173,8 +1169,11 @@ void exec( job_t *j )
pipe_read.param1.pipe_fd[0] = mypipe[0];
/*
If there is a next process, close the output end of the
pipe (the child subprocess already has a copy of the pipe).
If there is a next process in the pipeline, close the
output end of the current pipe (the surrent child
subprocess already has a copy of the pipe - this makes sure
we don't leak file descriptors either in the shell or in
the children).
*/
if( p->next )
{

229
expand.c
View File

@@ -42,10 +42,30 @@ parameter expansion.
#include "signal.h"
#include "tokenizer.h"
#include "complete.h"
#include "translate.h"
#include "parse_util.h"
#include "halloc_util.h"
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean %ls{$%ls}%ls? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
/**
Description for child process
*/
@@ -101,6 +121,8 @@ int expand_is_clean( const wchar_t *in )
const wchar_t * str = in;
CHECK( in, 1 );
/*
Test characters that have a special meaning in the first character position
*/
@@ -161,6 +183,8 @@ wchar_t *expand_escape_variable( const wchar_t *in )
array_list_t l;
string_buffer_t buff;
CHECK( in, 0 );
al_init( &l );
tokenize_variable_array( in, &l );
sb_init( &buff );
@@ -570,6 +594,10 @@ static int expand_pid( wchar_t *in,
int flags,
array_list_t *out )
{
CHECK( in, 0 );
CHECK( out, 0 );
if( *in != PROCESS_EXPAND )
{
al_push( out, in );
@@ -638,6 +666,83 @@ static int expand_pid( wchar_t *in,
return 1;
}
void expand_variable_error( const wchar_t *token, int token_pos, int error_pos )
{
int stop_pos = token_pos+1;
switch( token[stop_pos] )
{
case BRACKET_BEGIN:
{
wchar_t *cpy = wcsdup( token );
*(cpy+token_pos)=0;
wchar_t *name = &cpy[stop_pos+1];
wchar_t *end = wcschr( name, BRACKET_END );
wchar_t *post;
int is_var=0;
if( end )
{
post = end+1;
*end = 0;
if( !wcsvarname( name ) )
{
is_var = 1;
}
}
if( is_var )
{
error( SYNTAX_ERROR,
error_pos,
COMPLETE_VAR_BRACKET_DESC,
cpy,
name,
post );
}
else
{
error( SYNTAX_ERROR,
error_pos,
COMPLETE_VAR_BRACKET_DESC,
L"",
L"VARIABLE",
L"" );
}
free( cpy );
break;
}
case INTERNAL_SEPARATOR:
{
error( SYNTAX_ERROR,
error_pos,
COMPLETE_VAR_PARAN_DESC );
break;
}
case 0:
{
error( SYNTAX_ERROR,
error_pos,
COMPLETE_VAR_NULL_DESC );
break;
}
default:
{
error( SYNTAX_ERROR,
error_pos,
COMPLETE_VAR_DESC,
token[stop_pos] );
break;
}
}
}
/**
Expand all environment variables in the string *ptr.
@@ -663,11 +768,14 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
static string_buffer_t *var_tmp = 0;
static array_list_t *var_idx_list = 0;
CHECK( in, 0 );
CHECK( out, 0 );
if( !var_tmp )
{
var_tmp = sb_halloc( global_context );
if( !var_tmp )
die_mem();
DIE_MEM();
}
else
{
@@ -678,7 +786,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
{
var_idx_list = al_halloc( global_context );
if( !var_idx_list )
die_mem();
DIE_MEM();
}
else
{
@@ -718,43 +826,8 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
if( var_len == 0 )
{
switch( in[stop_pos] )
{
case BRACKET_BEGIN:
{
error( SYNTAX_ERROR,
-1,
COMPLETE_VAR_BRACKET_DESC );
break;
}
case INTERNAL_SEPARATOR:
{
error( SYNTAX_ERROR,
-1,
COMPLETE_VAR_PARAN_DESC );
break;
}
case 0:
{
error( SYNTAX_ERROR,
-1,
COMPLETE_VAR_NULL_DESC );
break;
}
default:
{
error( SYNTAX_ERROR,
-1,
COMPLETE_VAR_DESC,
in[stop_pos] );
break;
}
}
expand_variable_error( in, stop_pos-1, -1 );
is_ok = 0;
break;
}
@@ -778,7 +851,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
stop_pos++;
while( 1 )
{
int tmp;
long tmp;
while( iswspace(in[stop_pos]) || (in[stop_pos]==INTERNAL_SEPARATOR))
stop_pos++;
@@ -814,12 +887,17 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
int j;
for( j=0; j<al_get_count( var_idx_list ); j++)
{
int tmp = (int)al_get( var_idx_list, j );
long tmp = (long)al_get( var_idx_list, j );
if( tmp < 0 )
{
tmp = al_get_count( &var_item_list)+tmp+1;
}
if( tmp < 1 || tmp > al_get_count( &var_item_list ) )
{
error( SYNTAX_ERROR,
-1,
L"Array index out of bounds" );
ARRAY_BOUNDS_ERR );
is_ok=0;
al_truncate( var_idx_list, j );
break;
@@ -832,7 +910,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
}
}
/* Free remaining strings in list l and truncate it */
al_foreach( &var_item_list, (void (*)(const void *))&free );
al_foreach( &var_item_list, &free );
al_truncate( &var_item_list, 0 );
/* Add items from list idx back to list l */
al_push_all( &var_item_list, var_idx_list );
@@ -885,7 +963,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
{
die_mem();
DIE_MEM();
}
else
{
@@ -981,16 +1059,18 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
wchar_t *item_begin;
int len1, len2, tot_len;
CHECK( in, 0 );
CHECK( out, 0 );
for( pos=in;
(!bracket_end) && (*pos) && !syntax_error;
(*pos) && !syntax_error;
pos++ )
{
switch( *pos )
{
case BRACKET_BEGIN:
{
if(( bracket_count == 0)&&(bracket_begin==0))
bracket_begin = pos;
bracket_begin = pos;
bracket_count++;
break;
@@ -999,9 +1079,11 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
case BRACKET_END:
{
bracket_count--;
if( (bracket_count == 0) && (bracket_end == 0) )
if( bracket_end < bracket_begin )
{
bracket_end = pos;
}
if( bracket_count < 0 )
{
syntax_error = 1;
@@ -1019,7 +1101,9 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
if( bracket_count > 0 )
{
if( !(flags & ACCEPT_INCOMPLETE) )
{
syntax_error = 1;
}
else
{
@@ -1037,9 +1121,6 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
sb_append_char( &mod, BRACKET_END );
}
return expand_brackets( (wchar_t*)mod.buff, 1, out );
}
}
@@ -1103,7 +1184,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
*/
static int expand_subshell( wchar_t *in, array_list_t *out )
{
const wchar_t *paran_begin=0, *paran_end=0;
wchar_t *paran_begin=0, *paran_end=0;
int len1, len2;
wchar_t prev=0;
wchar_t *subcmd;
@@ -1111,18 +1192,9 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
int i, j;
const wchar_t *item_begin;
if( !in )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
if( !out )
{
debug( 2, L"Got null pointer on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
CHECK( in, 0 );
CHECK( out, 0 );
switch( parse_util_locate_cmdsubst(in,
&paran_begin,
&paran_end,
@@ -1158,7 +1230,7 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
if( exec_subshell( subcmd, &sub_res)==-1 )
{
al_foreach( &sub_res, (void (*)(const void *))&free );
al_foreach( &sub_res, &free );
al_destroy( &sub_res );
free( subcmd );
return 0;
@@ -1197,14 +1269,16 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
al_destroy( &sub_res );
al_foreach( &tail_expand, (void (*)(const void *))&free );
al_foreach( &tail_expand, &free );
al_destroy( &tail_expand );
free( subcmd );
return 1;
}
/**
Wrapper around unescape funtion. Issues an error() on failiure.
*/
static wchar_t *expand_unescape( const wchar_t * in, int escape_special )
{
wchar_t *res = unescape( in, escape_special );
@@ -1222,6 +1296,8 @@ static wchar_t *expand_unescape( const wchar_t * in, int escape_special )
static wchar_t * expand_tilde_internal( wchar_t *in )
{
CHECK( in, 0 );
if( in[0] == HOME_DIRECTORY )
{
int tilde_error = 0;
@@ -1296,6 +1372,8 @@ static wchar_t * expand_tilde_internal( wchar_t *in )
wchar_t *expand_tilde( wchar_t *in)
{
CHECK( in, 0 );
if( in[0] == L'~' )
{
in[0] = HOME_DIRECTORY;
@@ -1306,12 +1384,14 @@ wchar_t *expand_tilde( wchar_t *in)
/**
Remove any internal separators. Also optionally convert wildcard characters to
regular equivalents. This is done to support EXPAN_SKIP_WILDCARDS.
regular equivalents. This is done to support EXPAND_SKIP_WILDCARDS.
*/
static void remove_internal_separator( const void *s, int conv )
{
wchar_t *in = (wchar_t *)s;
wchar_t *out=in;
CHECK( s, );
while( *in )
{
@@ -1354,6 +1434,9 @@ int expand_string( void *context,
int res = EXPAND_OK;
int start_count = al_get_count( end_out );
CHECK( str, EXPAND_ERROR );
CHECK( end_out, EXPAND_ERROR );
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( str ) )
{
halloc_register( context, str );
@@ -1366,7 +1449,7 @@ int expand_string( void *context,
if( EXPAND_SKIP_SUBSHELL & flags )
{
const wchar_t *begin, *end;
wchar_t *begin, *end;
if( parse_util_locate_cmdsubst( str,
&begin,
@@ -1599,6 +1682,8 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
array_list_t l;
int res;
wchar_t *one;
CHECK( string, 0 );
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string ) )
{
@@ -1625,7 +1710,7 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
}
}
al_foreach( &l, (void(*)(const void *))&free );
al_foreach( &l, &free );
al_destroy( &l );
halloc_register( context, one );

View File

@@ -113,43 +113,31 @@ enum
#define ARRAY_SEP_STR L"\x1e"
/**
Error issued on invalid variable name
Error issued on array out of bounds
*/
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean {$VARIABLE}? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
#define ARRAY_BOUNDS_ERR _(L"Array index out of bounds")
/**
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),
(\~USER becomes the users home directory), variable expansion
(\$VAR_NAME becomes the value of the environment variable VAR_NAME),
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
out. If expansion is performed, the original parameter is freed and
newly allocated strings are inserted into the list out.
If \c context is non-null, all the strings contained in the
array_list_t \c out will be registered to be free'd when context is
free'd.
\param context the halloc context to use for automatic deallocation
\param in The parameter to expand
\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
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH. EXPAND_WILDCARD_NO_MATCH and EXPAND_WILDCARD_MATCH are normal exit conditions used only on strings containing wildcards to tell if the wildcard produced any matches.
*/
int expand_string( void *context, wchar_t *in, array_list_t *out, int flag );
@@ -158,6 +146,10 @@ int expand_string( void *context, wchar_t *in, array_list_t *out, int flag );
expands to more than one string. This is used for expanding command
names.
If \c context is non-null, the returning string ill be registered
to be free'd when context is free'd.
\param context the halloc context to use for automatic deallocation
\param in The parameter to expand
\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
@@ -166,6 +158,8 @@ wchar_t *expand_one( void *context, wchar_t *in, int flag );
/**
Convert the variable value to a human readable form, i.e. escape things, handle arrays, etc. Suitable for pretty-printing.
\param in the value to escape
*/
wchar_t *expand_escape_variable( const wchar_t *in );
@@ -174,6 +168,8 @@ wchar_t *expand_escape_variable( const wchar_t *in );
If tilde expansion is needed, the original string is freed and a
new string, allocated using malloc, is returned.
\param in the string to tilde expand
*/
wchar_t *expand_tilde(wchar_t *in);
@@ -186,7 +182,22 @@ wchar_t *expand_tilde(wchar_t *in);
skipping expansion on them actually does save a small amount of
time, since it avoids multiple memory allocations during the
expansion process.
\param in the string to test
*/
int expand_is_clean( const wchar_t *in );
/**
Perform error reporting for a syntax error related to the variable
expansion beginning at the specified character of the specified
token. This function will call the error function with an
explanatory string about what is wrong with the specified token.
\param token The token containing the error
\param token_pos The position where the expansion begins
\param error_pos The position on the line to report to the error function.
*/
void expand_variable_error( const wchar_t *token, int token_pos, int error_pos );
#endif

View File

@@ -2,6 +2,10 @@
This file only contains fallback implementations of functions which
have been found to be missing or broken by the configuration
scripts.
Many of these functions are more or less broken and
incomplete. lrand28_r internally uses the regular (bad) rand_r
function, the gettext function doesn't actually do anything, etc.
*/
#include "config.h"
@@ -65,7 +69,11 @@ int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t))
#ifdef INTERNAL_FWPRINTF
void pad( void (*writer)(wchar_t), int count)
/**
Internal function for the wprintf fallbacks. USed to write the
specified number of spaces.
*/
static void pad( void (*writer)(wchar_t), int count)
{
int i;
@@ -1005,3 +1013,66 @@ int del_curterm(TERMINAL *oterm)
#endif
#ifndef HAVE_LRAND48_R
int lrand48_r(struct drand48_data *buffer, long int *result)
{
*result = rand_r( &buffer->seed );
return 0;
}
int srand48_r(long int seedval, struct drand48_data *buffer)
{
buffer->seed = (int)seedval;
return 0;
}
#endif
#ifndef HAVE_FUTIMES
int futimes(int fd, const struct timeval *times)
{
errno = ENOSYS;
return -1;
}
#endif
#ifndef HAVE_GETTEXT
char * gettext (const char * msgid)
{
return (char *)msgid;
}
char * bindtextdomain (const char * domainname, const char * dirname)
{
return 0;
}
char * textdomain (const char * domainname)
{
return 0;
}
#endif
#ifndef HAVE_DCGETTEXT
char * dcgettext ( const char * domainname,
const char * msgid,
int category)
{
return (char *)msgid;
}
#endif
#ifndef HAVE__NL_MSG_CAT_CNTR
int _nl_msg_cat_cntr=0;
#endif

View File

@@ -8,6 +8,7 @@
#include <wctype.h>
#include <wchar.h>
#include <limits.h>
#include <sys/time.h>
#ifndef WCHAR_MAX
/**
@@ -16,6 +17,19 @@
#define WCHAR_MAX INT_MAX
#endif
/**
Make sure __func__ is defined to some string. In C99, this should
be the currently compiled function. If we aren't using C99 or
later, older versions of GCC had __FUNCTION__.
*/
#if __STDC_VERSION__ < 199901L
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
#endif
/**
Under curses, tputs expects an int (*func)(char) as its last
parameter, but in ncurses, tputs expects a int (*func)(int) as its
@@ -279,4 +293,78 @@ size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
int del_curterm(TERMINAL *oterm);
#endif
#ifndef HAVE_LRAND48_R
/**
Datastructure for the lrand48_r fallback implementation.
*/
struct drand48_data
{
/**
Seed value
*/
unsigned int seed;
}
;
/**
Fallback implementation of lrand48_r. Internally uses rand_r, so it is pretty weak.
*/
int lrand48_r( struct drand48_data *buffer, long int *result );
/**
Fallback implementation of srand48_r, the seed function for lrand48_r.
*/
int srand48_r( long int seedval, struct drand48_data *buffer );
#endif
#ifndef HAVE_FUTIMES
int futimes( int fd, const struct timeval *times );
#endif
#ifndef HAVE_GETTEXT
/**
Fallback implementation of gettext. Just returns the original string.
*/
char * gettext( const char * msgid );
/**
Fallback implementation of bindtextdomain. Does nothing.
*/
char * bindtextdomain( const char * domainname, const char * dirname );
/**
Fallback implementation of textdomain. Does nothing.
*/
char * textdomain( const char * domainname );
#endif
#ifndef HAVE_DCGETTEXT
/**
Fallback implementation of dcgettext. Just returns the original string.
*/
char * dcgettext ( const char * domainname,
const char * msgid,
int category );
#endif
#ifndef HAVE__NL_MSG_CAT_CNTR
/**
Some gettext implementation use have this variable, and by
increasing it, one can tell the system that the translations need
to be reloaded.
*/
extern int _nl_msg_cat_cntr;
#endif
#endif

View File

@@ -13,7 +13,7 @@ URL: http://roo.no-ip.org/fish/
Source0: http://roo.no-ip.org/%{name}/files/%{version}/%{name}-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: doxygen ncurses-devel
BuildRequires: ncurses-devel
BuildRequires: %{xinclude}/X11/StringDefs.h, %{xinclude}/X11/Xlib.h
BuildRequires: %{xinclude}/X11/Intrinsic.h, %{xinclude}/X11/Xatom.h

View File

@@ -97,13 +97,34 @@ static wchar_t *hightlight_var[] =
static string_buffer_t out_buff;
static FILE *out_file;
/**
Data structure describing one or a group of related completions
*/
typedef struct
{
/**
The list of all completin strings this entry applies to
*/
array_list_t *comp;
/**
The description
*/
wchar_t *desc;
/**
On-screen width of the completion string
*/
int comp_width;
/**
On-screen width of the description information
*/
int desc_width;
/**
Preffered total width
*/
int pref_width;
/**
Minimum acceptable width
*/
int min_width;
}
comp_t;
@@ -719,7 +740,8 @@ static void mangle_descriptions( array_list_t *l )
*/
static void join_completions( array_list_t *l )
{
int i, in, out;
long i;
int in, out;
hash_table_t desc_table;
hash_init( &desc_table, &hash_wcs_func, &hash_wcs_cmp );
@@ -760,8 +782,6 @@ static void join_completions( array_list_t *l )
al_set( l, i, 0 );
}
// debug( 1, L"WOOT WOOT %ls är släkt med %ls", item, al_get( l, prev_idx ) );
}
}

View File

@@ -51,6 +51,11 @@
*/
#define LAPS 50
/**
The result of one of the test passes
*/
#define NUM_ANS L"-7 99999999 1234567 deadbeef DEADBEEFDEADBEEF"
/**
Number of encountered errors
*/
@@ -193,7 +198,7 @@ static int stack_test( int elements )
/**
Hash function for pointers
*/
static int hash_func( const void *data )
static int hash_func( void *data )
{
/* srand( (int)data );
return rand();
@@ -205,7 +210,7 @@ static int hash_func( const void *data )
/**
Pointer hash comparison function
*/
static int compare_func( const void *key1, const void *key2 )
static int compare_func( void *key1, void *key2 )
{
return key1==key2;
}
@@ -345,8 +350,6 @@ static void sb_test()
sb_clear( &b );
#define NUM_ANS L"-7 99999999 1234567 deadbeef DEADBEEFDEADBEEF"
sb_printf( &b, L"%d %u %o %x %llX", -7, 99999999, 01234567, 0xdeadbeef, 0xdeadbeefdeadbeefll );
if( wcscmp( (wchar_t *)b.buff, NUM_ANS) != 0 )
{
@@ -483,43 +486,43 @@ static void test_parser()
say( L"Testing null input to parser" );
if( !parser_test( 0, 0 ) )
if( !parser_test( 0, 0, 0 ) )
{
err( L"Null input to parser_test undetected" );
}
say( L"Testing block nesting" );
if( !parser_test( L"if; end", 0 ) )
if( !parser_test( L"if; end", 0, 0 ) )
{
err( L"Incomplete if statement undetected" );
}
if( !parser_test( L"if test; echo", 0 ) )
if( !parser_test( L"if test; echo", 0, 0 ) )
{
err( L"Missing end undetected" );
}
if( !parser_test( L"if test; end; end", 0 ) )
if( !parser_test( L"if test; end; end", 0, 0 ) )
{
err( L"Unbalanced end undetected" );
}
say( L"Testing detection of invalid use of builtin commands" );
if( !parser_test( L"case foo", 0 ) )
if( !parser_test( L"case foo", 0, 0 ) )
{
err( L"'case' command outside of block context undetected" );
}
if( !parser_test( L"switch ggg; if true; case foo;end;end", 0 ) )
if( !parser_test( L"switch ggg; if true; case foo;end;end", 0, 0 ) )
{
err( L"'case' command outside of switch block context undetected" );
}
if( !parser_test( L"else", 0 ) )
if( !parser_test( L"else", 0, 0 ) )
{
err( L"'else' command outside of conditional block context undetected" );
}
if( !parser_test( L"break", 0 ) )
if( !parser_test( L"break", 0, 0 ) )
{
err( L"'break' command outside of loop block context undetected" );
}
if( !parser_test( L"exec ls|less", 0 ) || !parser_test( L"echo|return", 0 ))
if( !parser_test( L"exec ls|less", 0, 0 ) || !parser_test( L"echo|return", 0, 0 ))
{
err( L"Invalid pipe command undetected" );
}
@@ -574,7 +577,7 @@ static int expand_test( const wchar_t *in, int flags, ... )
}
va_end( va );
al_foreach( &out, (void (*)(const void *))&free );
al_foreach( &out, &free );
return res;
}
@@ -639,7 +642,7 @@ void perf_complete()
matches += al_get_count( &out );
al_foreach( &out, (void (*)(const void *))&free );
al_foreach( &out, &free );
al_truncate( &out, 0 );
}
t2=get_time();
@@ -661,7 +664,7 @@ void perf_complete()
matches += al_get_count( &out );
al_foreach( &out, (void (*)(const void *))&free );
al_foreach( &out, &free );
al_truncate( &out, 0 );
}
t2=get_time();
@@ -693,7 +696,6 @@ int main( int argc, char **argv )
parser_init();
function_init();
builtin_init();
complete_init();
reader_init();
env_init();
@@ -715,7 +717,6 @@ int main( int argc, char **argv )
parser_destroy();
function_destroy();
builtin_destroy();
complete_destroy();
wutil_destroy();
event_destroy();
proc_destroy();

25
fishd.c
View File

@@ -6,7 +6,7 @@ variables from ~/.fishd, and takes care of communication between fish
instances. When no clients are running, fishd will automatically shut
down and save.
\subsection fishd-commands Commands
\section fishd-commands Commands
Fishd works by sending and receiving commands. Each command is ended
with a newline. These are the commands supported by fishd:
@@ -88,7 +88,12 @@ time the original barrier request was sent have been received.
/**
Small greeting to show that fishd is running
*/
#define GREETING "#Fish universal variable daemon\n"
#define GREETING "# Fish universal variable daemon\n"
/**
Small not about not editing ~/.fishd manually. Inserted at the top of all .fishd files.
*/
#define SAVE_MSG "# This file is automatically generated by the fishd universal variable daemon.\n# Do NOT edit it directly, your changes will be overwritten.\n"
/**
The name of the save file. The hostname is appended to this.
@@ -230,7 +235,7 @@ static int get_socket()
debug( 0, L"Unable to obtain lock on socket, exiting" );
exit( EXIT_FAILURE );
}
debug( 1, L"Acquired lockfile: %s", lockfile );
debug( 4, L"Acquired lockfile: %s", lockfile );
local.sun_family = AF_UNIX;
strcpy( local.sun_path, sock_name );
@@ -278,7 +283,7 @@ static int get_socket()
unlock:
(void)unlink( lockfile );
debug( 1, L"Released lockfile: %s", lockfile );
debug( 4, L"Released lockfile: %s", lockfile );
/*
End critical section protected by lock
*/
@@ -406,7 +411,7 @@ void load_or_save( int save)
strcat( name, FILE );
strcat( name, hostname );
debug( 1, L"Open file for %s: '%s'",
debug( 4, L"Open file for %s: '%s'",
save?"saving":"loading",
name );
@@ -419,14 +424,18 @@ void load_or_save( int save)
wperror( L"open" );
return;
}
debug( 1, L"File open on fd %d", c.fd );
debug( 4, L"File open on fd %d", c.fd );
sb_init( &c.input );
memset (&c.wstate, '\0', sizeof (mbstate_t));
q_init( &c.unsent );
if( save )
{
write( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
enqueue_all( &c );
}
else
read_message( &c );
@@ -592,7 +601,7 @@ int main( int argc, char ** argv )
}
else
{
debug( 1, L"Connected with new child on fd %d", child_socket );
debug( 4, L"Connected with new child on fd %d", child_socket );
if( fcntl( child_socket, F_SETFL, O_NONBLOCK ) != 0 )
{
@@ -649,7 +658,7 @@ int main( int argc, char ** argv )
{
if( c->killme )
{
debug( 1, L"Close connection %d", c->fd );
debug( 4, L"Close connection %d", c->fd );
close(c->fd );
sb_destroy( &c->input );

View File

@@ -16,7 +16,6 @@
#include "function.h"
#include "proc.h"
#include "translate.h"
#include "parser.h"
#include "common.h"
#include "intern.h"
@@ -36,9 +35,22 @@ typedef struct
wchar_t *cmd;
/** Function description */
wchar_t *desc;
/**
File where this function was defined
*/
const wchar_t *definition_file;
/**
Line where definition started
*/
int definition_offset;
/**
Flag for specifying functions which are actually key bindings
*/
int is_binding;
/**
Flag for specifying that this function was automatically loaded
*/
int is_autoload;
}
function_data_t;
@@ -47,6 +59,12 @@ typedef struct
Table containing all functions
*/
static hash_table_t function;
/**
Kludgy flag set by the load function in order to tell function_add
that the function being defined is autoloaded. There should be a
better way to do this...
*/
static int is_autoload = 0;
/**
@@ -110,13 +128,13 @@ static void autoload_names( array_list_t *out, int get_hidden )
*suffix = 0;
dup = intern( fn );
if( !dup )
die_mem();
DIE_MEM();
al_push( out, dup );
}
}
closedir(dir);
}
al_foreach( &path_list, (void (*)(const void *))&free );
al_foreach( &path_list, &free );
al_destroy( &path_list );
}
@@ -124,8 +142,8 @@ static void autoload_names( array_list_t *out, int get_hidden )
/**
Free all contents of an entry to the function hash table
*/
static void clear_function_entry( const void *key,
const void *data )
static void clear_function_entry( void *key,
void *data )
{
function_data_t *d = (function_data_t *)data;
free( (void *)d->cmd );
@@ -157,10 +175,13 @@ void function_add( const wchar_t *name,
wchar_t *cmd_end;
function_data_t *d;
CHECK( name, );
CHECK( val, );
function_remove( name );
d = malloc( sizeof( function_data_t ) );
d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos );
d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos )-1;
d->cmd = wcsdup( val );
cmd_end = d->cmd + wcslen(d->cmd)-1;
@@ -185,6 +206,9 @@ void function_add( const wchar_t *name,
int function_exists( const wchar_t *cmd )
{
CHECK( cmd, 0 );
if( parser_is_reserved(cmd) )
return 0;
@@ -195,13 +219,15 @@ int function_exists( const wchar_t *cmd )
void function_remove( const wchar_t *name )
{
void *key;
const void *dv;
void *dv;
function_data_t *d;
event_t ev;
CHECK( name, );
hash_remove( &function,
name,
(const void **) &key,
&key,
&dv );
d=(function_data_t *)dv;
@@ -214,11 +240,24 @@ void function_remove( const wchar_t *name )
event_remove( &ev );
clear_function_entry( key, d );
/*
Notify the autoloader that the specified function is erased, but
only if this call to fish_remove is not made by the autoloader
itself.
*/
if( !is_autoload )
{
parse_util_unload( name, L"fish_function_path", 0 );
}
}
const wchar_t *function_get_definition( const wchar_t *argv )
{
function_data_t *data;
CHECK( argv, 0 );
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
@@ -229,6 +268,9 @@ const wchar_t *function_get_definition( const wchar_t *argv )
const wchar_t *function_get_desc( const wchar_t *argv )
{
function_data_t *data;
CHECK( argv, 0 );
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
@@ -240,6 +282,10 @@ const wchar_t *function_get_desc( const wchar_t *argv )
void function_set_desc( const wchar_t *name, const wchar_t *desc )
{
function_data_t *data;
CHECK( name, );
CHECK( desc, );
load( name );
data = (function_data_t *)hash_get( &function, name );
if( data == 0 )
@@ -248,6 +294,9 @@ void function_set_desc( const wchar_t *name, const wchar_t *desc )
data->desc =wcsdup(desc);
}
/**
Search arraylist of strings for specified string
*/
static int al_contains_str( array_list_t *list, const wchar_t * str )
{
int i;
@@ -264,8 +313,8 @@ static int al_contains_str( array_list_t *list, const wchar_t * str )
/**
Helper function for removing hidden functions
*/
static void get_names_internal( const void *key,
const void *val,
static void get_names_internal( void *key,
void *val,
void *aux )
{
wchar_t *name = (wchar_t *)key;
@@ -280,9 +329,9 @@ static void get_names_internal( const void *key,
/**
Helper function for removing hidden functions
*/
static void get_names_internal_all( const void *key,
const void *val,
void *aux )
static void get_names_internal_all( void *key,
void *val,
void *aux )
{
wchar_t *name = (wchar_t *)key;
@@ -294,6 +343,8 @@ static void get_names_internal_all( const void *key,
void function_get_names( array_list_t *list, int get_hidden )
{
CHECK( list, );
autoload_names( list, get_hidden );
if( get_hidden )
@@ -310,6 +361,9 @@ void function_get_names( array_list_t *list, int get_hidden )
const wchar_t *function_get_definition_file( const wchar_t *argv )
{
function_data_t *data;
CHECK( argv, 0 );
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
@@ -322,6 +376,9 @@ const wchar_t *function_get_definition_file( const wchar_t *argv )
int function_get_definition_offset( const wchar_t *argv )
{
function_data_t *data;
CHECK( argv, -1 );
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )

View File

@@ -18,37 +18,92 @@
#include "common.h"
#include "halloc.h"
/**
Extra size to allocate whenever doing a halloc, in order to fill uyp smaller halloc calls
*/
#define HALLOC_BLOCK_SIZE 128
/**
Maximum size of trailing halloc space to refuse to discard
*/
#define HALLOC_SCRAP_SIZE 16
#ifdef HALLOC_DEBUG
/**
Debug statistic parameter
*/
static int child_count=0;
/**
Debug statistic parameter
*/
static int child_size=0;
/**
Debug statistic parameter
*/
static int alloc_count =0;
/**
Debug statistic parameter
*/
static int alloc_spill = 0;
/**
Debug statistic parameter
*/
static pid_t pid=0;
/**
Debug statistic parameter
*/
static int parent_count=0;
#endif
/**
The main datastructure for a main halloc context
*/
typedef struct halloc
{
/**
List of all addresses and functions to call on them
*/
array_list_t children;
/**
Memory scratch area used to fullfil smaller memory allocations
*/
void *scratch;
/**
Amount of free space in the scratch area
*/
size_t scratch_free;
long long data[0];
#if __STDC_VERSION__ < 199901L
/**
The actual data. MAde to be of type long long to make sure memory alignment is in order.
*/
long long data[1]; // Waste one byte on non-C99 compilers... :-(
#else
long long data[];
#endif
}
halloc_t;
/**
Get the offset of the halloc structure before a data block
*/
static halloc_t *halloc_from_data( void *data )
{
return (halloc_t *)(((char *)data) - sizeof( halloc_t ) );
}
/**
A function that does nothing
*/
static void late_free( void *data)
{
}
#ifdef HALLOC_DEBUG
/**
Debug function, called at exit when in debug mode. Prints usage
statistics, like number of allocations and number of internal calls
to malloc.
*/
static void woot()
{
if( getpid() == pid )

View File

@@ -1,4 +1,4 @@
/** \file halloc.c
/** \file halloc_util.c
A hierarchical memory allocation system. Works just like talloc
used in Samba, except that an arbitrary block allocated with
@@ -35,7 +35,7 @@ array_list_t *al_halloc( void *context )
{
array_list_t *res = halloc( context, sizeof( array_list_t ) );
if( !res )
die_mem();
DIE_MEM();
al_init( res );
halloc_register_function( context, (void (*)(void *)) &al_destroy, res );
return res;
@@ -45,12 +45,15 @@ string_buffer_t *sb_halloc( void *context )
{
string_buffer_t *res = halloc( context, sizeof( string_buffer_t ) );
if( !res )
die_mem();
DIE_MEM();
sb_init( res );
halloc_register_function( context, (void (*)(void *)) &sb_destroy, res );
return res;
}
/**
A function that takes a single parameter, which is a function pointer, and calls it.
*/
static void halloc_passthrough( void *f )
{
void (*func)() = (void (*)() )f;
@@ -71,14 +74,14 @@ void *halloc_register( void *context, void *data )
return data;
}
wchar_t *halloc_wcsdup( void *context, wchar_t *in )
wchar_t *halloc_wcsdup( void *context, const wchar_t *in )
{
size_t len=wcslen(in);
wchar_t *out = halloc( context, sizeof( wchar_t)*(len+1));
if( out == 0 )
{
die_mem();
DIE_MEM();
}
memcpy( out, in, sizeof( wchar_t)*(len+1));
return out;
@@ -89,7 +92,7 @@ wchar_t *halloc_wcsndup( void * context, const wchar_t *in, int c )
wchar_t *res = halloc( context, sizeof(wchar_t)*(c+1) );
if( res == 0 )
{
die_mem();
DIE_MEM();
}
wcslcpy( res, in, c+1 );
res[c] = L'\0';

View File

@@ -55,7 +55,7 @@ void *halloc_register( void *context, void *data );
Make a copy of the specified string using memory allocated using
halloc and the specified context
*/
wchar_t *halloc_wcsdup( void *context, wchar_t *str );
wchar_t *halloc_wcsdup( void *context, const wchar_t *str );
/**
Make a copy of the specified substring using memory allocated using

View File

@@ -30,6 +30,14 @@
#include "common.h"
#include "complete.h"
#include "output.h"
#include "halloc.h"
#include "halloc_util.h"
#include "wildcard.h"
/**
Number of elements in the highlight_var array
*/
#define VAR_COUNT ( sizeof(highlight_var)/sizeof(wchar_t *) )
static void highlight_universal_internal( wchar_t * buff,
int *color,
@@ -43,39 +51,181 @@ static void highlight_universal_internal( wchar_t * buff,
static wchar_t *highlight_var[] =
{
L"fish_color_normal",
L"fish_color_command",
L"fish_color_redirection",
L"fish_color_end",
L"fish_color_error",
L"fish_color_command",
L"fish_color_end",
L"fish_color_param",
L"fish_color_comment",
L"fish_color_match",
L"fish_color_search_match",
L"fish_color_operator",
L"fish_color_escape",
L"fish_color_quote"
L"fish_color_quote",
L"fish_color_redirection",
L"fish_color_valid_path"
}
;
#define VAR_COUNT ( sizeof(highlight_var)/sizeof(wchar_t *) )
/**
Tests if the specified string is the prefix of any valid path in the system.
\return zero it this is not a valid prefix, non-zero otherwise
*/
static int is_potential_path( const wchar_t *path )
{
wchar_t *tilde, *unescaped;
wchar_t *in, *out;
int has_magic = 0;
int res = 0;
void *context = halloc( 0, 0 );
tilde = expand_tilde( wcsdup(path) );
if( tilde )
{
halloc_register( context, tilde );
unescaped = unescape( tilde, 1 );
if( unescaped )
{
// debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
halloc_register( context, unescaped );
for( in = out = unescaped; *in; in++ )
{
switch( *in )
{
case PROCESS_EXPAND:
case VARIABLE_EXPAND:
case VARIABLE_EXPAND_SINGLE:
case BRACKET_BEGIN:
case BRACKET_END:
case BRACKET_SEP:
case ANY_CHAR:
case ANY_STRING:
case ANY_STRING_RECURSIVE:
{
has_magic = 1;
break;
}
case INTERNAL_SEPARATOR:
{
break;
}
default:
{
*(out++) = *in;
break;
}
}
}
*out = 0;
if( !has_magic && wcslen( unescaped ) )
{
int must_be_dir = 0;
DIR *dir;
must_be_dir = unescaped[wcslen(unescaped)-1] == L'/';
if( must_be_dir )
{
dir = wopendir( unescaped );
res = !!dir;
closedir( dir );
}
else
{
wchar_t *dir_name, *base;
struct wdirent *ent;
dir_name = wdirname( halloc_wcsdup(context, unescaped) );
base = wbasename( halloc_wcsdup(context, unescaped) );
if( (wcscmp( dir_name, L"/" ) == 0 ) &&
(wcscmp( base, L"/" ) == 0 ) )
{
res = 1;
}
else if( (dir = wopendir( dir_name )) )
{
while( (ent = wreaddir( dir )) )
{
if( wcsncmp( ent->d_name, base, wcslen(base) ) == 0 )
{
res = 1;
break;
}
}
closedir( dir );
}
}
}
}
}
halloc_free( context );
return res;
}
int highlight_get_color( int highlight )
{
int i;
int idx=0;
int result = 0;
if( highlight < 0 )
return FISH_COLOR_NORMAL;
if( highlight >= VAR_COUNT )
if( highlight >= (1<<VAR_COUNT) )
return FISH_COLOR_NORMAL;
wchar_t *val = env_get( highlight_var[highlight]);
if( val == 0 )
val = env_get( highlight_var[HIGHLIGHT_NORMAL]);
if( val == 0 )
for( i=0; i<(VAR_COUNT-1); i++ )
{
return FISH_COLOR_NORMAL;
if( highlight & (1<<i ))
{
idx = i;
break;
}
}
wchar_t *val = env_get( highlight_var[idx]);
// debug( 1, L"%d -> %d -> %ls", highlight, idx, val );
if( val == 0 )
val = env_get( highlight_var[0]);
if( val )
result = output_color_code( val );
if( highlight & HIGHLIGHT_VALID_PATH )
{
wchar_t *val2 = env_get( L"fish_color_valid_path" );
int result2 = output_color_code( val2 );
if( result == FISH_COLOR_NORMAL )
result = result2;
else
{
if( result2 & FISH_COLOR_BOLD )
result |= FISH_COLOR_BOLD;
if( result2 & FISH_COLOR_UNDERLINE )
result |= FISH_COLOR_UNDERLINE;
}
}
return result;
return output_color_code( val );
}
/**
@@ -92,6 +242,7 @@ static void highlight_param( const wchar_t * buff,
int in_pos, len = wcslen( buff );
int bracket_count=0;
wchar_t c;
int normal_status = *color;
for( in_pos=0;
in_pos<len;
@@ -116,7 +267,7 @@ static void highlight_param( const wchar_t * buff,
if( in_pos == 1 )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
}
}
else if( buff[in_pos]==L',' )
@@ -124,13 +275,13 @@ static void highlight_param( const wchar_t * buff,
if( bracket_count )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
}
}
else if( wcschr( L"nrtbe*?$(){}'\"<>^ \\#;|&", buff[in_pos] ) )
{
color[start_pos]=HIGHLIGHT_ESCAPE;
color[in_pos+1]=HIGHLIGHT_NORMAL;
color[in_pos+1]=normal_status;
}
else if( wcschr( L"uUxX01234567", buff[in_pos] ) )
{
@@ -195,12 +346,12 @@ static void highlight_param( const wchar_t * buff,
if( (res <= max_val) )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
}
else
{
color[start_pos] = HIGHLIGHT_ERROR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
}
}
@@ -214,26 +365,34 @@ static void highlight_param( const wchar_t * buff,
if( in_pos == 0 )
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
}
break;
}
case L'$':
{
wchar_t n = buff[in_pos+1];
color[in_pos] = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
color[in_pos+1] = normal_status;
break;
}
case L'*':
case L'?':
case L'$':
case L'(':
case L')':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
break;
}
case L'{':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
bracket_count++;
break;
}
@@ -241,7 +400,7 @@ static void highlight_param( const wchar_t * buff,
case L'}':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
bracket_count--;
break;
}
@@ -251,7 +410,7 @@ static void highlight_param( const wchar_t * buff,
if( bracket_count )
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
}
break;
@@ -305,7 +464,7 @@ static void highlight_param( const wchar_t * buff,
if( c == L'\'' )
{
mode = 0;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
}
break;
@@ -321,7 +480,7 @@ static void highlight_param( const wchar_t * buff,
case '"':
{
mode = 0;
color[in_pos+1] = HIGHLIGHT_NORMAL;
color[in_pos+1] = normal_status;
break;
}
@@ -349,8 +508,9 @@ static void highlight_param( const wchar_t * buff,
case '$':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = HIGHLIGHT_QUOTE;
wchar_t n = buff[in_pos+1];
color[in_pos] = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
color[in_pos+1] = HIGHLIGHT_QUOTE;
break;
}
@@ -372,11 +532,21 @@ void highlight_shell( wchar_t * buff,
int i;
int last_val;
wchar_t *last_cmd=0;
int len = wcslen(buff);
int len;
void *context;
wchar_t *cmd=0;
CHECK( buff, );
CHECK( color, );
len = wcslen(buff);
if( !len )
return;
context = halloc( 0, 0 );
for( i=0; buff[i] != 0; i++ )
color[i] = -1;
@@ -387,6 +557,7 @@ void highlight_shell( wchar_t * buff,
int last_type = tok_last_type( &tok );
int prev_argc=0;
switch( last_type )
{
case TOK_STRING:
@@ -408,10 +579,25 @@ void highlight_shell( wchar_t * buff,
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_PARAM;
}
if( cmd && (wcscmp( cmd, L"cd" ) == 0) )
{
wchar_t *dir = expand_one( context,
wcsdup(tok_last( &tok )),
EXPAND_SKIP_SUBSHELL );
if( dir )
{
if( !parser_cdpath_get( context, dir ) )
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
}
}
}
highlight_param( param,
&color[tok_get_pos( &tok )],
pos-tok_get_pos( &tok ),
error );
}
else
@@ -421,9 +607,9 @@ void highlight_shell( wchar_t * buff,
/*
Command. First check that the command actually exists.
*/
wchar_t *cmd = expand_one( 0,
wcsdup(tok_last( &tok )),
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
cmd = expand_one( context,
wcsdup(tok_last( &tok )),
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
if( cmd == 0 )
{
@@ -431,7 +617,6 @@ void highlight_shell( wchar_t * buff,
}
else
{
wchar_t *tmp;
int is_cmd = 0;
int is_subcommand = 0;
int mark = tok_get_pos( &tok );
@@ -440,8 +625,9 @@ void highlight_shell( wchar_t * buff,
if( parser_is_subcommand( cmd ) )
{
tok_next( &tok );
if(( wcscmp( L"-h", tok_last( &tok ) ) == 0 ) ||
( wcscmp( L"--help", tok_last( &tok ) ) == 0 ) )
if( ( ! parser_is_block( cmd ) ) &&
( ( wcscmp( L"-h", tok_last( &tok ) ) == 0 ) ||
( wcsncmp( L"--help", tok_last( &tok ), wcslen( tok_last( &tok ) ) ) == 0 && wcslen( tok_last( &tok ) ) >= 3 ) ) )
{
/*
The builtin and command builtins
@@ -460,31 +646,37 @@ void highlight_shell( wchar_t * buff,
if( !is_subcommand )
{
wchar_t *tmp;
/*
OK, this is a command, it has been
successfully expanded and everything
looks ok. Lets check if the command
exists.
*/
/*
First check if it is a builtin or
function, since we don't have to stat
any files for that
*/
is_cmd |= builtin_exists( cmd );
is_cmd |= function_exists( cmd );
is_cmd |= (tmp=get_filename( cmd )) != 0;
/*
Moving on to expensive tests
*/
/*
Check if this is a regular command
*/
is_cmd |= !!(tmp=parser_get_filename( context, cmd ));
/*
Could not find the command. Maybe it is a path for a implicit cd command.
Lets check!
Could not find the command. Maybe it is
a path for a implicit cd command.
*/
if( !is_cmd )
{
wchar_t *pp = parser_cdpath_get( cmd );
if( pp )
{
free( pp );
is_cmd = 1;
}
}
free(tmp);
is_cmd |= !!(tmp=parser_cdpath_get( context, cmd ));
if( is_cmd )
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_COMMAND;
@@ -497,15 +689,11 @@ void highlight_shell( wchar_t * buff,
}
had_cmd = 1;
}
free(cmd);
if( had_cmd )
{
if( last_cmd )
free( last_cmd );
last_cmd = wcsdup( tok_last( &tok ) );
}
last_cmd = halloc_wcsdup( context, tok_last( &tok ) );
}
}
}
@@ -538,7 +726,7 @@ void highlight_shell( wchar_t * buff,
{
case TOK_STRING:
{
target = expand_one( 0, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL);
target = expand_one( context, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL);
/*
Redirect filename may contain a subshell.
If so, it will be ignored/not flagged.
@@ -556,7 +744,7 @@ void highlight_shell( wchar_t * buff,
if( target != 0 )
{
wchar_t *dir = wcsdup( target );
wchar_t *dir = halloc_wcsdup( context, target );
wchar_t *dir_end = wcsrchr( dir, L'/' );
struct stat buff;
/*
@@ -572,9 +760,8 @@ void highlight_shell( wchar_t * buff,
if( error )
al_push( error, wcsdupcat2( L"Directory \'", dir, L"\' does not exist", 0 ) );
}
}
}
free( dir );
/*
If the file is read from or appended to, check
@@ -590,7 +777,6 @@ void highlight_shell( wchar_t * buff,
al_push( error, wcsdupcat2( L"File \'", target, L"\' does not exist", 0 ) );
}
}
free( target );
}
break;
}
@@ -640,16 +826,13 @@ void highlight_shell( wchar_t * buff,
}
}
if( last_cmd )
free( last_cmd );
tok_destroy( &tok );
/*
Locate and syntax highlight subshells recursively
*/
wchar_t *buffcpy = wcsdup( buff );
wchar_t *buffcpy = halloc_wcsdup( context, buff );
wchar_t *subpos=buffcpy;
int done=0;
@@ -658,8 +841,8 @@ void highlight_shell( wchar_t * buff,
wchar_t *begin, *end;
if( parse_util_locate_cmdsubst( subpos,
(const wchar_t **)&begin,
(const wchar_t **)&end,
&begin,
&end,
1) <= 0)
{
break;
@@ -679,9 +862,11 @@ void highlight_shell( wchar_t * buff,
subpos = end+1;
}
free( buffcpy);
/*
The highlighting code only changes the first element when the
color changes. This fills in the rest.
*/
last_val=0;
for( i=0; buff[i] != 0; i++ )
{
@@ -691,6 +876,32 @@ void highlight_shell( wchar_t * buff,
color[i] = last_val;
}
/*
Color potentially valid paths in a special path color if they
are the current token.
*/
if( pos >= 0 && pos <= len )
{
wchar_t *tok_begin, *tok_end;
wchar_t *token;
parse_util_token_extent( buff, pos, &tok_begin, &tok_end, 0, 0 );
if( tok_begin && tok_end )
{
token = halloc_wcsndup( context, tok_begin, tok_end-tok_begin );
if( is_potential_path( token ) )
{
for( i=tok_begin-buff; i < (tok_end-buff); i++ )
{
color[i] |= HIGHLIGHT_VALID_PATH;
}
}
}
}
highlight_universal_internal( buff, color, pos, error );
@@ -704,6 +915,9 @@ void highlight_shell( wchar_t * buff,
color[i]=0;
}
}
halloc_free( context );
}
/**
@@ -753,15 +967,15 @@ static void highlight_universal_internal( wchar_t * buff,
{
if( prev_q == *str )
{
int pos1, pos2;
long pos1, pos2;
level--;
pos1 = (int)al_pop( &l );
pos1 = (long)al_pop( &l );
pos2 = str-buff;
if( pos1==pos || pos2==pos )
{
color[pos1]|=HIGHLIGHT_MATCH<<8;
color[pos2]|=HIGHLIGHT_MATCH<<8;
color[pos1]|=HIGHLIGHT_MATCH<<16;
color[pos2]|=HIGHLIGHT_MATCH<<16;
match_found = 1;
}
@@ -786,7 +1000,7 @@ static void highlight_universal_internal( wchar_t * buff,
al_destroy( &l );
if( !match_found )
color[pos] = HIGHLIGHT_ERROR<<8;
color[pos] = HIGHLIGHT_ERROR<<16;
}
/*
@@ -799,8 +1013,7 @@ static void highlight_universal_internal( wchar_t * buff,
wchar_t inc_char = buff[pos];
int level = 0;
wchar_t *str = &buff[pos];
int match_found=0;
int match_found=0;
while( (str >= buff) && *str)
{
@@ -811,8 +1024,8 @@ static void highlight_universal_internal( wchar_t * buff,
if( level == 0 )
{
int pos2 = str-buff;
color[pos]|=HIGHLIGHT_MATCH<<8;
color[pos2]|=HIGHLIGHT_MATCH<<8;
color[pos]|=HIGHLIGHT_MATCH<<16;
color[pos2]|=HIGHLIGHT_MATCH<<16;
match_found=1;
break;
}
@@ -820,7 +1033,7 @@ static void highlight_universal_internal( wchar_t * buff,
}
if( !match_found )
color[pos] = HIGHLIGHT_ERROR<<8;
color[pos] = HIGHLIGHT_ERROR<<16;
}
}
}
@@ -832,7 +1045,7 @@ void highlight_universal( wchar_t * buff,
{
int i;
for( i=0; buff[i] != 0; i++ )
for( i=0; buff[i]; i++ )
color[i] = 0;
highlight_universal_internal( buff, color, pos, error );

View File

@@ -9,6 +9,59 @@
#include "util.h"
/**
Internal value representing highlighting of normal text
*/
#define HIGHLIGHT_NORMAL 0x1
/**
Internal value representing highlighting of an error
*/
#define HIGHLIGHT_ERROR 0x2
/**
Internal value representing highlighting of a command
*/
#define HIGHLIGHT_COMMAND 0x4
/**
Internal value representing highlighting of a process separator
*/
#define HIGHLIGHT_END 0x8
/**
Internal value representing highlighting of a regular command parameter
*/
#define HIGHLIGHT_PARAM 0x10
/**
Internal value representing highlighting of a comment
*/
#define HIGHLIGHT_COMMENT 0x20
/**
Internal value representing highlighting of a matching parenteses, etc.
*/
#define HIGHLIGHT_MATCH 0x40
/**
Internal value representing highlighting of a search match
*/
#define HIGHLIGHT_SEARCH_MATCH 0x80
/**
Internal value representing highlighting of an operator
*/
#define HIGHLIGHT_OPERATOR 0x100
/**
Internal value representing highlighting of an escape sequence
*/
#define HIGHLIGHT_ESCAPE 0x200
/**
Internal value representing highlighting of a quoted string
*/
#define HIGHLIGHT_QUOTE 0x400
/**
Internal value representing highlighting of an IO redirection
*/
#define HIGHLIGHT_REDIRECTION 0x800
/**
Internal value representing highlighting a potentially valid path
*/
#define HIGHLIGHT_VALID_PATH 0x1000
/**
Perform syntax highlighting for the shell commands in buff. The result is
stored in the color array as a color_code from the HIGHLIGHT_ enum

View File

@@ -41,15 +41,20 @@ typedef struct
Number of entries
*/
int count;
/**
Last history item
*/
ll_node_t *last;
/**
The last item loaded from file
*/
ll_node_t *last_loaded;
/**
Set to one if the file containing the saved history has been loaded
*/
int is_loaded;
}
history_data;
@@ -79,7 +84,9 @@ static int past_end =1;
static int history_count=0;
/**
The name of the current history list. The name is used to switch between history lists for different commands as sell as for deciding the name of the file to save the history in.
The name of the current history list. The name is used to switch
between history lists for different commands as sell as for
deciding the name of the file to save the history in.
*/
static wchar_t *mode_name;
@@ -91,18 +98,24 @@ static hash_table_t history_table;
/**
Flag, set to 1 once the history file has been loaded
*/
static int is_loaded;
static int is_loaded=0;
/**
Load history from file
*/
static void history_load()
static int history_load()
{
wchar_t *fn;
wchar_t *buff=0;
int buff_len=0;
FILE *in_stream;
hash_table_t used;
int res = 0;
if( !mode_name )
{
return -1;
}
is_loaded = 1;
@@ -129,7 +142,7 @@ static void history_load()
free( fn );
free( buff );
signal_unblock();
return;
return -1;
}
/*
@@ -147,7 +160,7 @@ static void history_load()
history_current = malloc( sizeof( ll_node_t ) );
if( !history_current )
{
die_mem();
DIE_MEM();
}
@@ -175,6 +188,8 @@ static void history_load()
{
debug( 1, L"The following non-fatal error occurred while reading command history from \'%ls\':", mode_name );
wperror( L"fopen" );
res = -1;
}
}
@@ -186,6 +201,8 @@ static void history_load()
free( fn );
last_loaded = history_last;
signal_unblock();
return res;
}
void history_init()
@@ -202,7 +219,7 @@ static void history_to_hash()
{
history_data *d;
if( !history_last )
if( !mode_name )
return;
@@ -229,12 +246,22 @@ void history_set_mode( wchar_t *name )
if( mode_name )
{
/*
Move the current history to the hashtable
*/
history_to_hash();
}
/*
See if the new history already exists
*/
curr = (history_data *)hash_get( &history_table,
name );
if( curr )
{
/*
Yes. Restore it.
*/
mode_name = (wchar_t *)hash_get_key( &history_table,
name );
history_current = history_last = curr->last;
@@ -244,6 +271,9 @@ void history_set_mode( wchar_t *name )
}
else
{
/*
Nope. Create a new history list.
*/
history_count=0;
history_last = history_current = last_loaded=0;
mode_name = wcsdup( name );
@@ -295,7 +325,9 @@ static void history_save()
history_count=0;
past_end=1;
history_load();
if( !history_load() )
{
if( real_pos != 0 )
{
/*
@@ -353,6 +385,8 @@ static void history_save()
}
free( fn );
}
}
}
@@ -360,7 +394,7 @@ static void history_save()
Save the specified mode to file
*/
static void history_destroy_mode( const void *name, const void *link )
static void history_destroy_mode( void *name, void *link )
{
mode_name = (wchar_t *)name;
history_data *d = (history_data *)link;
@@ -370,7 +404,7 @@ static void history_destroy_mode( const void *name, const void *link )
past_end=1;
// fwprintf( stderr, L"Destroy history mode \'%ls\'\n", mode_name );
if( history_last )
{
history_save();
@@ -389,11 +423,12 @@ static void history_destroy_mode( const void *name, const void *link )
void history_destroy()
{
/**
Make sure current mode is in table
*/
history_to_hash();
/**
Save all modes in table
*/
@@ -412,7 +447,13 @@ void history_destroy()
static ll_node_t *history_find( ll_node_t *n, const wchar_t *s )
{
if( !is_loaded )
history_load();
{
if( history_load() )
{
return 0;
}
}
if( n == 0 )
return 0;
@@ -431,7 +472,13 @@ void history_add( const wchar_t *str )
ll_node_t *old_node;
if( !is_loaded )
history_load();
{
if( history_load() )
{
return;
}
}
if( wcslen( str ) == 0 )
return;
@@ -482,13 +529,19 @@ static int history_test( const wchar_t *needle, const wchar_t *haystack )
/*
return wcsncmp( haystack, needle, wcslen(needle) )==0;
*/
return (int)wcsstr( haystack, needle );
return !!wcsstr( haystack, needle );
}
const wchar_t *history_prev_match( const wchar_t *str )
{
if( !is_loaded )
history_load();
{
if( history_load() )
{
return 0;
}
}
if( history_current == 0 )
return str;
@@ -512,7 +565,13 @@ const wchar_t *history_prev_match( const wchar_t *str )
const wchar_t *history_next_match( const wchar_t *str)
{
if( !is_loaded )
history_load();
{
if( history_load() )
{
return 0;
}
}
if( history_current == 0 )
return str;
@@ -550,9 +609,15 @@ wchar_t *history_get( int idx )
{
ll_node_t *n;
int i;
if( !is_loaded )
history_load();
{
if( history_load() )
{
return 0;
}
}
n = history_last;
if( idx<0)

177
input.c
View File

@@ -1,5 +1,5 @@
/** \file input.c
a
Functions for reading a character of input from stdin, using the
inputrc information for key bindings.
@@ -59,8 +59,9 @@ implementation in fish is as of yet incomplete.
#include "expand.h"
#include "event.h"
#include "signal.h"
#include "translate.h"
#include "output.h"
#include "intern.h"
static void input_read_inputrc( wchar_t *fn );
@@ -71,9 +72,9 @@ static void input_read_inputrc( wchar_t *fn );
typedef struct
{
wchar_t *seq; /**< Character sequence which generates this event */
wchar_t *seq_desc; /**< Description of the character sequence suitable for printing on-screen */
wchar_t *command; /**< command that should be evaluated by this mapping */
const wchar_t *seq; /**< Character sequence which generates this event */
const wchar_t *seq_desc; /**< Description of the character sequence suitable for printing on-screen */
const wchar_t *command; /**< command that should be evaluated by this mapping */
}
mapping;
@@ -90,7 +91,7 @@ typedef struct
/**
Names of all the readline functions supported
*/
const wchar_t *name_arr[] =
static const wchar_t *name_arr[] =
{
L"beginning-of-line",
L"end-of-line",
@@ -120,14 +121,16 @@ const wchar_t *name_arr[] =
L"history-token-search-forward",
L"self-insert",
L"null",
L"eof"
L"eof",
L"vi-arg-digit"
}
;
/**
Description of each supported readline function
*/
const wchar_t *desc_arr[] =
/*
static const wchar_t *desc_arr[] =
{
L"Move to beginning of line",
L"Move to end of line",
@@ -157,14 +160,15 @@ const wchar_t *desc_arr[] =
L"Search forward through list of previous commands for matching token",
L"Insert the pressed key",
L"Do nothing",
L"End of file"
L"End of file",
L"Repeat command"
}
;
*/
/**
Internal code for each supported readline function
*/
const wchar_t code_arr[] =
static const wchar_t code_arr[] =
{
R_BEGINNING_OF_LINE,
R_END_OF_LINE,
@@ -194,7 +198,8 @@ const wchar_t code_arr[] =
R_HISTORY_TOKEN_SEARCH_FORWARD,
R_SELF_INSERT,
R_NULL,
R_EOF
R_EOF,
R_VI_ARG_DIGIT
}
;
@@ -231,9 +236,25 @@ static int inputrc_block_count=0;
*/
static int inputrc_error = 0;
/**
Set to one when the input subsytem has been initialized.
*/
static int is_init = 0;
wchar_t input_get_code( wchar_t *name )
/**
This is the variable telling us how many timew the next command
should bne repeated. Only actually used in vi-mode.
*/
static int repeat_count = 1;
/**
This is the type of the first command in a vi-mode two-part combo
like 'dw' or '3d3l'.
*/
static wint_t first_command = 0;
wchar_t input_get_code( const wchar_t *name )
{
int i;
@@ -250,7 +271,7 @@ wchar_t input_get_code( wchar_t *name )
/**
Returns the function name for the given function code.
*/
/*
static const wchar_t *input_get_name( wchar_t c )
{
@@ -264,7 +285,7 @@ static const wchar_t *input_get_name( wchar_t c )
}
return 0;
}
*/
/**
Returns the function description for the given function code.
*/
@@ -336,18 +357,16 @@ void add_mapping( const wchar_t *mode,
mapping *m = (mapping *)al_get( mappings, i );
if( wcscmp( m->seq, s ) == 0 )
{
free( m->command );
free( m->seq_desc );
m->seq_desc = wcsdup(d );
m->command=wcsdup(c);
m->seq_desc = intern(d);
m->command = intern(c);
return;
}
}
mapping *m = malloc( sizeof( mapping ) );
m->seq = wcsdup( s );
m->seq_desc = wcsdup(d );
m->command=wcsdup(c);
m->seq = intern( s );
m->seq_desc = intern(d );
m->command = intern(c);
al_push( mappings, m );
}
@@ -995,7 +1014,7 @@ void input_parse_inputrc_line( wchar_t *cmd )
{
if( wcscmp( key, L"editing-mode" ) == 0 )
{
// current_mode_mappings = get_mapping( value );
current_mode_mappings = get_mapping( value );
}
}
@@ -1128,6 +1147,9 @@ static void input_read_inputrc( wchar_t *fn )
}
}
free( buff );
/*
Don't need to check exit status of fclose on read-only stream
*/
fclose( rc );
}
signal_unblock();
@@ -1270,7 +1292,14 @@ static void add_emacs_bindings()
add_escaped_mapping( L"emacs", (L"\\C-h"), L"Control-h", L"backward-delete-char" );
add_escaped_mapping( L"emacs", (L"\\C-e"), L"Control-e", L"end-of-line" );
add_escaped_mapping( L"emacs", (L"\\C-w"), L"Control-w", L"backward-kill-word" );
add_escaped_mapping( L"emacs", (L"\\C-p"), L"Control-p", L"history-search-backward" );
add_escaped_mapping( L"emacs", (L"\\C-n"), L"Control-n", L"history-search-forward" );
add_escaped_mapping( L"emacs", (L"\\C-f"), L"Control-f", L"forward-char" );
add_escaped_mapping( L"emacs", (L"\\C-b"), L"Control-b", L"backward-char" );
add_escaped_mapping( L"emacs", (L"\e\x7f"), L"Alt-backspace", L"backward-kill-word" );
add_escaped_mapping( L"emacs", (L"\eb"), L"Alt-b", L"backward-word" );
add_escaped_mapping( L"emacs", (L"\ef"), L"Alt-f", L"forward-word" );
add_escaped_mapping( L"emacs", (L"\ed"), L"Alt-d", L"forward-kill-word" );
add_terminfo_mapping( L"emacs", (key_ppage), L"Page Up", L"beginning-of-history" );
add_terminfo_mapping( L"emacs", (key_npage), L"Page Down", L"end-of-history" );
}
@@ -1292,12 +1321,29 @@ static void add_vi_bindings()
add_mapping( L"vi-command", L"$", L"$", L"end-of-line" );
add_mapping( L"vi-command", L"^", L"^", L"beginning-of-line" );
add_mapping( L"vi-command", L"0", L"0", L"beginning-of-line" );
add_mapping( L"vi-command", L"b", L"b", L"backward-word" );
add_mapping( L"vi-command", L"B", L"B", L"backward-word" );
add_mapping( L"vi-command", L"w", L"w", L"forward-word" );
add_mapping( L"vi-command", L"W", L"W", L"forward-word" );
add_mapping( L"vi-command", L"x", L"x", L"delete-char" );
add_mapping( L"vi-command", L"1", L"1", L"vi-arg-digit" );
add_mapping( L"vi-command", L"2", L"2", L"vi-arg-digit" );
add_mapping( L"vi-command", L"3", L"3", L"vi-arg-digit" );
add_mapping( L"vi-command", L"4", L"4", L"vi-arg-digit" );
add_mapping( L"vi-command", L"5", L"5", L"vi-arg-digit" );
add_mapping( L"vi-command", L"6", L"6", L"vi-arg-digit" );
add_mapping( L"vi-command", L"7", L"7", L"vi-arg-digit" );
add_mapping( L"vi-command", L"8", L"8", L"vi-arg-digit" );
add_mapping( L"vi-command", L"9", L"9", L"vi-arg-digit" );
add_mapping( L"vi-command", L"d", L"d", L"vi-delete-to" );
add_mapping( L"vi-command", L"D", L"D", L"vi-delete-to" );
/*
movement ("h", "l"), word movement
("b", "B", "w", "W", "e", "E"), moving to beginning and end of line
@@ -1411,22 +1457,13 @@ int input_init()
/**
Free memory used by the specified mapping
*/
static void destroy_mapping( const void *key, const void *val )
static void destroy_mapping( void *key, void *val )
{
int i;
array_list_t *mappings = (array_list_t *)val;
for( i=0; i<al_get_count( mappings ); i++ )
{
mapping *m = (mapping *)al_get( mappings, i );
free( m->seq );
free( m->seq_desc );
free( m->command );
free(m );
}
al_foreach( mappings, &free );
al_destroy( mappings );
free((void *)key);
free((void *)val);
}
@@ -1452,6 +1489,8 @@ void input_destroy()
*/
static wint_t input_exec_binding( mapping *m, const wchar_t *seq )
{
int i;
// fwprintf( stderr, L"Binding %ls\n", m->command );
wchar_t code = input_get_code( m->command );
if( code != -1 )
@@ -1460,15 +1499,63 @@ static wint_t input_exec_binding( mapping *m, const wchar_t *seq )
{
case R_DUMP_FUNCTIONS:
{
dump_functions();
for( i=0; i<repeat_count; i++ )
dump_functions();
repeat_count = 1;
return R_NULL;
}
case R_SELF_INSERT:
{
for( i=1; i<repeat_count; i++ )
input_unreadch( seq[0] );
repeat_count = 1;
return seq[0];
}
case R_VI_ARG_DIGIT:
{
int repeat = seq[0]-L'0';
if( repeat > 0 && repeat <= 9 )
repeat_count *= repeat;
return R_NULL;
}
case R_VI_DELETE_TO:
{
first_command = R_VI_DELETE_TO;
return R_NULL;
}
default:
{
if( first_command )
{
switch( first_command )
{
case R_VI_DELETE_TO:
{
break;
}
}
}
else
{
for( i=1; i<repeat_count; i++ )
{
input_unreadch( code );
}
}
repeat_count = 1;
first_command = 0;
return code;
}
}
}
else
@@ -1507,6 +1594,13 @@ static wint_t input_try_mapping( mapping *m)
{
int j, k;
wint_t c=0;
c = input_common_readch( 0 );
if( c == input_get_code( m->command ) )
{
return input_exec_binding( m, m->seq );
}
input_unreadch( c );
if( m->seq != 0 )
{
@@ -1520,9 +1614,14 @@ static wint_t input_try_mapping( mapping *m)
}
else
{
/*
Return the read characters
*/
input_unreadch(c);
for(k=j-1; k>=0; k--)
input_unreadch(m->seq[k]);
for( k=j-1; k>=0; k-- )
{
input_unreadch( m->seq[k] );
}
}
}
return 0;

View File

@@ -44,6 +44,8 @@ enum
R_HISTORY_TOKEN_SEARCH_BACKWARD,
R_HISTORY_TOKEN_SEARCH_FORWARD,
R_SELF_INSERT,
R_VI_ARG_DIGIT,
R_VI_DELETE_TO
}
;
@@ -111,6 +113,6 @@ void input_parse_inputrc_line( wchar_t *cmd );
/**
Returns the function for the given function name.
*/
wchar_t input_get_code( wchar_t *name );
wchar_t input_get_code( const wchar_t *name );
#endif

View File

@@ -40,7 +40,7 @@ const wchar_t *intern( const wchar_t *in )
intern_table = malloc( sizeof( hash_table_t ) );
if( !intern_table )
{
die_mem();
DIE_MEM();
}
hash_init( intern_table, &hash_wcs_func, &hash_wcs_cmp );
}
@@ -59,7 +59,7 @@ const wchar_t *intern( const wchar_t *in )
res = wcsdup( in );
if( !res )
{
die_mem();
DIE_MEM();
}
hash_put( intern_table, res, res );
@@ -81,7 +81,7 @@ const wchar_t *intern_static( const wchar_t *in )
intern_static_table = malloc( sizeof( hash_table_t ) );
if( !intern_static_table )
{
die_mem();
DIE_MEM();
}
hash_init( intern_static_table, &hash_wcs_func, &hash_wcs_cmp );
}
@@ -100,7 +100,7 @@ const wchar_t *intern_static( const wchar_t *in )
/**
Free the specified key/value pair. Should only be called by intern_free_all at shutdown
*/
static void clear_value( const void *key, const void *data )
static void clear_value( void *key, void *data )
{
debug( 3, L"interned string: '%ls'", data );
free( (void *)data );

4
io.c
View File

@@ -39,7 +39,7 @@ Utilities for io redirection.
#include "exec.h"
#include "common.h"
#include "io.h"
#include "translate.h"
#include "halloc.h"
@@ -189,7 +189,7 @@ io_data_t *io_duplicate( void *context, io_data_t *l )
if( !res )
{
die_mem();
DIE_MEM();
}

3
io.h
View File

@@ -89,6 +89,9 @@ io_data_t *io_buffer_create();
*/
void io_buffer_read( io_data_t *d );
/**
Print debug information about the specified IO redirection chain to stderr.
*/
void io_print( io_data_t *io );
#endif

16
kill.c
View File

@@ -30,6 +30,7 @@
#include "env.h"
#include "exec.h"
#include "parser.h"
#include "halloc.h"
/**
Maximum entries in killring
@@ -48,14 +49,11 @@ static wchar_t *cut_buffer=0;
*/
static int has_xsel()
{
wchar_t *path = get_filename( L"xsel" );
if( path)
{
free(path);
return 1;
}
else
return 0;
void *context = halloc(0, 0);
wchar_t *path = parser_get_filename( context, L"xsel" );
int res = !!path;
halloc_free( context );
return res;
}
@@ -181,7 +179,7 @@ static void kill_check_x_buffer()
}
}
al_foreach( &list, (void (*)(const void *))&free );
al_foreach( &list, &free );
al_destroy( &list );
}
}

68
main.c
View File

@@ -3,8 +3,7 @@ Copyright (C) 2005 Axel Liljencrantz
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -59,7 +58,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "exec.h"
#include "event.h"
#include "output.h"
#include "translate.h"
#include "halloc_util.h"
#include "history.h"
@@ -82,17 +81,16 @@ static int read_init()
return 0;
}
env_set( L"__fish_help_dir", DOCDIR, 0);
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and . fish 2>/dev/null", 0, TOP );
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; and . fish 2>/dev/null", 0, TOP );
eval( L"builtin cd 2>/dev/null; and . .fish 2>/dev/null", 0, TOP );
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and builtin . fish 2>/dev/null", 0, TOP );
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; and builtin . fish 2>/dev/null", 0, TOP );
eval( L"builtin cd 2>/dev/null; and builtin . .fish 2>/dev/null", 0, TOP );
if( chdir( cwd ) == -1 )
{
// fwprintf( stderr, L"Invalid directory: %s\n", cwd );
// wperror( L"chdir" );
// return 0;
/*
If we can't change back to previos directory, we'll stay in
~. Should be a sane default behavior.
*/
}
wcwd = str2wcs( cwd );
if( wcwd )
@@ -117,6 +115,8 @@ int main( int argc, char **argv )
char *cmd=0;
halloc_util_init();
wsetlocale( LC_ALL, L"" );
is_interactive_session=1;
program_name=L"fish";
@@ -184,13 +184,17 @@ int main( int argc, char **argv )
switch( opt )
{
case 0:
{
break;
}
case 'c':
{
cmd = optarg;
is_interactive_session = 0;
break;
}
case 'd':
{
char *end;
@@ -208,35 +212,49 @@ int main( int argc, char **argv )
}
case 'h':
{
cmd = "help";
break;
}
case 'i':
{
force_interactive = 1;
break;
}
case 'l':
{
is_login=1;
break;
}
case 'n':
{
no_exec=1;
break;
}
case 'p':
{
profile = optarg;
break;
}
case 'v':
{
fwprintf( stderr,
_(L"%s, version %s\n"),
PACKAGE_NAME,
PACKAGE_VERSION );
exit( 0 );
}
case '?':
{
return 1;
}
}
}
@@ -258,8 +276,6 @@ int main( int argc, char **argv )
no_exec = 0;
}
common_init();
halloc_util_init();
proc_init();
event_init();
@@ -268,7 +284,6 @@ int main( int argc, char **argv )
builtin_init();
function_init();
env_init();
complete_init();
reader_init();
history_init();
@@ -342,10 +357,9 @@ int main( int argc, char **argv )
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
history_destroy();
complete_destroy();
proc_destroy();
env_destroy();
builtin_destroy();
function_destroy();
reader_destroy();
@@ -353,8 +367,10 @@ int main( int argc, char **argv )
wutil_destroy();
event_destroy();
common_destroy();
halloc_util_destroy();
env_destroy();
intern_free_all();

View File

@@ -548,6 +548,9 @@ static char *get_description( const char *mimetype )
return 0;
}
/*
Don't need to check exit status of close on read-only file descriptors
*/
close( fd );
free( fn );
@@ -1120,7 +1123,7 @@ static void launch( char *filter, array_list_t *files, int fileno )
/**
Clean up one entry from the hash table of launch files
*/
static void clear_entry( const void *key, const void *val )
static void clear_entry( void *key, void *val )
{
/*
The key is a mime value, either from the libraries internal hash

View File

@@ -113,6 +113,9 @@ static char *writestr_buff = 0;
static int (*out)(char c) = &writeb_internal;
/**
Cleanup function. Run automatically through halloc
*/
static void output_destroy()
{
free( writestr_buff );
@@ -120,6 +123,7 @@ static void output_destroy()
void output_set_writer( int (*writer)(char) )
{
CHECK( writer, );
out = writer;
}
@@ -129,18 +133,21 @@ void set_color( int c, int c2 )
static int last_color = FISH_COLOR_NORMAL;
static int last_color2 = FISH_COLOR_NORMAL;
static int was_bold=0;
static int was_underline=0;
int bg_set=0, last_bg_set=0;
char *fg = 0, *bg=0;
int is_bold = 0;
int is_underline = 0;
is_bold |= (c&FISH_COLOR_BOLD)!=0;
is_bold |= (c2&FISH_COLOR_BOLD)!=0;
// debug( 1, L"WOO %d %d %d", is_bold, c&FISH_COLOR_BOLD,c2&FISH_COLOR_BOLD);
is_underline |= (c&FISH_COLOR_UNDERLINE)!=0;
is_underline |= (c2&FISH_COLOR_UNDERLINE)!=0;
c = c&(~FISH_COLOR_BOLD);
c2 = c2&(~FISH_COLOR_BOLD);
c = c&(~(FISH_COLOR_BOLD|FISH_COLOR_UNDERLINE));
c2 = c2&(~(FISH_COLOR_BOLD|FISH_COLOR_UNDERLINE));
if( (set_a_foreground != 0) && (strlen( set_a_foreground) != 0 ) )
{
@@ -157,6 +164,7 @@ void set_color( int c, int c2 )
{
c = c2 = FISH_COLOR_NORMAL;
was_bold=0;
was_underline=0;
if( fg )
{
/*
@@ -179,6 +187,7 @@ void set_color( int c, int c2 )
last_color = FISH_COLOR_NORMAL;
last_color2 = FISH_COLOR_NORMAL;
was_bold=0;
was_underline=0;
}
if( last_color2 != FISH_COLOR_NORMAL &&
@@ -219,6 +228,8 @@ void set_color( int c, int c2 )
exit bold mode
*/
writembs( exit_attribute_mode );
was_bold=0;
was_underline=0;
/*
We don't know if exit_attribute_mode resets colors, so
we set it to something known.
@@ -242,6 +253,8 @@ void set_color( int c, int c2 )
writembs( exit_attribute_mode );
last_color2 = FISH_COLOR_NORMAL;
was_bold=0;
was_underline=0;
}
else if( ( c >= 0 ) && ( c < FISH_COLOR_NORMAL ) )
{
@@ -269,6 +282,8 @@ void set_color( int c, int c2 )
writembs( tparm( fg, last_color ) );
}
was_bold=0;
was_underline=0;
last_color2 = c2;
}
else if ( ( c2 >= 0 ) && ( c2 < FISH_COLOR_NORMAL ) )
@@ -282,7 +297,7 @@ void set_color( int c, int c2 )
}
/*
Lastly, we set bold mode correctly
Lastly, we set bold mode and underline mode correctly
*/
if( (enter_bold_mode != 0) && (strlen(enter_bold_mode) > 0) && !bg_set )
{
@@ -292,6 +307,18 @@ void set_color( int c, int c2 )
}
was_bold = is_bold;
}
if( was_underline && !is_underline )
{
writembs( exit_underline_mode );
}
if( !was_underline && is_underline )
{
writembs( enter_underline_mode );
}
was_underline = is_underline;
}
@@ -322,6 +349,9 @@ void move_cursor( int steps )
}
}
/**
Default output method, simply calls write() on stdout
*/
static int writeb_internal( char c )
{
write( 1, &c, 1 );
@@ -336,6 +366,8 @@ int writeb( tputs_arg_t b )
int writembs( char *str )
{
CHECK( str, 1 );
return tputs(str,1,&writeb)==ERR?1:0;
}
@@ -376,6 +408,8 @@ int writech( wint_t ch )
void writestr( const wchar_t *str )
{
char *pos;
CHECK( str, );
// while( *str )
// writech( *str++ );
@@ -406,7 +440,7 @@ void writestr( const wchar_t *str )
writestr_buff = realloc( writestr_buff, len );
if( !writestr_buff )
{
die_mem();
DIE_MEM();
}
writestr_buff_sz = len;
}
@@ -431,7 +465,11 @@ void writestr( const wchar_t *str )
void writestr_ellipsis( const wchar_t *str, int max_width )
{
int written=0;
int tot = my_wcswidth(str);
int tot;
CHECK( str, );
tot = my_wcswidth(str);
if( tot <= max_width )
{
@@ -463,11 +501,16 @@ void writestr_ellipsis( const wchar_t *str, int max_width )
int write_escaped_str( const wchar_t *str, int max_len )
{
wchar_t *out = escape( str, 1 );
wchar_t *out;
int i;
int len = my_wcswidth( out );
int len;
int written=0;
CHECK( str, 0 );
out = escape( str, 1 );
len = my_wcswidth( out );
if( max_len && (max_len < len))
{
for( i=0; (written+wcwidth(out[i]))<=(max_len-1); i++ )
@@ -519,6 +562,7 @@ int output_color_code( const wchar_t *val )
int j, i, color=FISH_COLOR_NORMAL;
array_list_t el;
int is_bold=0;
int is_underline=0;
if( !val )
return FISH_COLOR_NORMAL;
@@ -531,7 +575,10 @@ int output_color_code( const wchar_t *val )
wchar_t *next = (wchar_t *)al_get( &el, j );
is_bold |= (wcsncmp( next, L"--bold", wcslen(next) ) == 0 ) && wcslen(next)>=3;
is_bold |= wcscmp( next, L"-b" ) == 0;
is_bold |= wcscmp( next, L"-o" ) == 0;
is_underline |= (wcsncmp( next, L"--underline", wcslen(next) ) == 0 ) && wcslen(next)>=3;
is_underline |= wcscmp( next, L"-u" ) == 0;
for( i=0; i<COLORS; i++ )
{
@@ -544,9 +591,9 @@ int output_color_code( const wchar_t *val )
}
al_foreach( &el, (void (*)(const void *))&free );
al_foreach( &el, &free );
al_destroy( &el );
return color | (is_bold?FISH_COLOR_BOLD:0);
return color | (is_bold?FISH_COLOR_BOLD:0) | (is_underline?FISH_COLOR_UNDERLINE:0);
}

View File

@@ -10,23 +10,6 @@
#include <wchar.h>
enum
{
HIGHLIGHT_NORMAL,
HIGHLIGHT_COMMAND,
HIGHLIGHT_REDIRECTION,
HIGHLIGHT_END,
HIGHLIGHT_ERROR,
HIGHLIGHT_PARAM,
HIGHLIGHT_COMMENT,
HIGHLIGHT_MATCH,
HIGHLIGHT_SEARCH_MATCH,
HIGHLIGHT_OPERATOR,
HIGHLIGHT_ESCAPE,
HIGHLIGHT_QUOTE,
}
;
/**
Constants for various colors as used by the set_color function.
*/
@@ -47,7 +30,14 @@ enum
}
;
/**
The value to send to set_color to tell it to use a bold font
*/
#define FISH_COLOR_BOLD 0x80
/**
The value to send to set_color to tell it to underline the text
*/
#define FISH_COLOR_UNDERLINE 0x100
/**
Sets the fg and bg color. May be called as often as you like, since

View File

@@ -29,9 +29,36 @@
#include "intern.h"
#include "exec.h"
#include "env.h"
#include "wildcard.h"
#include "halloc_util.h"
/**
A structure representing the autoload state for a specific variable, e.g. fish_complete_path
*/
typedef struct
{
/**
A table containing the modification times of all loaded
files. Failed loads (non-existing files) have modification time
0.
*/
hash_table_t load_time;
/**
A string containg the path used to find any files to load. If
this differs from the current environment variable, the
autoloader needs to drop all loaded files and reload them.
*/
wchar_t *old_path;
/**
A table containing all the files that are currently being
loaded. This is here to help prevent recursion.
*/
hash_table_t is_loading;
}
autoload_t;
/**
Set of files which have been autoloaded
*/
@@ -42,22 +69,25 @@ int parse_util_lineno( const wchar_t *str, int len )
/**
First cached state
*/
static const wchar_t *prev_str = 0;
static wchar_t *prev_str = 0;
static int i=0;
static int res = 1;
/**
Second cached state
*/
static const wchar_t *prev_str2 = 0;
static wchar_t *prev_str2 = 0;
static int i2 = 0;
static int res2 = 1;
CHECK( str, 0 );
if( str != prev_str || i>len )
{
if( prev_str2 == str && i2 <= len )
{
const wchar_t *tmp_str = prev_str;
wchar_t *tmp_str = prev_str;
int tmp_i = i;
int tmp_res = res;
prev_str = prev_str2;
@@ -74,7 +104,7 @@ int parse_util_lineno( const wchar_t *str, int len )
i2 = i;
res2=res;
prev_str = str;
prev_str = (wchar_t *)str;
i=0;
res=1;
}
@@ -89,30 +119,34 @@ int parse_util_lineno( const wchar_t *str, int len )
}
int parse_util_locate_cmdsubst( const wchar_t *in,
const wchar_t **begin,
const wchar_t **end,
wchar_t **begin,
wchar_t **end,
int allow_incomplete )
{
const wchar_t *pos;
wchar_t *pos;
wchar_t prev=0;
int syntax_error=0;
int paran_count=0;
const wchar_t *paran_begin=0, *paran_end=0;
wchar_t *paran_begin=0, *paran_end=0;
for( pos=in; *pos; pos++ )
CHECK( in, 0 );
for( pos = (wchar_t *)in; *pos; pos++ )
{
if( prev != '\\' )
{
if( wcschr( L"\'\"", *pos ) )
{
const wchar_t *end = quote_end( pos );
if( end && *end)
wchar_t *q_end = quote_end( pos );
if( q_end && *q_end)
{
pos=end;
pos=q_end;
}
else
{
break;
}
}
else
{
@@ -141,7 +175,6 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
}
}
prev = *pos;
}
@@ -161,7 +194,7 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
if( begin )
*begin = paran_begin;
if( end )
*end = paran_count?in+wcslen(in):paran_end;
*end = paran_count?(wchar_t *)in+wcslen(in):paran_end;
return 1;
}
@@ -169,55 +202,58 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
void parse_util_cmdsubst_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **a,
const wchar_t **b )
wchar_t **a,
wchar_t **b )
{
const wchar_t *begin, *end;
const wchar_t *pos;
wchar_t *begin, *end;
wchar_t *pos;
const wchar_t *cursor = buff + cursor_pos;
CHECK( buff, );
if( a )
*a=0;
*a = (wchar_t *)buff;
if( b )
*b = 0;
if( !buff )
return;
pos = buff;
*b = (wchar_t *)buff+wcslen(buff);
pos = (wchar_t *)buff;
while( 1 )
{
int bc, ec;
if( parse_util_locate_cmdsubst( pos,
&begin,
&end,
1 ) <= 0)
{
begin=buff;
end = buff + wcslen(buff);
/*
No subshell found
*/
break;
}
if( !end )
{
end = buff + wcslen(buff);
end = (wchar_t *)buff + wcslen(buff);
}
bc = begin-buff;
ec = end-buff;
if(( bc < cursor_pos ) && (ec >= cursor_pos) )
if(( begin < cursor ) && (end >= cursor) )
{
begin++;
if( a )
*a = begin;
if( b )
*b = end;
break;
}
if( !*end )
{
break;
}
pos = end+1;
}
if( a )
*a = begin;
if( b )
*b = end;
}
/**
@@ -225,17 +261,19 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
*/
static void job_or_process_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **a,
const wchar_t **b,
wchar_t **a,
wchar_t **b,
int process )
{
const wchar_t *begin, *end;
wchar_t *begin, *end;
int pos;
wchar_t *buffcpy;
int finished=0;
tokenizer tok;
CHECK( buff, );
if( a )
*a=0;
if( b )
@@ -261,7 +299,7 @@ static void job_or_process_extent( const wchar_t *buff,
if( !buffcpy )
{
die_mem();
DIE_MEM();
}
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
@@ -284,12 +322,12 @@ static void job_or_process_extent( const wchar_t *buff,
{
finished=1;
if( b )
*b = buff + tok_begin;
*b = (wchar_t *)buff + tok_begin;
}
else
{
if( a )
*a = buff + tok_begin+1;
*a = (wchar_t *)buff + tok_begin+1;
}
break;
@@ -305,16 +343,16 @@ static void job_or_process_extent( const wchar_t *buff,
void parse_util_process_extent( const wchar_t *buff,
int pos,
const wchar_t **a,
const wchar_t **b )
wchar_t **a,
wchar_t **b )
{
job_or_process_extent( buff, pos, a, b, 1 );
}
void parse_util_job_extent( const wchar_t *buff,
int pos,
const wchar_t **a,
const wchar_t **b )
wchar_t **a,
wchar_t **b )
{
job_or_process_extent( buff,pos,a, b, 0 );
}
@@ -322,19 +360,22 @@ void parse_util_job_extent( const wchar_t *buff,
void parse_util_token_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **tok_begin,
const wchar_t **tok_end,
const wchar_t **prev_begin,
const wchar_t **prev_end )
wchar_t **tok_begin,
wchar_t **tok_end,
wchar_t **prev_begin,
wchar_t **prev_end )
{
const wchar_t *begin, *end;
wchar_t *begin, *end;
int pos;
wchar_t *buffcpy;
tokenizer tok;
const wchar_t *a, *b, *pa, *pb;
wchar_t *a, *b, *pa, *pb;
CHECK( buff, );
assert( cursor_pos >= 0 );
a = b = pa = pb = 0;
@@ -342,24 +383,24 @@ void parse_util_token_extent( const wchar_t *buff,
if( !end || !begin )
return;
pos = cursor_pos - (begin - buff);
a = buff + pos;
a = (wchar_t *)buff + pos;
b = a;
pa = buff + pos;
pa = (wchar_t *)buff + pos;
pb = pa;
assert( begin >= buff );
assert( begin <= (buff+wcslen(buff) ) );
assert( end >= begin );
assert( end <= (buff+wcslen(buff) ) );
buffcpy = wcsndup( begin, end-begin );
if( !buffcpy )
{
die_mem();
DIE_MEM();
}
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
@@ -382,7 +423,7 @@ void parse_util_token_extent( const wchar_t *buff,
*/
if( tok_begin > pos )
{
a = b = buff + pos;
a = b = (wchar_t *)buff + pos;
break;
}
@@ -390,11 +431,11 @@ void parse_util_token_extent( const wchar_t *buff,
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 )
{
if( (tok_last_type( &tok ) == TOK_STRING) && (tok_end >= pos ) )
{
a = begin + tok_get_pos( &tok );
b = a + wcslen(tok_last(&tok));
// fwprintf( stderr, L"Whee %ls\n", *a );
break;
@@ -433,20 +474,33 @@ void parse_util_token_extent( const wchar_t *buff,
/**
Free hash value, but not hash key
*/
static void clear_hash_value( const void *key, const void *data )
static void clear_hash_value( void *key, void *data, void *aux )
{
if( aux )
{
wchar_t *name = (wchar_t *)key;
void (*handler)(const wchar_t *)= (void (*)(const wchar_t *))aux;
handler( name );
}
free( (void *)data );
}
/**
Part of the autoloader cleanup
*/
static void clear_loaded_entry( const void *key, const void *data )
static void clear_loaded_entry( void *key,
void *data,
void *handler )
{
hash_table_t *loaded = (hash_table_t *)data;
hash_foreach( loaded,
&clear_hash_value );
hash_destroy( loaded );
autoload_t *loaded = (autoload_t *)data;
hash_foreach2( &loaded->load_time,
&clear_hash_value,
handler );
hash_destroy( &loaded->load_time );
hash_destroy( &loaded->is_loading );
free( loaded->old_path );
free( loaded );
free( (void *)key );
}
@@ -460,8 +514,9 @@ static void parse_util_destroy()
{
if( all_loaded )
{
hash_foreach( all_loaded,
&clear_loaded_entry );
hash_foreach2( all_loaded,
&clear_loaded_entry,
0 );
hash_destroy( all_loaded );
free( all_loaded );
@@ -469,18 +524,61 @@ static void parse_util_destroy()
}
}
void parse_util_load_reset( const wchar_t *path_var )
void parse_util_load_reset( const wchar_t *path_var_name,
void (*on_load)(const wchar_t *cmd) )
{
wchar_t *path_var;
CHECK( path_var_name, );
path_var = env_get( path_var_name );
if( !path_var )
return;
if( all_loaded )
{
void *key, *data;
hash_remove( all_loaded, path_var, (const void **)&key, (const void **)&data );
hash_remove( all_loaded, path_var_name, &key, &data );
if( key )
clear_loaded_entry( key, data );
clear_loaded_entry( key, data, (void *)on_load );
}
}
int parse_util_unload( const wchar_t *cmd,
const wchar_t *path_var_name,
void (*on_load)(const wchar_t *cmd) )
{
autoload_t *loaded;
void *val;
CHECK( path_var_name, 0 );
CHECK( cmd, 0 );
if( !all_loaded )
{
return 0;
}
loaded = (autoload_t *)hash_get( all_loaded, path_var_name );
if( !loaded )
{
return 0;
}
hash_remove( &loaded->load_time, cmd, 0, &val );
if( val )
{
if( on_load )
{
on_load( (wchar_t *)val );
}
free( val );
}
return !!val;
}
int parse_util_load( const wchar_t *cmd,
const wchar_t *path_var_name,
@@ -493,16 +591,22 @@ int parse_util_load( const wchar_t *cmd,
int i;
time_t *tm;
int reloaded = 0;
hash_table_t *loaded;
autoload_t *loaded;
const wchar_t *path_var = env_get( path_var_name );
wchar_t *path_var;
CHECK( path_var_name, 0 );
CHECK( cmd, 0 );
path_var = env_get( path_var_name );
/*
Do we know where to look
*/
if( !path_var )
{
return 0;
}
if( !all_loaded )
{
@@ -510,28 +614,57 @@ int parse_util_load( const wchar_t *cmd,
halloc_register_function_void( global_context, &parse_util_destroy );
if( !all_loaded )
{
die_mem();
DIE_MEM();
}
hash_init( all_loaded, &hash_wcs_func, &hash_wcs_cmp );
}
loaded = (hash_table_t *)hash_get( all_loaded, path_var_name );
if( !loaded )
loaded = (autoload_t *)hash_get( all_loaded, path_var_name );
if( loaded )
{
loaded = malloc( sizeof( hash_table_t ) );
if( hash_get( &loaded->is_loading, cmd ) )
{
debug( 0, _(L"Could not autoload item %ls, it is already being autoloaded. This is a circular dependency in the autoloading scripts, please remove it."), cmd );
return 1;
}
/*
Check if the lookup path has changed. If so, drop all loaded
files and start from scratch.
*/
if( wcscmp( path_var, loaded->old_path ) != 0 )
{
parse_util_load_reset( path_var_name, on_load);
reload = parse_util_load( cmd, path_var_name, on_load, reload );
return reload;
}
}
else
{
/*
We have never tried to autoload using this name before, set up initial data
*/
loaded = malloc( sizeof( autoload_t ) );
if( !loaded )
{
die_mem();
DIE_MEM();
}
hash_init( loaded, &hash_wcs_func, &hash_wcs_cmp );
hash_init( &loaded->load_time, &hash_wcs_func, &hash_wcs_cmp );
hash_put( all_loaded, wcsdup(path_var_name), loaded );
hash_init( &loaded->is_loading, &hash_wcs_func, &hash_wcs_cmp );
loaded->old_path = wcsdup( path_var );
}
hash_put( &loaded->is_loading, cmd, cmd );
/*
Get modification time of file
*/
tm = (time_t *)hash_get( loaded, cmd );
tm = (time_t *)hash_get( &loaded->load_time, cmd );
/*
Did we just check this?
@@ -540,6 +673,7 @@ int parse_util_load( const wchar_t *cmd,
{
if(time(0)-tm[1]<=1)
{
hash_remove( &loaded->is_loading, cmd, 0, 0 );
return 0;
}
}
@@ -548,7 +682,10 @@ int parse_util_load( const wchar_t *cmd,
Return if already loaded and we are skipping reloading
*/
if( !reload && tm )
{
hash_remove( &loaded->is_loading, cmd, 0, 0 );
return 0;
}
if( !path_list )
path_list = al_halloc( global_context);
@@ -581,12 +718,12 @@ int parse_util_load( const wchar_t *cmd,
{
tm = malloc(sizeof(time_t)*2);
if( !tm )
die_mem();
DIE_MEM();
}
tm[0] = buf.st_mtime;
tm[1] = time(0);
hash_put( loaded,
hash_put( &loaded->load_time,
intern( cmd ),
tm );
@@ -615,16 +752,17 @@ int parse_util_load( const wchar_t *cmd,
{
tm = malloc(sizeof(time_t)*2);
if( !tm )
die_mem();
DIE_MEM();
tm[0] = 0;
tm[1] = time(0);
hash_put( loaded, intern( cmd ), tm );
hash_put( &loaded->load_time, intern( cmd ), tm );
}
al_foreach( path_list, (void (*)(const void *))&free );
al_foreach( path_list, &free );
al_truncate( path_list, 0 );
hash_remove( &loaded->is_loading, cmd, 0, 0 );
return reloaded;
}
@@ -655,10 +793,14 @@ void parse_util_set_argv( wchar_t **argv )
wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
{
wchar_t *in, *out;
wchar_t *unescaped = wcsdup(str);
wchar_t *unescaped;
CHECK( str, 0 );
unescaped = wcsdup(str);
if( !unescaped )
die_mem();
DIE_MEM();
for( in=out=unescaped; *in; in++ )
{

View File

@@ -20,12 +20,16 @@
*/
int parse_util_locate_cmdsubst( const wchar_t *in,
const wchar_t **begin,
const wchar_t **end,
int allow_incomplete );
wchar_t **begin,
wchar_t **end,
int flags );
/**
Find the beginning and end of the command substitution under the cursor
Find the beginning and end of the command substitution under the
cursor. If no subshell is found, the entire string is returned. If
the current command substitution is not ended, i.e. the closing
parenthesis is missing, then the string from the beginning of the
substitution to the end of the string is returned.
\param buff the string to search for subshells
\param cursor_pos the position of the cursor
@@ -34,8 +38,8 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
*/
void parse_util_cmdsubst_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **a,
const wchar_t **b );
wchar_t **a,
wchar_t **b );
/**
Find the beginning and end of the process definition under the cursor
@@ -47,8 +51,8 @@ void parse_util_cmdsubst_extent( const wchar_t *buff,
*/
void parse_util_process_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **a,
const wchar_t **b );
wchar_t **a,
wchar_t **b );
/**
@@ -61,23 +65,27 @@ void parse_util_process_extent( const wchar_t *buff,
*/
void parse_util_job_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **a,
const wchar_t **b );
wchar_t **a,
wchar_t **b );
/**
Find the beginning and end of the token under the cursor
Find the beginning and end of the token under the cursor and the
toekn before the current token. Any combination of tok_begin,
tok_end, prev_begin and prev_end may be null.
\param buff the string to search for subshells
\param cursor_pos the position of the cursor
\param a the start of the searched string
\param b the end of the searched string
\param tok_begin the start of the current token
\param tok_end the end of the current token
\param prev_begin the start o the token before the current token
\param prev_end the end of the token before the current token
*/
void parse_util_token_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **tok_begin,
const wchar_t **tok_end,
const wchar_t **prev_begin,
const wchar_t **prev_end );
wchar_t **tok_begin,
wchar_t **tok_end,
wchar_t **prev_begin,
wchar_t **prev_end );
/**
@@ -87,10 +95,11 @@ int parse_util_lineno( const wchar_t *str, int len );
/**
Autoload the specified file, if it exists in the specified path. Do
not load it multiple times unless it's timestamp changes.
not load it multiple times unless it's timestamp changes or
parse_util_unload is called.
\param cmd the filename to search for. The suffix '.fish' is always added to this name
\param path_var_name the name of an environment variable containing a search path
\param path_var_name the environment variable giving the search path
\param on_load a callback function to run if a suitable file is found, which has not already been run
\param reload wheter to recheck file timestamps on already loaded files
*/
@@ -100,9 +109,28 @@ int parse_util_load( const wchar_t *cmd,
int reload );
/**
Reset the loader for the specified path variable
Reset the loader for the specified path variable. This will cause
all information on loaded files in the specified directory to be
reset.
\param path_var_name the environment variable giving the search path
\param on_load the callback function to use when a file is reloaded
\param on_load the callback function to call if the file has been previously loaded
*/
void parse_util_load_reset( const wchar_t *path_var );
void parse_util_load_reset( const wchar_t *path_var_name,
void (*on_load)(const wchar_t *cmd) );
/**
Tell the autoloader that the specified file, in the specified path,
is no longer loaded.
\param cmd the filename to search for. The suffix '.fish' is always added to this name
\param path_var_name the environment variable giving the search path
\return non-zero if the file was removed, zero if the file had not yet been loaded
*/
int parse_util_unload( const wchar_t *cmd,
const wchar_t *path_var_name,
void (*on_load)(const wchar_t *cmd) );
/**
Set the argv environment variable to the specified null-terminated

738
parser.c

File diff suppressed because it is too large Load Diff

View File

@@ -191,10 +191,6 @@ extern block_t *current_block;
/** Global event blocks */
extern event_block_t *global_event_block;
/** The current error code */
extern int error_code;
/**
Current block level io redirections
*/
@@ -204,9 +200,10 @@ extern io_data_t *block_io;
Finds the full path of an executable in a newly allocated string.
\param cmd The name of the executable.
\param context the halloc context to use for memory allocations
\return 0 if the command can not be found, the path of the command otherwise.
*/
wchar_t *get_filename( const wchar_t *cmd );
wchar_t *parser_get_filename( void *context, const wchar_t *cmd );
/**
Evaluate the expressions contained in cmd.
@@ -320,7 +317,7 @@ const wchar_t *parser_get_block_desc( int block );
contains errors, and the second bit is set if the string contains
an unclosed block.
*/
int parser_test( const wchar_t * buff, int babble );
int parser_test( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix );
/**
Test if the specified string can be parsed as an argument list,
@@ -328,7 +325,7 @@ int parser_test( const wchar_t * buff, int babble );
string contains errors, and the second bit is set if the string
contains an unclosed block.
*/
int parser_test_args( const wchar_t * buff, int babble );
int parser_test_args( const wchar_t * buff, string_buffer_t *out, const wchar_t *prefix );
/**
Returns the full path of the specified directory. If the \c in is a
@@ -337,7 +334,7 @@ int parser_test_args( const wchar_t * buff, int babble );
directories i the CDPATH, the full path is returned. If no
directory can be found, 0 is returned.
*/
wchar_t *parser_cdpath_get( wchar_t *in );
wchar_t *parser_cdpath_get( void *context, wchar_t *in );
/**
Tell the parser that the specified function may not be run if not

11257
po/en.po Normal file

File diff suppressed because it is too large Load Diff

1636
po/fr.po Normal file

File diff suppressed because it is too large Load Diff

1491
po/sv.po

File diff suppressed because it is too large Load Diff

26
proc.c
View File

@@ -55,7 +55,7 @@ Some of the code in this file is based on code from the Glibc manual.
#include "parser.h"
#include "signal.h"
#include "event.h"
#include "translate.h"
#include "halloc.h"
#include "halloc_util.h"
#include "output.h"
@@ -108,6 +108,9 @@ static string_buffer_t event_pid;
*/
static string_buffer_t event_status;
/**
A stack containing the values of is_interactive. Used by proc_push_interactive and proc_pop_interactive.
*/
static array_list_t *interactive_stack;
void proc_init()
@@ -171,6 +174,7 @@ void proc_destroy()
void proc_set_last_status( int s )
{
last_status = s;
// fwprintf( stderr, L"Set last status to %d\n", s );
}
@@ -253,7 +257,7 @@ int job_is_stopped( const job_t *j )
/*
Return true if all processes in the job have completed.
Return true if the last processes in the job has completed.
\param j the job to test
*/
@@ -261,14 +265,11 @@ int job_is_completed( const job_t *j )
{
process_t *p;
for (p = j->first_process; p; p = p->next)
{
if (!p->completed)
{
return 0;
}
}
return 1;
for (p = j->first_process; p->next; p = p->next)
;
return p->completed;
}
/**
@@ -691,6 +692,10 @@ unsigned long proc_get_jiffies( process_t *p )
{
return 0;
}
/*
Don't need to check exit status of fclose on read-only streams
*/
fclose( f );
return utime+stime+cutime+cstime;
@@ -1005,6 +1010,7 @@ void job_continue (job_t *j, int cont)
signal_unblock();
}
}
}
void proc_sanity_check()

8
proc.h
View File

@@ -276,7 +276,7 @@ job_t *job_get_from_pid(int pid);
int job_is_stopped( const job_t *j );
/**
Tests if the job has completed
Tests if the job has completed, i.e. if the last process of the pipeline has ended.
*/
int job_is_completed( const job_t *j );
@@ -291,15 +291,15 @@ int job_is_completed( const job_t *j );
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.
Notify the user about stopped or terminated jobs. Delete terminated
jobs from the job list.
\param interactive whether interactive jobs should be reaped as well
*/
int job_reap( int interactive );
/**
Signal handler for SIGCHLD. Mark any processes with relevant
Signal handler for SIGCHLD. Mark any processes with relevant
information.
*/
void job_handle_signal( int signal, siginfo_t *info, void *con );

124
reader.c
View File

@@ -82,7 +82,7 @@ commence.
#include "function.h"
#include "output.h"
#include "signal.h"
#include "translate.h"
#include "parse_util.h"
/**
@@ -449,7 +449,7 @@ static int check_size()
data->color==0 ||
data->new_color == 0 )
{
die_mem();
DIE_MEM();
}
}
@@ -609,8 +609,8 @@ static void remove_duplicates( array_list_t *l )
*/
static void set_color_translated( int c )
{
set_color( highlight_get_color( c & 0xff ),
highlight_get_color( (c>>8)&0xff ) );
set_color( highlight_get_color( c & 0xffff ),
highlight_get_color( (c>>16)&0xffff ) );
}
int reader_interupted()
@@ -660,7 +660,7 @@ void reader_write_title()
}
proc_pop_interactive();
al_foreach( &l, (void (*)(const void *))&free );
al_foreach( &l, &free );
al_destroy( &l );
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
}
@@ -712,7 +712,8 @@ static int calc_prompt_width( array_list_t *arr )
int found = 0;
/*
Test these color escapes with parameter value 0..7
Detect these terminfo color escapes with parameter
value 0..7, all of which don't move the cursor
*/
char * esc[] =
{
@@ -724,7 +725,8 @@ static int calc_prompt_width( array_list_t *arr )
;
/*
Test these regular escapes without any parameter values
Detect these semi-common terminfo escapes without any
parameter values, all of which don't move the cursor
*/
char *esc2[] =
{
@@ -734,7 +736,20 @@ static int calc_prompt_width( array_list_t *arr )
exit_underline_mode,
enter_standout_mode,
exit_standout_mode,
flash_screen
flash_screen,
enter_subscript_mode,
exit_subscript_mode,
enter_superscript_mode,
exit_superscript_mode,
enter_blink_mode,
enter_italics_mode,
exit_italics_mode,
enter_reverse_mode,
enter_shadow_mode,
exit_shadow_mode,
enter_standout_mode,
exit_standout_mode,
enter_secure_mode
}
;
@@ -766,7 +781,7 @@ static int calc_prompt_width( array_list_t *arr )
*/
len = maxi( try_sequence( tparm(esc2[l]), &next[j] ),
try_sequence( esc2[l], &next[j] ));
if( len )
{
j += (len-1);
@@ -774,6 +789,10 @@ static int calc_prompt_width( array_list_t *arr )
}
}
}
else if( next[j] == L'\t' )
{
res=(res+8)&~7;
}
else
{
/*
@@ -781,7 +800,6 @@ static int calc_prompt_width( array_list_t *arr )
*/
res += wcwidth( next[j] );
}
}
}
return res;
@@ -804,7 +822,7 @@ static void write_prompt()
if( data->exec_prompt )
{
al_foreach( &prompt_list, (void (*)(const void *))&free );
al_foreach( &prompt_list, &free );
al_truncate( &prompt_list, 0 );
if( data->prompt )
@@ -814,7 +832,7 @@ static void write_prompt()
if( exec_subshell( data->prompt, &prompt_list ) == -1 )
{
/* If executing the prompt fails, make sure we at least don't print any junk */
al_foreach( &prompt_list, (void (*)(const void *))&free );
al_foreach( &prompt_list, &free );
al_destroy( &prompt_list );
al_init( &prompt_list );
}
@@ -944,7 +962,6 @@ static void check_colors()
static void reader_save_status()
{
#ifdef HAVE_FUTIMES
/*
This futimes call tries to trick the system into using st_mtime
as a tampering flag. This of course only works on systems where
@@ -965,9 +982,13 @@ static void reader_save_status()
}
;
/*
Don't check return value on these. We don't care if they fail,
really. This is all just to make the prompt look ok, which is
impossible to do 100% reliably. We try, at least.
*/
futimes( 1, t );
futimes( 2, t );
#endif
fstat( 1, &prev_buff_1 );
fstat( 2, &prev_buff_2 );
@@ -1674,7 +1695,7 @@ static void reader_interactive_init()
static void reader_interactive_destroy()
{
kill_destroy();
al_foreach( &prompt_list, (void (*)(const void *))&free );
al_foreach( &prompt_list, &free );
al_destroy( &prompt_list );
writestr( L"\n" );
@@ -1697,7 +1718,7 @@ void reader_sanity_check()
void reader_replace_current_token( wchar_t *new_token )
{
const wchar_t *begin, *end;
wchar_t *begin, *end;
string_buffer_t sb;
int new_pos;
@@ -1764,7 +1785,7 @@ static int contains( const wchar_t *needle,
*/
static void reset_token_history()
{
const wchar_t *begin, *end;
wchar_t *begin, *end;
parse_util_token_extent( data->buff, data->buff_pos, &begin, &end, 0, 0 );
if( begin )
@@ -1776,7 +1797,7 @@ static void reset_token_history()
data->token_history_pos = -1;
data->search_pos=0;
al_foreach( &data->search_prev, (void (*)(const void *))&free );
al_foreach( &data->search_prev, &free );
al_truncate( &data->search_prev, 0 );
al_push( &data->search_prev, wcsdup( data->search_buff ) );
}
@@ -2062,7 +2083,7 @@ int reader_get_cursor_pos()
}
void reader_run_command( wchar_t *cmd )
void reader_run_command( const wchar_t *cmd )
{
wchar_t *ft;
@@ -2099,10 +2120,15 @@ void reader_run_command( wchar_t *cmd )
static int shell_test( wchar_t *b )
{
if( parser_test( b, 0 ) )
if( parser_test( b, 0, 0 ) )
{
string_buffer_t sb;
sb_init( &sb );
writech( L'\n' );
parser_test( b, 1 );
parser_test( b, &sb, L"fish" );
fwprintf( stderr, L"%ls", sb.buff );
sb_destroy( &sb );
return 1;
}
return 0;
@@ -2167,7 +2193,7 @@ void reader_pop()
/*
Clean up after history search
*/
al_foreach( &n->search_prev, (void (*)(const void *))&free );
al_foreach( &n->search_prev, &free );
al_destroy( &n->search_prev );
free( (void *)n->token_history_buff);
@@ -2233,7 +2259,7 @@ static void reader_super_highlight_me_plenty( wchar_t * buff, int *color, int po
*/
if( color[start+i]>>8 == 0 )
{
color[start+i] |= HIGHLIGHT_SEARCH_MATCH<<8;
color[start+i] |= HIGHLIGHT_SEARCH_MATCH<<16;
}
}
}
@@ -2433,7 +2459,7 @@ wchar_t *reader_readline()
if( (last_char == R_COMPLETE) && (c != R_COMPLETE) && (!comp_empty) )
{
al_foreach( &comp, (void (*)(const void *))&free );
al_foreach( &comp, &free );
al_truncate( &comp, 0 );
comp_empty = 1;
}
@@ -2489,8 +2515,8 @@ wchar_t *reader_readline()
if( comp_empty )
{
const wchar_t *begin, *end;
const wchar_t *token_begin, *token_end;
wchar_t *begin, *end;
wchar_t *token_begin, *token_end;
wchar_t *buffcpy;
int len;
int cursor_steps;
@@ -2498,11 +2524,12 @@ wchar_t *reader_readline()
parse_util_cmdsubst_extent( data->buff, data->buff_pos, &begin, &end );
parse_util_token_extent( begin, data->buff_pos - (begin-data->buff), &token_begin, &token_end, 0, 0 );
cursor_steps = token_end - data->buff- data->buff_pos;
data->buff_pos += cursor_steps;
move_cursor( cursor_steps );
len = data->buff_pos - (data->buff - begin);
len = data->buff_pos - (begin-data->buff);
buffcpy = wcsndup( begin, len );
reader_save_status();
@@ -2518,7 +2545,7 @@ wchar_t *reader_readline()
if( (comp_empty =
handle_completions( &comp ) ) )
{
al_foreach( &comp, (void (*)(const void *))&free );
al_foreach( &comp, &free );
al_truncate( &comp, 0 );
}
@@ -2541,7 +2568,7 @@ wchar_t *reader_readline()
{
wchar_t *str = wcsndup( data->buff, data->buff_pos );
if( !str )
die_mem();
DIE_MEM();
kill_add( str );
free( str );
@@ -2837,13 +2864,11 @@ wchar_t *reader_readline()
else
{
/*
Carriage returns happen - they are usually a
sign of an incorrectly set terminal, but there
really isn't very much we can do at this point,
so we ignore them.
Low priority debug message. These can happen if
the user presses an unefined control
sequnece. No reason to report.
*/
if( c != 13 )
debug( 0, _( L"Unknown keybinding %d" ), c );
debug( 2, _( L"Unknown keybinding %d" ), c );
}
break;
}
@@ -2944,18 +2969,21 @@ static int read_ni( int fd )
if( str )
{
if( !parser_test( str, 1 ) )
{
eval( str, 0, TOP );
}
else
{
/*
No error reporting - parser_test did that for us
*/
res = 1;
}
free( str );
string_buffer_t sb;
sb_init( &sb );
if( !parser_test( str, &sb, L"fish" ) )
{
eval( str, 0, TOP );
}
else
{
fwprintf( stderr, L"%ls", sb.buff );
res = 1;
}
sb_destroy( &sb );
free( str );
}
else
{

View File

@@ -72,7 +72,7 @@ void repaint();
Run the specified command with the correct terminal modes, and
while taking care to perform job notification, set the title, etc.
*/
void reader_run_command( wchar_t *buff );
void reader_run_command( const wchar_t *buff );
/**
Get the string of character currently entered into the command

View File

@@ -25,7 +25,7 @@
#include "reader.h"
#include "kill.h"
#include "wutil.h"
#include "translate.h"
/**
Status from earlier sanity checks
@@ -60,7 +60,7 @@ void validate_pointer( const void *ptr, const wchar_t *err, int null_ok )
Test if the pointer data crosses a segment boundary.
*/
if( (0x00000003 & (int)ptr) != 0 )
if( (0x00000003l & (long)ptr) != 0 )
{
debug( 0, _(L"The pointer '%ls' is invalid"), err );
sanity_lose();

View File

@@ -36,6 +36,8 @@
#include <libintl.h>
#endif
#include "fallback.h"
/*
Small utility for setting the color.
Usage: set_color COLOR
@@ -52,7 +54,7 @@
/**
Getopt short switches for set_color
*/
#define GETOPT_STRING "b:hvoc"
#define GETOPT_STRING "b:hvocu"
#if HAVE_GETTEXT
#define _(string) gettext(string)
@@ -152,9 +154,9 @@ int main( int argc, char **argv )
char *fgcolor=0;
int fg, bg;
int bold=0;
int underline=0;
char *bg_seq, *fg_seq;
while( 1 )
{
#ifdef HAVE_GETOPT_LONG
@@ -173,6 +175,10 @@ int main( int argc, char **argv )
"bold", no_argument, 0, 'o'
}
,
{
"underline", no_argument, 0, 'u'
}
,
{
"version", no_argument, 0, 'v'
}
@@ -218,6 +224,10 @@ int main( int argc, char **argv )
bold=1;
break;
case 'u':
underline=1;
break;
case 'v':
check_locale_init();
fprintf( stderr, _("%s, version %s\n"), SET_COLOR, PACKAGE_VERSION );
@@ -251,7 +261,7 @@ int main( int argc, char **argv )
return 1;
}
if( !fgcolor && !bgcolor && !bold )
if( !fgcolor && !bgcolor && !bold && !underline )
{
check_locale_init();
fprintf( stderr, _("%s: Expected an argument\n"), SET_COLOR );
@@ -277,16 +287,28 @@ int main( int argc, char **argv )
setupterm( 0, STDOUT_FILENO, 0);
fg_seq = set_a_foreground?set_a_foreground:set_foreground;
bg_seq = set_a_background?set_a_background:set_background;
if( bold )
{
putp( enter_bold_mode );
if( enter_bold_mode )
putp( enter_bold_mode );
}
if( underline )
{
if( enter_underline_mode )
putp( enter_underline_mode );
}
if( bgcolor )
{
if( bg == 8 )
{
putp( tparm( set_a_background, 0) );
if( bg_seq )
putp( tparm( bg_seq, 0) );
putp( tparm(exit_attribute_mode) );
}
}
@@ -295,12 +317,14 @@ int main( int argc, char **argv )
{
if( fg == 8 )
{
putp( tparm( set_a_foreground, 0) );
if( fg_seq )
putp( tparm( fg_seq, 0) );
putp( tparm(exit_attribute_mode) );
}
else
{
putp( tparm( set_a_foreground, fg) );
if( fg_seq )
putp( tparm( fg_seq, fg) );
}
}
@@ -308,8 +332,11 @@ int main( int argc, char **argv )
{
if( bg != 8 )
{
putp( tparm( set_a_background, bg) );
if( bg_seq )
putp( tparm( bg_seq, bg) );
}
}
del_curterm( cur_term );
}

View File

@@ -1,39 +1,2 @@
function __fish_complete_cd -d "Completions for the cd command"
#
# We can't simply use __fish_complete_directory because of the CDPATH
#
set -- wd $PWD
set -- owd $OLDPWD
# Check if CDPATH is set
set -l mycdpath
if test -z $CDPATH[1]
set mycdpath .
else
set mycdpath $CDPATH
end
if echo (commandline -ct)|grep '^/\|./' >/dev/null
# This is an absolute search path
eval printf '\%s\\tDirectory\\n' (commandline -ct)\*/
else
# This is a relative search path
# Iterate over every directory in CDPATH and check for possible completions
for i in $mycdpath
# Move to the initial directory first, in case the CDPATH directory is relative
builtin cd $wd
builtin cd $i
eval printf '"%s\tDirectory in "'$i'"\n"' (commandline -ct)\*/
end
end
builtin cd $wd
set -- OLDPWD $owd
end
complete -x -c cd -a "(__fish_complete_cd)"

28
share/completions/cp.fish Normal file
View File

@@ -0,0 +1,28 @@
complete -c cp -s a -l archive -d (N_ "Same as -dpR")
complete -c cp -s b -l backup -d (N_ "Make backup of each existing destination file") -a "none off numbered t existing nil simple never"
complete -c cp -l copy-contents -d (N_ "Copy contents of special files when recursive")
complete -c cp -s d -d (N_ "Same as --no-dereference --preserve=link")
complete -c cp -s f -l force -d (N_ "Do not prompt before overwriting")
complete -c cp -s i -l interactive -d (N_ "Prompt before overwrite")
complete -c cp -s H -d (N_ "Follow command-line symbolic links")
complete -c cp -s l -l link -d (N_ "Link files instead of copying")
complete -c cp -l strip-trailing-slashes -d (N_ "Remove trailing slashes from source")
complete -c cp -s S -l suffix -r -d (N_ "Backup suffix")
complete -c cp -s t -l target-directory -d (N_ "Target directory") -x -a "(__fish_complete_directory (commandline -ct) 'Target directory')"
complete -c cp -s u -l update -d (N_ "Do not overwrite newer files")
complete -c cp -s v -l verbose -d (N_ "Verbose mode")
complete -c cp -l help -d (N_ "Display help and exit")
complete -c cp -l version -d (N_ "Display version and exit")
complete -c cp -s L -l dereference -d (N_ "Always follow symbolic links")
complete -c cp -s P -l no-dereference -d (N_ "Never follow symbolic links")
complete -c cp -s p -d (N_ "Same as --preserve=mode,ownership,timestamps")
complete -c cp -l preserve -d (N_ "Preserve the specified attributes and security contexts, if possible") -a "mode ownership timestamps links all"
complete -c cp -l no-preserve -r -d (N_ "Don't preserve the specified attributes") -a "mode ownership timestamps links all"
complete -c cp -l parents -d (N_ "Use full source file name under DIRECTORY")
complete -c cp -s r -s R -l recursive -d (N_ "Copy directories recursively")
complete -c cp -l remove-destination -d (N_ "Remove each existing destination file before attempting to open it (contrast with --force)")
complete -c cp -l sparse -r -d (N_ "Control creation of sparse files") -a "always auto never"
complete -c cp -s s -l symbolic-link -d (N_ "Make symbolic links instead of copying")
complete -c cp -s T -l no-target-directory -d (N_ "Treat DEST as a normal file")
complete -c cp -s x -l one-file-system -d (N_ "Stay on this file system")
complete -c cp -s X -l context -r -d (N_ "Set security context of copy to CONTEXT")

View File

@@ -3,4 +3,4 @@ complete -c functions -xa "(functions -na)" -d (N_ "Function")
complete -c functions -s a -l all -d (N_ "Show hidden functions")
complete -c functions -s h -l help -d (N_ "Display help and exit")
complete -c functions -s d -l description -d (N_ "Set function description") -x
complete -c functions -s q -l query -d (N_ "Test if function is defined")

View File

@@ -6,7 +6,7 @@ for i in (builtin -n)
complete -c help -x -a $i -d (N_ "Help for the specified builtin")
end
for i in case (sed -n < /usr/share/doc/fish-1.21.7/commands.html -e "s/.*<h2><a class=\"anchor\" name=\"\([^\"]*\)\">.*/\1/p")
for i in case (sed -n < $__fish_help_dir/commands.html -e "s/.*<h2><a class=\"anchor\" name=\"\([^\"]*\)\">.*/\1/p")
complete -c help -x -a $i -d (N_ "Help for the specified command")
end

View File

@@ -6,7 +6,7 @@ complete -c mv -l strip-trailing-slashes -d (N_ "Remove trailing slashes from so
complete -c mv -s S -l suffix -r -d (N_ "Backup suffix")
complete -c mv -l target-directory -d (N_ "Target directory") -x -a "(__fish_complete_directory (commandline -ct) 'Target directory')"
complete -c mv -s u -l update -d (N_ "Do not overwrite newer files")
complete -c mv -s v -l vervose -d (N_ "Verbose mode")
complete -c mv -s v -l verbose -d (N_ "Verbose mode")
complete -c mv -l help -d (N_ "Display help and exit")
complete -c mv -l version -d (N_ "Display version and exit")

View File

@@ -1,5 +1,5 @@
#
#Completions for patch
# Completions for patch
#
complete -c patch -s b -l backup -d (N_ "Make backup files, when patching a file, rename or copy the original instead of removing it")
@@ -24,7 +24,7 @@ complete -c patch -s N -l forward -d (N_ "Ignore patches that seem to be reverse
complete -c patch -s o -l output -r -f -d (N_ "Send output to outfile instead of patching files in place")
complete -c patch -s p -l strip -r -f -d (N_ "Strip the smallest prefix containing num leading slashes from each file name found in the patch file")
complete -c patch -l posix -d (N_ "Conform more strictly to the POSIX standard")
complete -c patch -l quoting-style -r -f -d (N_ "Use style word to quote output names")
complete -c patch -l quoting-style -r -f -d (N_ "Use style word to quote output names") -a "literal shell shell-always c escape"
complete -c patch -s r -l reject-file -r -f -d (N_ "Put rejects into rejectfile instead of the default .rej file")
complete -c patch -s R -l reverse -d (N_ "Assume that this patch was created with the old and new files swapped")
complete -c patch -s s -l silent -l quiet -d (N_ "Work silently, unless an error occurs")

View File

@@ -1,3 +1,8 @@
complete -c set_color -x -d (N_ "Color") -a '(set_color --print-colors)'
complete -c set_color -s b -l background -x -a '(set_color --print-colors)' -d (N_ "Change background color")
complete -c set_color -s o -l bold -d (N_ 'Make font bold')
complete -c set_color -s u -l underline -d (N_ 'Underline text')
complete -c set_color -s v -l version -d (N_ 'Display version and exit')
complete -c set_color -s h -l help -d (N_ 'Display help and exit')
complete -c set_color -s c -l print-colors -d (N_ 'Print a list of all accepted color names')

View File

@@ -6,20 +6,20 @@
complete -x -c telnet -d Hostname -a "(__fish_print_hostnames)"
complete -c telnet -s 8 -d (_ "Specifies an 8-bit data path.")
complete -c telnet -s 7 -d (_ "Do not try to negotiate TELNET BINARY option.")
complete -c telnet -s E -d (_ "Stops any character from being recognized as an escape character.")
complete -c telnet -s F -d (_ "Use local Kerberos authentication, if possible.")
complete -c telnet -s K -d (_ "Specifies no automatic login to remote system.")
complete -c telnet -s L -d (_ "Specifies an 8-bit data path.")
complete -c telnet -s a -d (_ "Attempt automatic login.")
complete -c telnet -s 8 -d (_ "Specifies an 8-bit data path")
complete -c telnet -s 7 -d (_ "Do not try to negotiate TELNET BINARY option")
complete -c telnet -s E -d (_ "Stops any character from being recognized as an escape character")
complete -c telnet -s F -d (_ "Use local Kerberos authentication, if possible")
complete -c telnet -s K -d (_ "Specifies no automatic login to remote system")
complete -c telnet -s L -d (_ "Specifies an 8-bit data path")
complete -c telnet -s a -d (_ "Attempt automatic login")
complete -c telnet -s c -d (_ "Disables reading user's .telnetrc")
complete -c telnet -s d -d (_ "Sets debug mode.")
complete -c telnet -s S -x -d (_ "Sets IP TOS.")
complete -c telnet -s X -x -d (_ "Disables atype type of authentication.")
complete -c telnet -s l -x -a "(__fish_complete_users)" -d (_ "User login.")
complete -c telnet -s n -x -d (_ "Log to tracefile.")
complete -c telnet -s x -d (_ "Turn on encryption.")
complete -c telnet -s r -d (_ "User interface similar to rlogin.")
complete -c telnet -s k -x -d (_ "Use Kerberos realm for authentication.")
complete -c telnet -s d -d (_ "Sets debug mode")
complete -c telnet -s S -x -d (_ "Sets IP TOS")
complete -c telnet -s X -x -d (_ "Disables specified type of authentication")
complete -c telnet -s l -x -a "(__fish_complete_users)" -d (_ "User login")
complete -c telnet -s n -x -d (_ "Log to tracefile")
complete -c telnet -s x -d (_ "Turn on encryption")
complete -c telnet -s r -d (_ "User interface similar to rlogin")
complete -c telnet -s k -x -d (_ "Use Kerberos realm for authentication")

View File

@@ -0,0 +1,15 @@
complete -c which -s a -l all -d (N_ "Print all matching executables in PATH, not just the first")
complete -c which -s i -l read-alias -d (N_ "Read aliases from stdin, reporting matching ones on stdout")
complete -c which -l skip-alias -d (N_ "Ignore option '--read-alias'")
complete -c which -l read-functions -d (N_ "Read shell function definitions from stdin, reporting matching ones on stdout")
complete -c which -l skip-functions -d (N_ "Ignore option '--read-functions'")
complete -c which -l skip-dot -d (N_ "Skip directories in PATH that start with a dot")
complete -c which -l skip-tilde -d (N_ "Skip directories in PATH that start with a tilde and executables which reside in the HOME directory")
complete -c which -l show-dot -d (N_ "If a directory in PATH starts with a dot and a matching executable was found for that path, then print './programname'")
complete -c which -l show-tilde -d (N_ "Output a tilde when a directory matches the HOME directory")
complete -c which -l tty-only -d (N_ "Stop processing options on the right if not on tty")
complete -c which -s v -s V -l version -d (N_ "Display version and exit")
complete -c which -l help -d (N_ "Display help and exit")
complete -c which -a "(__fish_complete_command)" -d "Command" -x

View File

@@ -3,12 +3,14 @@
# common helper functions for the command completions. All actual
# completions are located in the completions subdirectory.
#
# @configure_input@
#
# Assign a temporary value here for performance reasons. The real value should be set in /etc/fish.
#
# Assign a temporary value here for performance reasons. The real
# value should be set in /etc/fish.
set -g fish_function_path @datadir@/fish/functions/
set __fish_help_dir @docdir@
set -g fish_function_path $PWD/functions/
#
# Make sure there are no invalid entries in the PATH
@@ -19,12 +21,12 @@ for idx in (seq (count $PATH))
set i $PATH[$idx]
if not test -d $i
set erase_idx $erase_idx $idx
printf (_ '%s: Warning: The directory %s has been removed from your PATH, because it does not exist\n') fish $i
printf (_ '%s: Warning: The directory %s has been removed from your PATH because it does not exist\n') fish $i
end
end
if count $erase_idx >/dev/null
set -e PATH[(echo $erase_idx)]
set -e PATH[(echo $erase_idx)]
end
#
@@ -33,7 +35,7 @@ end
# want this even for text-only terminals.
#
set -l path_list /bin /usr/bin /usr/X11R6/bin @PREFIX@/bin @optbindirs@
set -l path_list /bin /usr/bin /usr/X11R6/bin @prefix@/bin @optbindirs@
# Root should also have the sbin directories in the path
if test "$USER" = root

View File

@@ -0,0 +1,43 @@
function __fish_complete_cd -d "Completions for the cd command"
#
# We can't simply use __fish_complete_directory because of the CDPATH
#
set -l wd $PWD
set -l owd $OLDPWD
# Check if CDPATH is set
set -l mycdpath
if test -z $CDPATH[1]
set mycdpath .
else
set mycdpath $CDPATH
end
if echo (commandline -ct)|grep '^/\|^\./\|^\.\./' >/dev/null
# This is an absolute search path
eval printf '\%s\\tDirectory\\n' (commandline -ct)\*/
else
# This is a relative search path
# Iterate over every directory in CDPATH
# and check for possible completions
for i in $mycdpath
# Move to the initial directory first,
# in case the CDPATH directory is relative
builtin cd $wd
builtin cd $i
eval printf '"%s\tDirectory in "'$i'"\n"' (commandline -ct)\*/
end
end
builtin cd $wd
set OLDPWD $owd
end

View File

@@ -7,7 +7,7 @@
function __fish_complete_ls -d "Compleletions for ls and it's aliases"
set -l is_gnu
ls --version >/dev/null ^/dev/null; and set is_gnu --is-gnu
command ls --version >/dev/null ^/dev/null; and set is_gnu --is-gnu
set -l cmds -c $argv

View File

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

View File

@@ -2,7 +2,7 @@
# Match colors for grep, if supported
#
if grep --color=auto --help 1>/dev/null 2>/dev/null
if command grep --color=auto --help 1>/dev/null 2>/dev/null
if not set -q GREP_COLOR
set -gx GREP_COLOR '97;45'
end

View File

@@ -79,7 +79,7 @@ function help -d (N_ "Show help for the fish shell")
# documentation. It's a bit of a hack, since it relies on the
# Doxygen markup format to never change...
case (sed -n < /usr/share/doc/fish-1.21.7/commands.html -e "s/.*<h2><a class=\"anchor\" name=\"\([^\"]*\)\">.*/\1/p")
case (sed -n < $__fish_help_dir/commands.html -e "s/.*<h2><a class=\"anchor\" name=\"\([^\"]*\)\">.*/\1/p")
set fish_help_page "commands.html\#$fish_help_item"
case $help_topics
set fish_help_page "index.html\#$fish_help_item"

View File

@@ -12,7 +12,7 @@ else
function prompt_pwd -d (N_ "Print the current working directory, shortend to fit the prompt")
if test "$PWD" != "$HOME"
printf "%s" (echo $PWD|sed -e "s|^$HOME|~|" -e 's-/\([^/]\)\([^/]*\)-/\1-g')
echo $PWD|sed -e 's-.*/[^/]\([^/]*$\)-\1-'
echo $PWD|sed -n -e 's-.*/[^/]\([^/]*$\)-\1-p'
else
echo '~'
end

View File

@@ -1,7 +1,14 @@
#
# Make pwd print out the home directory as a tilde.
# Also drop '/private' directories on OS X.
#
function pwd -d (N_ "Print working directory")
echo $PWD | sed -e 's|/private||' -e "s|^$HOME|~|"
end
if test (uname) = Darwin
function pwd -d (N_ "Print working directory")
echo $PWD | sed -e 's|/private||' -e "s|^$HOME|~|"
end
else
function pwd -d (N_ "Print working directory")
echo $PWD | sed -e "s|^$HOME|~|"
end
end

View File

@@ -0,0 +1,4 @@
function setenv -d (N_ 'Set global variable. Alias for set -g, made for csh compatibility')
set -g $argv
end

View File

@@ -24,7 +24,7 @@ The library for various signal related issues
#include "event.h"
#include "reader.h"
#include "proc.h"
#include "translate.h"
/**
Struct describing an entry for the lookup table used to convert
@@ -46,6 +46,9 @@ struct lookup_entry
const wchar_t *desc;
};
/**
The number of signal blocks in place. Increased by signal_block, decreased by signal_unblock.
*/
static int block_count=0;
@@ -53,7 +56,7 @@ static int block_count=0;
Lookup table used to convert between signal names and signal ids,
etc.
*/
static struct lookup_entry lookup[] =
const static struct lookup_entry lookup[] =
{
#ifdef SIGHUP
{

View File

@@ -111,5 +111,19 @@ else
echo Test 9 pass
end
# Test erasing variables in specific scope
set -eU foo
set -g foo bar
begin
set -l foo baz
set -eg foo
end
if set -q foo
echo Test 10 fail
else
echo Test 10 pass
end

View File

@@ -7,3 +7,4 @@ Test 6 pass
Test 7 pass
Test 8 pass
Test 9 pass
Test 10 pass

Some files were not shown because too many files have changed in this diff Show More