Compare commits

..

489 Commits

Author SHA1 Message Date
axel
ab162c6c25 Bump version number
darcs-hash:20061112210938-ac50b-af5fc653b1ec0da6832338aec2d56c98fba69897.gz
2006-11-13 07:09:38 +10:00
axel
5ed912bebc The incorrect pointer is used for the autounload callback, causing possible crashes
darcs-hash:20061112121725-ac50b-1f49f3f37c20d3fe2d4a12617e9dda139d2ad5ec.gz
2006-11-12 22:17:25 +10:00
axel
ec43090c16 Fix file descriptor leakage from completion pager
darcs-hash:20061112121613-ac50b-209d42c06401faf675ff123236823dcaa651d6f7.gz
2006-11-12 22:16:13 +10:00
axel
80759ee03f Fix exit status of delete-or-exit function
darcs-hash:20061112114544-ac50b-d5fd61b3819715057caba2dd8b48119df080edd1.gz
2006-11-12 21:45:44 +10:00
axel
816f473ac9 Add a few missing completions for the ls command
darcs-hash:20061111113315-ac50b-2a77e93a78571e1e83801128c1793c52bb03e13f.gz
2006-11-11 21:33:15 +10:00
axel
d59d3b4463 Minor code simplification in main.c
darcs-hash:20061111110650-ac50b-0d50d10087ea863ff0c79d05c614fdb06fa3b9bd.gz
2006-11-11 21:06:50 +10:00
axel
8784b78d84 Add a few more darcs completions. These are still unfinished, though.
darcs-hash:20061111105547-ac50b-0791e833664ff67d8ced1176577d8266fe4a3782.gz
2006-11-11 20:55:47 +10:00
axel
5005c67d76 Minor cleanups, mostly of code comments
darcs-hash:20061111105452-ac50b-24ab7965f6208ecdfced738e08cdb4cb4a565458.gz
2006-11-11 20:54:52 +10:00
axel
63732a99e9 Tweak Makefile, including fixing slight dependency problem
darcs-hash:20061111105314-ac50b-69703cc2575856a321515aa0554e97d1895a4606.gz
2006-11-11 20:53:14 +10:00
axel
04b7da336d Documentation updates
darcs-hash:20061111105208-ac50b-27e335ba701b021d3119206e91d68c8504d45c2b.gz
2006-11-11 20:52:08 +10:00
axel
5f69f2bb0c Make fish send a HUP signal to jobs when the terminal tells it to exit.
darcs-hash:20061111104840-ac50b-ae989e26bdb6c769ed93dcf11b742887c97858aa.gz
2006-11-11 20:48:40 +10:00
tassilo
fb62a35921 complete-eik-and-friends.dpatch
Completions for all tools which come with eix.
(http://dev.croup.de/proj/eix)

darcs-hash:20061110155925-a923b-fd06120f7ea5f65cb752fe437bfccb6f16c87b45.gz
2006-11-11 01:59:25 +10:00
axel
08787c7674 fix bug where off_t was assumed to be long long, causing display errors on systems with no large file support
darcs-hash:20061109175804-ac50b-b05ec0aa9ae6f7dd23b7432c321eff44b446397d.gz
2006-11-10 03:58:04 +10:00
tassilo
79de45eed5 better-emerge-completion.dpatch
- You don't need to supply the package right after -C or -u etc.
- Better descriptions

darcs-hash:20061109145341-a923b-a1a54d3a5a040396ccba350c125f3b1ba645c601.gz
2006-11-10 00:53:41 +10:00
axel
9bc9e1c08d Add completions for equery, written by Tassilo Horn.
darcs-hash:20061107211708-ac50b-6199e58e84bc8ee8729be5f2a5ff2f3518888bfc.gz
2006-11-08 07:17:08 +10:00
axel
3acdeb87a4 Update the emerge completions. They are now complete, ignore switch ordering, handle packages in different catagories with the same name. This update was made by Tassilo Horn.
darcs-hash:20061107211617-ac50b-fcd3108209671283b2d5553d3adf5a81a46869f9.gz
2006-11-08 07:16:17 +10:00
axel
9959e53985 Add alias function. Thanks to Tassilo Horn for pointing out that it was missing.
darcs-hash:20061107205539-ac50b-0053f828d40be5bcb088cdb8d669c239c201b433.gz
2006-11-08 06:55:39 +10:00
axel
4edb71325f Do not escape the ':' character. Thanks to Tassilo Horn for pointing this out.
darcs-hash:20061107205437-ac50b-51632ce51915d4ca8680ab4c4522bcd002a794b6.gz
2006-11-08 06:54:37 +10:00
axel
310768e8d2 Try to avoid the '
darcs-hash:20061107181911-ac50b-fda6044a81b3a09707f17d4017c2c3dacf4e1801.gz
2006-11-08 04:19:11 +10:00
axel
dc90e460fe Fix a bug in the help function causing help to fail when trying to open help for a builtin command. Thanks to Reuben Thomas for the report.
darcs-hash:20061107131211-ac50b-9727a813d940b34923b23b073c80a7b42c023486.gz
2006-11-07 23:12:11 +10:00
axel
d20c14b4bb Do not print a newline on empty greeting message. Thanks to Reuben Thomas for pointing this out.
darcs-hash:20061107130629-ac50b-553bc13390c0f040f4cecf2780e34da674e065fa.gz
2006-11-07 23:06:29 +10:00
axel
981f5782d8 Fix code for locating inputrc-file in users fish configuration directory. Thanks to Reuben Thomas for reporting this.
darcs-hash:20061103155335-ac50b-23ddaec5d0ca591b00e8a59ccc39e63ed8b9ff25.gz
2006-11-04 01:53:35 +10:00
axel
c2021b6225 Fix typo in documentation for the commandline builtin. Thanks to Reuben Thomas for reporting this.
darcs-hash:20061103143140-ac50b-b37fbfe68321f904936c002010045e467bc3a778.gz
2006-11-04 00:31:40 +10:00
axel
9de4dbdd03 Add the file that generated the wajig completions to the tree. This should not be installed but it should be included with the tarball. The file was written by Reuben Thomas.
darcs-hash:20061103142645-ac50b-0e13e41941b5dc990c60d775cdd8503ed8e54529.gz
2006-11-04 00:26:45 +10:00
axel
1a84a44cc2 Add completions for ps2pdf, dvipdf and dvipdfm commands, written by Reuben Thomas.
darcs-hash:20061103141945-ac50b-7592bb5784a55272747bbb0322281b9090e5fd65.gz
2006-11-04 00:19:45 +10:00
axel
80a9fc2fce Add mention of uninstalling old fish versions to the INSTALL file. Thanks to Jason Grossman for the suggestion
darcs-hash:20061103141254-ac50b-27f1f4741379bff54298b6c18d289947f66f91cf.gz
2006-11-04 00:12:54 +10:00
axel
8aac7e82c0 Try to detect seq versions installed by earlier fish versions and replace them
darcs-hash:20061103131621-ac50b-2748c958f8614f39fbaa7a45261877a912de539e.gz
2006-11-03 23:16:21 +10:00
axel
49e300d0ca Check if any libraries need to be linked in order to use iconv. This is needed on OS X. Thanks to Jason Grossman for the report
darcs-hash:20061103100004-ac50b-861ca2bc42414c475b1ab24399c8d240cf1e4651.gz
2006-11-03 20:00:04 +10:00
axel
136e99de62 Fix bugs causing all unmapped inputs below 31 to be interpreted as newlines. Thanks to Reuben Thomas for the report.
darcs-hash:20061103003457-ac50b-5f3fee63e211b12014e40dc3d8d8c94eaa22f24d.gz
2006-11-03 10:34:57 +10:00
axel
c41986a63f Add command specific completions for unrar command (No switches yet, only commands and files in archive)
darcs-hash:20061102235727-ac50b-7b7638289be4de52b4e3e3d109ad3167b7285023.gz
2006-11-03 09:57:27 +10:00
axel
bedf8ea55e Add support for completing using contents of tar archives
darcs-hash:20061102235548-ac50b-ec4a3b206c73f8fc44cc715b2a95fe6fef2d53c0.gz
2006-11-03 09:55:48 +10:00
axel
d8f1c0abcd Minor tweaks in the reader. Vastly simplyfu the insert_char function, and add a few code commants.
darcs-hash:20061102135019-ac50b-c5d4f7f307deb93b71e797bbb8a1d420a5790dc3.gz
2006-11-02 23:50:19 +10:00
axel
13a85ee3f1 Make sure fish has the currect exit status
darcs-hash:20061102134859-ac50b-692f9e9aff838ea375e5cf29eeae1e29b1b75338.gz
2006-11-02 23:48:59 +10:00
axel
fab18bae80 Updates to the documentation - add a few crossreferences, remove redundant listing of builtins and update the todo list
darcs-hash:20061102134725-ac50b-802d5cf8754ff94c4cc9533b2ff16a759e9aa2c9.gz
2006-11-02 23:47:25 +10:00
axel
6e24b26e2c Fix the code for ignoring infinite recursion
darcs-hash:20061102134537-ac50b-2dddd06dd77c362caf44c9160acc29b76278b230.gz
2006-11-02 23:45:37 +10:00
axel
7fb44d4d5f Spelling fix. Thanks to Reuben Thomas
darcs-hash:20061101231404-ac50b-8f5b08242aed565baf37035805d7b3614fe8022b.gz
2006-11-02 09:14:04 +10:00
axel
44f85d04f9 Fix formating issue for the documentation for the prevd function
darcs-hash:20061101221835-ac50b-03a9b5abc7e4a25cc75effecc734c20eb8fee342.gz
2006-11-02 08:18:35 +10:00
axel
bd71f0a096 Fix build error
darcs-hash:20061101181221-ac50b-227b2d2f6f5122c9f25c471872376884bdace13c.gz
2006-11-02 04:12:21 +10:00
axel
f7b656017f Use the same wording about license in Makefile and main.c.
darcs-hash:20061101144747-ac50b-fac8e3693445a8601f0c71ab191a64dac0ad7a67.gz
2006-11-02 00:47:47 +10:00
axel
7a8ca73376 Add missing include to fix a warning
darcs-hash:20061101105412-ac50b-1ee3d996330ad435954abfc8f827deb3f121adb5.gz
2006-11-01 20:54:12 +10:00
axel
9eb1826961 Update to buildscripts to fix dependency issues caused by new documentation layout
darcs-hash:20061101103112-ac50b-8ee49c3031b7802822c95ffcfee26d10e1870ed1.gz
2006-11-01 20:31:12 +10:00
axel
728a60bd67 Fix beginning/end-of-line input function, add beginning/end-of-buffer functions
darcs-hash:20061031220149-ac50b-6e6b8f523642bead730059dd96ee2d1290283b5e.gz
2006-11-01 08:01:49 +10:00
axel
0099c3c420 Add table of contents to begining of documentation. This involves some restructuring of the documentation files.
darcs-hash:20061031153614-ac50b-7a6e97e30ae759591028227466e76c574b931fd5.gz
2006-11-01 01:36:14 +10:00
axel
885d16fcd6 Fix casing and other minor issues in documentation
darcs-hash:20061031152316-ac50b-e68db9853d6e9461a0c054f1ea290704ccfc0a31.gz
2006-11-01 01:23:16 +10:00
axel
c4a8f4c890 Code beutification in build files
darcs-hash:20061031020656-ac50b-2385bb51d7df624e5691b7659120596600fd1d5d.gz
2006-10-31 12:06:56 +10:00
axel
c098cb5c87 Bump version number
darcs-hash:20061030160357-ac50b-29729cb4ba358e09f9c19e6d6e07e0c2489e14fd.gz
2006-10-31 02:03:57 +10:00
axel
63643ff17f Fix completions for which and type, which where broken by previous script updates
darcs-hash:20061030015221-ac50b-e4a0f2802e7a5dc4a1e594933f25cae00d9ea104.gz
2006-10-30 11:52:21 +10:00
axel
f83575f084 Make sure signals aren't blocked while autoloading, also add a few consistency checks to see that signals aren't blocked in critical places
darcs-hash:20061029210911-ac50b-50bec85c3d59d0332ba44f3ece1a012cdc3e8c4b.gz
2006-10-30 07:09:11 +10:00
axel
a6c00ca0d2 Minor edits
darcs-hash:20061028164448-ac50b-c53d5f235d01db3a11b01996b77411a213dc5303.gz
2006-10-29 02:44:48 +10:00
axel
c5eaefc8b5 Update autoloader to fix concurrency issues when changing loader path in autoloaded function
darcs-hash:20061028164122-ac50b-25f978df9afeb370a06ef7576ef03183034bc057.gz
2006-10-29 02:41:22 +10:00
axel
f16bb285be Documentation updates and clarifications
darcs-hash:20061028163229-ac50b-2b6d3712a97903788520c155326b0e7a193b5eec.gz
2006-10-29 02:32:29 +10:00
axel
09c348bef2 Add a shellscript function 'save'function' for saving the current definition of a function to file
darcs-hash:20061027225004-ac50b-2454152687ff84deec90e3d938a0288e62dc34e6.gz
2006-10-28 08:50:04 +10:00
axel
561ec7d5f5 Change the way the umask is used so that executable bits are ignored on file creation. Thanks to sqweek and Jamessan for explaining the issue.
darcs-hash:20061026151946-ac50b-3a55159343f1fe0a4edf3f077bcec8afd6f131f5.gz
2006-10-27 01:19:46 +10:00
axel
e98a604a21 Minor edits, remove unneeded code, add a few commants, correct spelling, tweak the todo list, etc.
darcs-hash:20061026102253-ac50b-eb42fdab9a9211d68386a563134856a96b870d90.gz
2006-10-26 20:22:53 +10:00
axel
3341fc888c Make the fish manpage in Doxygen and add it to the main fish documentation
darcs-hash:20061026102059-ac50b-2a7956bb4651b5ffe867e7c6eb26a29e2f15ad24.gz
2006-10-26 20:20:59 +10:00
axel
1faf7df371 Move out argument parsing into it's own function
darcs-hash:20061025205443-ac50b-2889624cadb3b92be13da523df32b178c773dbf7.gz
2006-10-26 06:54:43 +10:00
axel
3a128e1484 Use bitset to implement flags for jobs instead of wasting a whole int for every flag
darcs-hash:20061025204759-ac50b-ea07caa30782a1ea02d2cd8aa7cbc94474047a10.gz
2006-10-26 06:47:59 +10:00
axel
cdc52f7bde Add more comments to the history implementation
darcs-hash:20061025204650-ac50b-419d37d9ea68de0deee613524d06882a8e4c908e.gz
2006-10-26 06:46:50 +10:00
axel
e0899addcb Minor cleanups and improved error checking in reader code
darcs-hash:20061025203608-ac50b-213edeb462eaabce849d9cd13ffc30879e810bb8.gz
2006-10-26 06:36:08 +10:00
axel
c627509e59 Make al_pop return null on empty lists instead of crashing
darcs-hash:20061025203433-ac50b-5d3a18d788d6f36dffe1136664f029a500989db9.gz
2006-10-26 06:34:33 +10:00
axel
4502fc74c3 Fix spelling error in init file
darcs-hash:20061025203337-ac50b-576bd81401e332f94ecdff5665ca8da82c63fa8e.gz
2006-10-26 06:33:37 +10:00
axel
3b0ed061cd If the builtin help won't fit on-screen, and it can't be shortened, don't print it
darcs-hash:20061025203225-ac50b-8675f297a8aabea080edf7946d6f136296a6d7bb.gz
2006-10-26 06:32:25 +10:00
axel
dfa73c7cc1 Remove the --key-binding switch for fish
darcs-hash:20061025202836-ac50b-682015e2f5830a85ff520e89b0a951ca9d2913dc.gz
2006-10-26 06:28:36 +10:00
axel
12be24ef47 Update dependency list
darcs-hash:20061025163950-ac50b-161f81c51f5e923bfaf0aa9fda4d74f785e7aff7.gz
2006-10-26 02:39:50 +10:00
axel
c684b7c7c7 Update makefile to not try to delete old config files during install, and instead fail with a relevant error message. Thanks to Jamessan for pointing out the evilness of the old method and suggesting the new method.
darcs-hash:20061025163532-ac50b-ff394c53b8eb0d932894784bc25e086f9c9b65ec.gz
2006-10-26 02:35:32 +10:00
axel
4f22082a5c Do not remove trailing whitespace from function definitions, the may be a part of a function
darcs-hash:20061025122712-ac50b-6d7ab43572f71cafa5fddd65b8350498e2651b41.gz
2006-10-25 22:27:12 +10:00
axel
e3c1363831 Drop switch for saving of functions to file from the function builtin
darcs-hash:20061025105746-ac50b-942e878b01f5e080d7cf1e6414246b68b608b08f.gz
2006-10-25 20:57:46 +10:00
axel
6d413c8dc3 Fix bug where in rare cases calling the exit builtin would cause jobs to not execute even though the call to exit was blocked by running jobs
darcs-hash:20061025101402-ac50b-36456915671513f376a90c4455d1c9256f4a9030.gz
2006-10-25 20:14:02 +10:00
axel
32a49e45c8 Use the _t suffix for typedef:ed structs in complete.c
darcs-hash:20061024110352-ac50b-30768be6a11d9a5935be479fbdb430a42b0a95b9.gz
2006-10-24 21:03:52 +10:00
axel
b37d49a708 Fix bug in sed scripts for generating configuration files from templates. Multiple substitutions on the same line where ignored.
darcs-hash:20061023104315-ac50b-e5e84fb1e33fad98d81efccca0ae5dd57b479c7e.gz
2006-10-23 20:43:15 +10:00
axel
86b7023536 Decrease priority of fishd debug message
darcs-hash:20061022160329-ac50b-5f35fe90f6be184f02fc6514fc6047b25e4f93c3.gz
2006-10-23 02:03:29 +10:00
axel
287ab597ca Remove extra whitespace from warning message on directory transition
darcs-hash:20061022155759-ac50b-e1cd50b1b0d05413ad6e4d6c06a0f005e17d6976.gz
2006-10-23 01:57:59 +10:00
axel
c313f21066 A few more minor code tweaks to fish_pager, including added documentation and removing a few hardcoded constants.
darcs-hash:20061022115026-ac50b-590de2ef2f0cbe474ca4e41fd134e0c46d6877b3.gz
2006-10-22 21:50:26 +10:00
axel
e2dca4273a Add documentation, fix memory leaks and do minor code tweaks in fish_pager
darcs-hash:20061022110414-ac50b-e5ba776e795e0273d819d4eb51d5f60fba967db2.gz
2006-10-22 21:04:14 +10:00
axel
5a7a8003a0 Give search highligting precedence over other highligting types
darcs-hash:20061022094018-ac50b-0f688dc7e756f428c05e6977db6dc9cf9f642475.gz
2006-10-22 19:40:18 +10:00
axel
b83a7cb659 Make automatic history reloading actually work the way it should
darcs-hash:20061022012102-ac50b-e57a0dd2c918a2a8abd0210b9f8a2163ce664b74.gz
2006-10-22 11:21:02 +10:00
axel
da81328d75 Fix warning messages in fish_tests
darcs-hash:20061021225900-ac50b-992edf0914250ae090ef952717ef3a05cb9cfa6e.gz
2006-10-22 08:59:00 +10:00
axel
5ae4306418 Change meaning of ** to match both files and directories
darcs-hash:20061021224429-ac50b-38e46fa533baf9a46d207ab95bfa7af55abbe54a.gz
2006-10-22 08:44:29 +10:00
axel
ed36f30eae Fix crash bug in new history code - fish would segfauls in non-interactive mode on exit
darcs-hash:20061021103035-ac50b-a2a8d96416ff217cc5640f8f27db8dbac2c39b82.gz
2006-10-21 20:30:35 +10:00
axel
7b8ebdadd6 Fix flags for mmap in history, don't unload history items written to disk in order to keep proper ordering
darcs-hash:20061021101609-ac50b-563c0b14b620a6ef4bffe69202e97103b1d75ea5.gz
2006-10-21 20:16:09 +10:00
axel
bb4e166b37 Add some documentation to the new history code, and fix some minor code issues
darcs-hash:20061020230420-ac50b-39a08d68b82481514b0d6c1024a12618bf329d57.gz
2006-10-21 09:04:20 +10:00
axel
9dc1a7d5e9 Rewritten history implementation - uses mmap to save lots of memory and also allows incremental saving. The history is autosaved every five minutes and every five added entries
darcs-hash:20061020223649-ac50b-5e3e2c1e395feec0f5ac457149639f68d52d40f0.gz
2006-10-21 08:36:49 +10:00
axel
79f59e2a2d Decrease number of gettext messages that are buffered to save memory
darcs-hash:20061020223440-ac50b-ad0c0f685bfc851c62c340ee7d97fa1413bc9fca.gz
2006-10-21 08:34:40 +10:00
axel
8285242ff6 Add wrename wrapper around rename function
darcs-hash:20061020223347-ac50b-1735f7e63b87f021ca71c44e5278726d3e8debc3.gz
2006-10-21 08:33:47 +10:00
axel
c0a54955e7 Remove /etc/fish file before creating directory with the same name to avoid clash
darcs-hash:20061019234336-ac50b-569c1b492ab4d1f5f84dc8a4730700264c4e3e10.gz
2006-10-20 09:43:36 +10:00
axel
b2d4e85f17 Make any character except '/' legal in function names
darcs-hash:20061019154747-ac50b-f3ab0df1085b91ec0eadcceddb23f03d5b0247aa.gz
2006-10-20 01:47:47 +10:00
axel
a5868d67f5 Make failed process expansions expand to zero arguments, not to the original string
darcs-hash:20061019154127-ac50b-86975e62d9947819862a98e7b6fff3ff630f26b7.gz
2006-10-20 01:41:27 +10:00
axel
45f1263112 Minor code fixes
darcs-hash:20061019153950-ac50b-9a7d5939ce47cd5f8b7167a97b0e9c62315b7b6e.gz
2006-10-20 01:39:50 +10:00
axel
4683f4c989 Fix a number of bugs found using the warnings generated by earlier patch
darcs-hash:20061019153603-ac50b-4efb1ad1fe2cbe693a921648a0616a3d258d7933.gz
2006-10-20 01:36:03 +10:00
axel
ae16397e1c Fix occasional garbled characters in output of the set builtin
darcs-hash:20061019152418-ac50b-2ef6e93820deb5e272f28f893c51dca642a6b080.gz
2006-10-20 01:24:18 +10:00
axel
2d05b1c1b4 Add compiler warnings for some common incorrect usage of functions, such as forgetting to cast null pointers to variadic functions
darcs-hash:20061019151947-ac50b-4043638a7a830fa80fd918f92365f5afe3ff208a.gz
2006-10-20 01:19:47 +10:00
axel
ea998b03f2 First stab at directory transition. Test with care...
darcs-hash:20061019115023-ac50b-30c3fd51d8af8a616d63dfcac39370d7fe6d144e.gz
2006-10-19 21:50:23 +10:00
axel
52b2525b0e Make the callback for the file autoloader optional, and clarify its use
darcs-hash:20061019114632-ac50b-a0b3e1b3e7f26aa7cd674ade1a4fb2246f978ebc.gz
2006-10-19 21:46:32 +10:00
axel
ff96668151 Minor edits to documentation
darcs-hash:20061019114024-ac50b-e283638e3a34e1d38be58971f31900129230c598.gz
2006-10-19 21:40:24 +10:00
axel
d7576a409a Make history variable contain whole history
darcs-hash:20061019113916-ac50b-7e24780cdd591ae23210f0da2cb80a4cf09ba5c6.gz
2006-10-19 21:39:16 +10:00
axel
f6815629fc Give USER and HOME default values if undefined
darcs-hash:20061019113844-ac50b-def2288d589f479779166ed64903e99c8c8ab71a.gz
2006-10-19 21:38:44 +10:00
axel
8b3bcd2c4c Tweak initial capacity calculations to always be a Mersenne number
darcs-hash:20061018230246-ac50b-3da6ada42423f5bba3f8c3fdb366ce1f352cffde.gz
2006-10-19 09:02:46 +10:00
axel
c7bc31fe50 Fix exceptaionally rare crash bug in hash tables (happens once in every 2^32 hash lookups
darcs-hash:20061018230148-ac50b-4e67ecf1f9aeae8239c40101ae2ad6aa164c31bb.gz
2006-10-19 09:01:48 +10:00
axel
bab168f1d1 Fix yet another universal variable issue with initialization of the read buffer. This may fix fishd bugs reported by Philip Ganchev and Martin Bähr
darcs-hash:20061018164438-ac50b-c586b1ad36249853d613d0137b505377fe890d37.gz
2006-10-19 02:44:38 +10:00
axel
2ab04f4043 Skip command description lookup when no commands where found
darcs-hash:20061018155151-ac50b-5562479da23b89571f91ae1e2ed15e640ef0a094.gz
2006-10-19 01:51:51 +10:00
axel
b32bbb24b9 Fix bug in command description lookup code causing missing descriptions when command is given with a path
darcs-hash:20061018155059-ac50b-40936e573c07deb6b159a16d843f02ed60e79b49.gz
2006-10-19 01:50:59 +10:00
axel
f86f80fcd6 Properly handle character sets in universal variables
darcs-hash:20061017211129-ac50b-6aecd04b74a9122ff0e1b320a2cf48db36dd2194.gz
2006-10-18 07:11:29 +10:00
axel
d563e428e8 Avoid unloading an item currently being loaded by the autoloader
darcs-hash:20061016154022-ac50b-f4b74457a9e3acdcc70076f65dff4c1f00ac379f.gz
2006-10-17 01:40:22 +10:00
axel
5473711a20 Minor code simplifications in the reader and related libraries
darcs-hash:20061016153226-ac50b-830735fadfdf578dfa4c686a2a6cd98df0e50c95.gz
2006-10-17 01:32:26 +10:00
axel
91009ac9aa Fix hang bug when appending to killring
darcs-hash:20061016150017-ac50b-c1f789d9913949ebc44cd9d02af5c3555bdf51bf.gz
2006-10-17 01:00:17 +10:00
axel
49bff53370 Avoid reading before begining of buffer when moving/erasing word, fixes crash bug reported by Martin Bähr and further described by Philip Ganchev.
darcs-hash:20061016143912-ac50b-1deacc00f6c0438e6d760568ef5b1e47e3fe08c4.gz
2006-10-17 00:39:12 +10:00
axel
afcab9f1b3 Minor bugfix in the kill-ring code
darcs-hash:20061012223200-ac50b-6a046a89295f01937a38000ef6d016b7be5c19f1.gz
2006-10-13 08:32:00 +10:00
axel
841fdf3a04 Make kill-word and backward-kill-word accumulate kills in the killring
darcs-hash:20061012193000-ac50b-69f261df78b3957b9cec3d728fe05b8a27267c31.gz
2006-10-13 05:30:00 +10:00
axel
92446bda80 Yet another tweak to the move_word function
darcs-hash:20061012161317-ac50b-3b374e2b6c4c22f82c1cf018bf83298c8216fcb1.gz
2006-10-13 02:13:17 +10:00
axel
a620a1e5ed Update todo-list
darcs-hash:20061012140247-ac50b-ae6b9a26c5979dc7080ff3fea8dad618211227e1.gz
2006-10-13 00:02:47 +10:00
axel
5a8df6cc85 Fix major memory leak in autoloader introduced by recent autounloader patch
darcs-hash:20061012133012-ac50b-d03de17d9df4d41db075b24c2f7e48ad8c0f6417.gz
2006-10-12 23:30:12 +10:00
axel
b70b966f90 Fix the kill-line, backward-kill-line and kill-whole-line commands to work correctly with multiline editing
darcs-hash:20061012132732-ac50b-03fe641cf32ace645c88174528e849ab0d1ecb4b.gz
2006-10-12 23:27:32 +10:00
axel
97f7c2093b Drop warning in parse_util.c
darcs-hash:20061012120859-ac50b-1af2af938cd99630c2ea7b532e6213c26cc4ea6b.gz
2006-10-12 22:08:59 +10:00
axel
8ece4f3ddc Better string hashing function
darcs-hash:20061012010129-ac50b-3c420efe649e892c491d9d9830dda153ca395655.gz
2006-10-12 11:01:29 +10:00
axel
17a13a8eb7 Use the xdg-open command in the open function if it exists
darcs-hash:20061011161749-ac50b-f700489a238dafbd9aec4ef4f2eed731a8622b27.gz
2006-10-12 02:17:49 +10:00
axel
afaf156a42 Fix compilation issue in test suite,. Thanks to Martin Bähr for the report.
darcs-hash:20061010224721-ac50b-0bd07f325c2026d991cf9535941060fadd5869cb.gz
2006-10-11 08:47:21 +10:00
axel
c4f3b5e9ef Unload older autoloaded functions
darcs-hash:20061010224546-ac50b-7c3f38d32d4a413a9c0d8436bb13a5d65235f3a7.gz
2006-10-11 08:45:46 +10:00
axel
f5916358e5 Fix bug in the input buffering of messages to/from fishd causing garbled messages
darcs-hash:20061010222113-ac50b-1b6b01ab781ecbadf11a99b501f19a526ae7a7cf.gz
2006-10-11 08:21:13 +10:00
axel
e3e1b34fec Only show greeting in interactive mode
darcs-hash:20061010173154-ac50b-4831a80be03ed132ca5f709dcc5284d17d828d4e.gz
2006-10-11 03:31:54 +10:00
James Vega
18bb4ca826 Makefile.in: Update clean target to preserve builtin_help.c, user_doc, doc_src/builtin_doc and remove share/fish
darcs-hash:20060920040413-35ec8-2bc89e5dff67e2cab274676df2ca90eb1bb385e9.gz
2006-09-20 14:04:13 +10:00
axel
007e4662e3 Fix bug in contains function
darcs-hash:20061009215133-ac50b-3dc99c245e69c176f334046d9746d533a106cf2a.gz
2006-10-10 07:51:33 +10:00
axel
e11677ef66 Make the greeting message configurable using the fish_greeting variable
darcs-hash:20061009214905-ac50b-cc07bf2b76c5306f96d1bca7fd478d972de25de8.gz
2006-10-10 07:49:05 +10:00
axel
194167da32 New version of the xdg fix. Unlike the previous version, this one should actually work.
darcs-hash:20061009212440-ac50b-10d1cdd7441335d033171f5b71a8a97f8a1d1dfb.gz
2006-10-10 07:24:40 +10:00
axel
dafeac5c40 Fix compilation issues in xdg library caused missing headers. Thanks to Jamessan for the report.
darcs-hash:20061009201230-ac50b-4b5c183fbd88ef45a0ededdc3eea79191951fb5f.gz
2006-10-10 06:12:30 +10:00
axel
effea85984 Apdate address of fish homepage
darcs-hash:20061009152007-ac50b-403f605d46849a3b83192d872c4f6322bf97bb7e.gz
2006-10-10 01:20:07 +10:00
axel
0b34836c79 Update dependency list
darcs-hash:20061009151948-ac50b-89b0c12a9c8763517d85bf3e46f78b7c64846db6.gz
2006-10-10 01:19:48 +10:00
axel
f85ce201ee Do not use INTERNAL_SEPARATOR tokens to separate different parts of an unescaped string when unescape_special is false. This fixes a bug where weird characters would sometimes be printed in completion descriptions
darcs-hash:20061009151913-ac50b-47a9d3274b2399cef6fd0e12a908a606da2c4903.gz
2006-10-10 01:19:13 +10:00
axel
80ac4ddc2b Allow more than one argument to the commandline builtin. The arguments will be joined together using newlines
darcs-hash:20061009141608-ac50b-546c0f5897670bb7e628d6e7c63d687eac261ee1.gz
2006-10-10 00:16:08 +10:00
axel
9a0f712e29 Make the screen repainting code slightly more robust by keeping track of whether clr_eol may be needed to clear 'debris' from e.g. resizes
darcs-hash:20061009132642-ac50b-6162ed86a97771a8da4be2adff3ad6a4f1851616.gz
2006-10-09 23:26:42 +10:00
axel
286e110fb1 Various minor cleanups
darcs-hash:20061009103408-ac50b-a54797b9f89f51a8fc8f13674e8fd2329e989d4c.gz
2006-10-09 20:34:08 +10:00
axel
988a7fddf3 Indent empty lines after a block command correctly. Thanks to Philip Ganchev for the suggestion.
darcs-hash:20061009095931-ac50b-c958a6ec7a130019527e8e06d94af010d55ac3d5.gz
2006-10-09 19:59:31 +10:00
axel
a321505351 Allow escaped newlines within qoutes, expand them to themselves
darcs-hash:20061009012248-ac50b-a403705cfe166c7686a168bc017c50c316c28161.gz
2006-10-09 11:22:48 +10:00
axel
a074cd62bc Be more rigorous with the exit codes set by the parser and builtins
darcs-hash:20061009012102-ac50b-4f28c43dd1ccdcc04d1620a6da05218a99fd7337.gz
2006-10-09 11:21:02 +10:00
axel
7a8b468165 Allow Meta-newline to always insert a newline character
darcs-hash:20061009011529-ac50b-c8e3d77b569bc445e586c95aca01e4433fbff598.gz
2006-10-09 11:15:29 +10:00
axel
770fa771b6 Unknown commands should set the status flag to 127, as in bash and friends
darcs-hash:20061008234650-ac50b-d41e6ec3d0a6088b0addf5721aecf8d98ed866cd.gz
2006-10-09 09:46:50 +10:00
axel
414fa591b8 Make sure that if a syntax error occurs, the parser does not try to evaluate command substitutions in the command
darcs-hash:20061008234458-ac50b-96f9be42b12a9d2d2b61f6700b25c1242e1c385b.gz
2006-10-09 09:44:58 +10:00
axel
941b472b37 Make sure indentation works even if a line begins with whitespace
darcs-hash:20061008232351-ac50b-122ff623a2e428352477aa52afee9a71b40e569e.gz
2006-10-09 09:23:51 +10:00
axel
179f575593 Update history loading/saving to handle multiline editing
darcs-hash:20061008135046-ac50b-e830fe313e23f632b9c645227f41c49c8ce600f4.gz
2006-10-08 23:50:46 +10:00
axel
6400b60bdd Fix a few places where uncasted 0 was used as a null pointer in vararg functions, causing potential crashes on 64-bit platforms
darcs-hash:20061008132759-ac50b-23fe4f70a5143b8b187780403d8d21fb69c3e83f.gz
2006-10-08 23:27:59 +10:00
axel
0e03e872be Fis minor memory leak in screen handling code
darcs-hash:20061008004704-ac50b-3f40073c00f1ebd8e851c49e2df873c423637d0c.gz
2006-10-08 10:47:04 +10:00
axel
e51322ac81 Make it possible to use backslash to stay in multiline mode even when not at the end of the command
darcs-hash:20061007210631-ac50b-cc8513802c247d92c8d4d5f7bcf7a146aab67a1e.gz
2006-10-08 07:06:31 +10:00
axel
1e739166b3 Fix tokenizer bug causing bad highlighting in multiline mode
darcs-hash:20061007210521-ac50b-5cdfc808389c928b932b0e41ef14abd71b537633.gz
2006-10-08 07:05:21 +10:00
axel
560e53fd5f Add autoindentation support
darcs-hash:20061007005625-ac50b-11873654797eb1e98fd17893022bdf995be3e2aa.gz
2006-10-07 10:56:25 +10:00
axel
184d58cd36 Buffer calls to read() in the universal variable code
darcs-hash:20061006184539-ac50b-d8ecc4c45d0caae12cd60e32515a1218b37831d3.gz
2006-10-07 04:45:39 +10:00
axel
bcf3024cf0 Update todo list
darcs-hash:20061005201141-ac50b-5441cefd081ede3d7b02c5955c828ac7c3f132c3.gz
2006-10-06 06:11:41 +10:00
axel
9611a3b205 Color the ellipsis used by line wrapping as comments. Thanks to Philip Ganchev for the suggestion.
darcs-hash:20061005194026-ac50b-2708cfe79f28dbae9febc3fc5fcddb48c1fc8822.gz
2006-10-06 05:40:26 +10:00
axel
8ace1739f5 Add missing newline in error message for popd function. Thanks to Phipip Ganchev.
darcs-hash:20061005064419-ac50b-4770f393ea02761a5f4b4044b456d1b618d6da23.gz
2006-10-05 16:44:19 +10:00
axel
302516a747 Fix bug causing ls function to never color or classify files
darcs-hash:20061004235530-ac50b-815b8576b4d845c4d5929e034177c917fc050cae.gz
2006-10-05 09:55:30 +10:00
axel
ad5a6e0552 Move the code keeping track of file descriptor modification from reader.c to screen.c
darcs-hash:20061004233312-ac50b-9a10ff758375885ae78a5e5c04279c1976a037ea.gz
2006-10-05 09:33:12 +10:00
axel
873fd83307 Drop the optional checking of block type for the end builtin
darcs-hash:20061004233206-ac50b-cf72c879b4b58c8e5ba4e1dff5c2746ca2e8844f.gz
2006-10-05 09:32:06 +10:00
axel
d1078f8582 Detect and handle terminals size changes
darcs-hash:20061004214502-ac50b-aaf5b76a6281c0ba8757e794b0a802793ce92916.gz
2006-10-05 07:45:02 +10:00
axel
0ea668b260 Minor code cleanup
darcs-hash:20061004214204-ac50b-e1529fcedb1665f9871a95eba293a4a3c1150464.gz
2006-10-05 07:42:04 +10:00
axel
91c745e4b5 Add the possibility to set the cursor position using the commandline builtin
darcs-hash:20061004213948-ac50b-3f673edeb01390bb3f280812d90bc8469f2f8ba8.gz
2006-10-05 07:39:48 +10:00
axel
7d73349889 Add the possibility to set the input that the commandline builtin operates on
darcs-hash:20061004184939-ac50b-f2c3e2161a5bf77834a566462ac9942571c9d6ea.gz
2006-10-05 04:49:39 +10:00
axel
53a2c017fe Mangle very long variable values when using the set builtin to print variables and their values
darcs-hash:20061004181901-ac50b-a043695fa8fffe877970a51dd042c4bf623a770c.gz
2006-10-05 04:19:01 +10:00
axel
80ff583400 Use universal variables for fish_function_path and fish_complete_path
darcs-hash:20061004175519-ac50b-2e9dabc9ce1c21ebfcba020db8a8d84ef48433e9.gz
2006-10-05 03:55:19 +10:00
axel
0c7f74c78d Repain prompt after showing completion pager
darcs-hash:20061004102706-ac50b-51d0603c81f3125c01bad0901f8d2b745fc18e4a.gz
2006-10-04 20:27:06 +10:00
axel
13b1ea3f50 Various fixes to make double-wide characters (e.g. asian characters) work with the new multiline editing code
darcs-hash:20061001232136-ac50b-9bd771b382c00b71c5e2ee75df77ba2594b2a738.gz
2006-10-02 09:21:36 +10:00
axel
44ff9956b9 Second cleanup of multiline editing patch. Add code comments, use better variable names, etc..
darcs-hash:20061001212243-ac50b-6cd5abfcf6b7013fd23b27734ca29af27d945ca3.gz
2006-10-02 07:22:43 +10:00
axel
add1fa9208 First cleanup of multiline patch - add support for commands longer than one line and do minor cleanups, including removal of a few unused functions
darcs-hash:20061001205423-ac50b-2819a086fecb1bcd0ab1bc63bae76956f0181f54.gz
2006-10-02 06:54:23 +10:00
axel
8b2059c628 Add function to insert a range of new elements into the middle of an array_list
darcs-hash:20061001201728-ac50b-db2f7bccee53224f50347c8995b2f6496940243d.gz
2006-10-02 06:17:28 +10:00
axel
15724d0798 First stab at multiline editing
darcs-hash:20061001160258-ac50b-1a760913e64b96e30ff321d7fbe4069ca161cdfe.gz
2006-10-02 02:02:58 +10:00
axel
2839f5e567 Minor comment and documentation edits
darcs-hash:20061001155918-ac50b-8b5b4f5dbd8334bac1c0dc77fa18c8f3cfb4a878.gz
2006-10-02 01:59:18 +10:00
axel
67c820cee8 Minor tweaks to code validation for the for builtin (again)
darcs-hash:20061001155734-ac50b-6009b98dfccaf8f8292859f25c4d564c6b622f47.gz
2006-10-02 01:57:34 +10:00
axel
bce4c78d49 Further reduction of malloc calls in the history
darcs-hash:20061001152040-ac50b-085f4b8ce20c4793d5e592f7a213df04208630cb.gz
2006-10-02 01:20:40 +10:00
axel
421ebcc2d7 Be a bit more careful with memory alignemnt in halloc
darcs-hash:20060930121917-ac50b-6292696663684a38844b4c21360274b365e52969.gz
2006-09-30 22:19:17 +10:00
axel
92df4a6d91 Make sure M-d erases last character of word. Thanks to DynWind for the report
darcs-hash:20060929214804-ac50b-ffb19242fcbd594fb72016427704cb51cf9d0a22.gz
2006-09-30 07:48:04 +10:00
axel
22fe8e6a17 Fix bug in the setenv function (values wheren't exported!), thanks to Matrin Bähr for the report.
darcs-hash:20060928165405-ac50b-5ada00cfc08805677e1932c800ee79d68e35a68b.gz
2006-09-29 02:54:05 +10:00
axel
d0f1870735 Add syntax check to see that the for builtin is not given an insufficient number of arguments
darcs-hash:20060926124109-ac50b-b088397933fa7ea539e48fa9fcd461de8295f7ce.gz
2006-09-26 22:41:09 +10:00
axel
b71f5d09b0 Fix occasional off-by-one bug in syntax highlighting causing the character next to the cursor to be unhighlighted instead of the cursor itself
darcs-hash:20060924175723-ac50b-35757e87eb7076c2ecdecaed11c1bb673c571035.gz
2006-09-25 03:57:23 +10:00
axel
eb00ad77fb Make sure isatty docs are built into the main doc file
darcs-hash:20060919175509-ac50b-0174257f46e15d6e931bd8664e8a83ac498707b2.gz
2006-09-20 03:55:09 +10:00
axel
be886bc6df Unly use classifications in ls if stdout is a tty
darcs-hash:20060919165317-ac50b-c7923c7f5900ecc9814756743e6b0345efa382c5.gz
2006-09-20 02:53:17 +10:00
axel
7a5823fd60 Documentation updates from Beni Cherniavsky
darcs-hash:20060919145203-ac50b-bc87b8f5e6a18395e4bc3e364da4a40ad97850e7.gz
2006-09-20 00:52:03 +10:00
axel
81d61c467b Fix bug in for that causes crash on syntax error
darcs-hash:20060919142140-ac50b-48cbbdfd109e2b420d8e36acd5b13696445c0850.gz
2006-09-20 00:21:40 +10:00
axel
e91e3b6593 Minor bugfix in the switch parsing for the status builitn
darcs-hash:20060919142042-ac50b-b532e0308407d101d1f8b328a575a54e8bc46799.gz
2006-09-20 00:20:42 +10:00
axel
1db67a5105 Add completions for the wpa_cli command
darcs-hash:20060918222913-ac50b-9aeac9d1a5ecb4b6915625b07133b66ebab0b2bd.gz
2006-09-19 08:29:13 +10:00
axel
810faacd72 Make sure that syntax validator allows use of 'break' and 'continue' with --help even outside of loops, and make sure 'return' is only used in function definitions.
darcs-hash:20060918001518-ac50b-78977cbd17e4edce8d1b7d4c5426f478d42392af.gz
2006-09-18 10:15:18 +10:00
axel
6be3807cae Fix issue with ^W and other shortcurs sometimes not deleting anything
darcs-hash:20060916230532-ac50b-395d34e2c67d2be3d634638265a98239442fd6cd.gz
2006-09-17 09:05:32 +10:00
axel
4399503f4e Fix a bug in completion insertion code on string with escaped quotes. This bug was reported by David Benbennick.
darcs-hash:20060914151821-ac50b-c6628fc01a90865e0aec6e93b39b77c3877606fc.gz
2006-09-15 01:18:21 +10:00
axel
06b5fdc6e8 Update todo-list. Thanks to MArtin Bähr for the additions.
darcs-hash:20060913212744-ac50b-cb446bcebc04a89c7b065e2d3879b474740a005e.gz
2006-09-14 07:27:44 +10:00
axel
4037219dc0 Make sude completions include /sbin and /usr/sbin in PATH. Thanks to Xavier Douville for the suggestion.
darcs-hash:20060913171310-ac50b-a9e30533bc634f194f73fdee1e042d407f55fcac.gz
2006-09-14 03:13:10 +10:00
axel
1612ec50fb Fix bug in __fish_complete_subcommand, reported by Xavier Douville
darcs-hash:20060912231409-ac50b-c573d798d9d1abc197fcf50f3b52df2e44e1f70e.gz
2006-09-13 09:14:09 +10:00
axel
3bb0163598 Update todo-list again
darcs-hash:20060912221050-ac50b-1c16582591642beba13f83224dc7ef47cb9c5a0a.gz
2006-09-13 08:10:50 +10:00
axel
4d19aa7698 Update todo-list
darcs-hash:20060912215025-ac50b-448068ea065db5d2db4bb68b7e41ef4e986ecc83.gz
2006-09-13 07:50:25 +10:00
axel
f72de8e141 Ugly kludge to fix ugly header output from Doxygen in man-pages
darcs-hash:20060912155058-ac50b-50487271adc31d20a0e07e742a1cbe724068be6d.gz
2006-09-13 01:50:58 +10:00
axel
02eb856e44 Don't syntax highlight the character under the cursor, since that may hide the cursor. Thanks to Matin Bähr and Philip Ganchev for the reports
darcs-hash:20060911143935-ac50b-e1502365aeba0f4d97976f688329cbfc4b9871a4.gz
2006-09-12 00:39:35 +10:00
axel
c550f4eb21 Add completions for xpdf and xmms, written by Vikas Gorur
darcs-hash:20060911141848-ac50b-a541eafba3f0155b207963633262229330c01bea.gz
2006-09-12 00:18:48 +10:00
axel
00c25436d7 Make it possible to save a function when defining it using the -S switch
darcs-hash:20060908141241-ac50b-69a055a1e791e04e2b1208a5c36b9bb22c854c12.gz
2006-09-09 00:12:41 +10:00
axel
6107d63995 Add wmkdir function
darcs-hash:20060908141128-ac50b-9b67d1c5af9f746be18509bad3a0e8988efce29a.gz
2006-09-09 00:11:28 +10:00
axel
eafa0a7169 Bugfix in the wdirname function
darcs-hash:20060908141041-ac50b-8650eea2d071606654cad94553344ed12b4bf609.gz
2006-09-09 00:10:41 +10:00
axel
45d2b89780 Use halloc in history as well as other minor cleanups in history.c
darcs-hash:20060908123455-ac50b-9a3aa6a186fc883621c120cd0964a05ed595f2a4.gz
2006-09-08 22:34:55 +10:00
axel
72d73b7fdd Fix crash bug in cyntax validator when using an illegal command name. Thanks to Martin Bähr for the report.
darcs-hash:20060907201559-ac50b-34fa01bbc40eafddcc64a5111bebd88aab75a8d4.gz
2006-09-08 06:15:59 +10:00
axel
227a5da02c Fix syntax bug caused by new cmdsubs slicing feature. Thanks to Martin Bähr for the report.
darcs-hash:20060907201145-ac50b-8315f1c207883bfbe56db2ec8b3a8b3635e8dc84.gz
2006-09-08 06:11:45 +10:00
axel
e356bdaa8e Optionally add type of block to the end builtin to verify block nesting correctness
darcs-hash:20060905204347-ac50b-d0f87a700e38cdff9787be827b0df90b7f7baba5.gz
2006-09-06 06:43:47 +10:00
axel
697d524687 Clear error buffer before creating new error message to avoid bug causing all previous errors to accumulate
darcs-hash:20060905204020-ac50b-6ecc9e4c57a6b387431cef32c734ca525f05c26c.gz
2006-09-06 06:40:20 +10:00
axel
73f0d0bb48 Fix warning when help function is called with no arguments
darcs-hash:20060904201612-ac50b-63b83a589735021a6afd6be193500b549e3b25dd.gz
2006-09-05 06:16:12 +10:00
axel
200ebe43dc Add math shellscript function, which is a thin wrapper around bc
darcs-hash:20060904160023-ac50b-0d784182ca3930b0987d4338655b8717237e842c.gz
2006-09-05 02:00:23 +10:00
axel
ff2d354ef8 Bump version number
darcs-hash:20060904002509-ac50b-098c9c879257d689a975abd102f9b4d9fc00f592.gz
2006-09-04 10:25:09 +10:00
axel
3bef568955 Fix nagging warning message
darcs-hash:20060903234751-ac50b-c5d7f026323b5cab450e1770be572dcdf3ecc904.gz
2006-09-04 09:47:51 +10:00
axel
9a7be6db08 New status message for fish_pager
darcs-hash:20060903231209-ac50b-b8bad71cb9194a905918534fafec619118d61e21.gz
2006-09-04 09:12:09 +10:00
axel
40e2025327 Minor polish
darcs-hash:20060903230006-ac50b-c55a9272bb1cdb10312b8580c4c2a85654329e30.gz
2006-09-04 09:00:06 +10:00
axel
a819c863eb Skip bug causing autoloader to sometimes use the wrong version of a function. Thanks to Martin Bähr and Mystilleef for the bug reports.
darcs-hash:20060903225839-ac50b-5b1f3d5f0b8c54b999836c3384c22c2a31c31bd0.gz
2006-09-04 08:58:39 +10:00
axel
827c88e4a1 Fix bug where using the return builtin inside an if-block could cause the else-block to get executed
darcs-hash:20060831205320-ac50b-64ecbaa3ed5e32c1a815ba384a6831a8fd5e1b47.gz
2006-09-01 06:53:20 +10:00
axel
e2b7a078f4 Make "$foo\[1]" not be an array slicing. Notice the extra backslash
darcs-hash:20060831155932-ac50b-746462d2147f349f9a799cb4786a0abacd1d3d4a.gz
2006-09-01 01:59:32 +10:00
axel
6de0c4103b Add support for \cx backslash escapes for control sequences, syntax is borrowed from bash
darcs-hash:20060831155813-ac50b-cc93412afc87c1c391c3dbc5e7b8c9175efe01d8.gz
2006-09-01 01:58:13 +10:00
axel
b6e8171f01 Fix minor null pointer bug in the set builtin, fix bug causing the -n switch to be ignored, add missing completions for the -n switch to functions and set builtins, and touch up the documentation for said builtin a bit
darcs-hash:20060831154400-ac50b-dddbee79481e0e0a8da9fc025e8a15c466460a2f.gz
2006-09-01 01:44:00 +10:00
axel
b1439075c6 Updated definiton of move_word, more intuitive behaviour when a token consists only of non-alphanumerics
darcs-hash:20060831004525-ac50b-aa6675809f0f17fa266982374700a8a4ce6b2f5a.gz
2006-08-31 10:45:25 +10:00
axel
7df536023b Fix concurrency bug in autoloader causing memory leak
darcs-hash:20060828162734-ac50b-76c88ba8cc164646dcff16cb899633f1e10392e2.gz
2006-08-29 02:27:34 +10:00
axel
f5f15f9de2 Use dynamically sized buffer for reporting error messages in the parser
darcs-hash:20060828151913-ac50b-02453c13d107f88023b2331bf40daf6d329ac597.gz
2006-08-29 01:19:13 +10:00
axel
0e0a61119f Update english transliteration
darcs-hash:20060828130147-ac50b-2b07adaa3fd63cf0cd2b0122fef45b9aee365e37.gz
2006-08-28 23:01:47 +10:00
axel
6f058c687d Add fallback if SIGWINCH is unavailable
darcs-hash:20060828122515-ac50b-f2b8f1519bbbd62908a6648255bfb20bdce83212.gz
2006-08-28 22:25:15 +10:00
axel
53ea5d60b7 Minor code tweaks, mostly things like indentation, but also a ferw code reorderings
darcs-hash:20060828120244-ac50b-ad4be149ff245b6f799452f9eeff7bcc60af1526.gz
2006-08-28 22:02:44 +10:00
axel
9525f429c6 Dont let fallback implementation of killpg kill group 1
darcs-hash:20060828120122-ac50b-c5e3eb7392654feb378cdfcf11ab102418aa1386.gz
2006-08-28 22:01:22 +10:00
axel
548e379d6a Provide fallback version of getopt_long instead of checking for it's presense every time it is used
darcs-hash:20060828114305-ac50b-f4aad19e936fa42bbe84e51e72aa32445a469527.gz
2006-08-28 21:43:05 +10:00
axel
202d29de88 Restructure the autoloader. This fixes a very weird and rare Heissenbug, probably caused by a compiler bug, but also makes the structure of the code a bit more logical.
darcs-hash:20060828110019-ac50b-7be19eda18eb358163a9a5b7180c6c7d028e546d.gz
2006-08-28 21:00:19 +10:00
axel
23152ae8a6 Remove checks for gettext presense in mimedb.c and set_color.c. If gettext is unavailable, a fallback is provided.
darcs-hash:20060828105806-ac50b-47f092813ed70a03477d66c377edbe24f2aedf40.gz
2006-08-28 20:58:06 +10:00
axel
7310596dab Much more reliable getopt_long test. Idea from Netocrat.
darcs-hash:20060828102949-ac50b-bb55face2f3127018b6c79a72ee71e38f075232a.gz
2006-08-28 20:29:49 +10:00
axel
4afe49d7c6 Redo the -POSIX_C_SOURCE test to only add macros if they are found to fix things. Also add -stdÉ9 to CPPFLAGS if it is added to CFLAGS. Also add more comments, redo indentation and general file cleanup. Written cooperatively by Liljencrantz and Netocrat.
darcs-hash:20060828100334-ac50b-73eed298fdf5a853243413f0f12c235ffa9e787a.gz
2006-08-28 20:03:34 +10:00
axel
d7c3d2acbf Use OK as return value for del_curterm fallback
darcs-hash:20060828100046-ac50b-e52e7181ffb6fa5b1b3162ac3ae0aacc9bf7f5a3.gz
2006-08-28 20:00:46 +10:00
axel
f771fce892 Add a $version variable. Suggested by Martin Bähr
darcs-hash:20060828095840-ac50b-db561647eee1d06785448a4bfc6826eef5aec2b7.gz
2006-08-28 19:58:40 +10:00
axel
6522000bf0 Don't turn of file completion in svn completions if given an unknown subcommand
darcs-hash:20060827144853-ac50b-d09576fd6984eb18b06e0e7b1d8a88aa7b9d1df4.gz
2006-08-28 00:48:53 +10:00
axel
285abcc9bc Do not use the non-standard -i switch for sed
darcs-hash:20060827131554-ac50b-b969c2a56607ff46d028f5c44faabf2842814f0e.gz
2006-08-27 23:15:54 +10:00
axel
b15e8123ca If no completions have been found, use file completion even if command specific completions have disabled file completions. Suggested by MArtin Bähr.
darcs-hash:20060827005740-ac50b-41c3bf2bb91bcfc0122c317bcc2aca2061cd019e.gz
2006-08-27 10:57:40 +10:00
axel
1c86395ed8 Fix bug reportad by Martin Bähr that causes fish fail when using blocks in pipelines in interactive mode.
darcs-hash:20060827005252-ac50b-09c98537b9de72f0d4a2e5a28490b2e38fe321c8.gz
2006-08-27 10:52:52 +10:00
axel
3c8d2a1126 Don't use carriage return on initial painting of the prompt
darcs-hash:20060826022416-ac50b-16746f45142589e7fa83e95b6ee6a2fad98432c4.gz
2006-08-26 12:24:16 +10:00
axel
ed8cd08984 Fix minor memory leak in completion code
darcs-hash:20060826021948-ac50b-6fecba2056e47cb7c4e8499f2a51e1c0c23d0757.gz
2006-08-26 12:19:48 +10:00
axel
69537430ea Fix bug in completion code reported by Martin Bähr, as well as other bug evident in his bug report.
darcs-hash:20060826013722-ac50b-08de084a40af8ba5d708a7cd162087b7afbb7648.gz
2006-08-26 11:37:22 +10:00
axel
0a603a56c6 Minor bugfix for the completions for the complete builtin
darcs-hash:20060825154545-ac50b-eaa8b210ddc6fb6a089deb5c2b19723bd92228f3.gz
2006-08-26 01:45:45 +10:00
axel
046dd82995 Add minor new completion for make command
darcs-hash:20060825154516-ac50b-80284df4f7dd6cd332f2b21f5c9bdc359cc00eca.gz
2006-08-26 01:45:16 +10:00
axel
97c3e231f4 Allow slicing of command substitution output
darcs-hash:20060824133904-ac50b-fbc43cf30d8eb15e50343b786af77f85fb0b8d4e.gz
2006-08-24 23:39:04 +10:00
axel
76b782d576 Do not mix wide and narrow printf calls on stderr in set_color.c
darcs-hash:20060824133828-ac50b-399d9c8d4f6cd7c36ceb2991011d9dae23851d6f.gz
2006-08-24 23:38:28 +10:00
axel
ed5c1db392 Bump version number
darcs-hash:20060824105129-ac50b-999429675a936c246665940ee9154a524eae4be2.gz
2006-08-24 20:51:29 +10:00
axel
37f5db2bf9 Use terminfo to look up tab width instead of assuming 8 character tabs when calculating prompt width
darcs-hash:20060824104354-ac50b-bfb6428411a9c3f6e7a8df980b1005fdd1842a10.gz
2006-08-24 20:43:54 +10:00
axel
8a97bffd02 Spelling correction in documentation
darcs-hash:20060824103055-ac50b-8a81c73571b76dd2800787ca6e5bd29787eb9501.gz
2006-08-24 20:30:55 +10:00
axel
2fd48bce11 Fix use og uncasted 0 as null pointer in vararg function. Potential crash bug on 64 bit systems.
darcs-hash:20060824103014-ac50b-3fb830f548d383b8cef7a37b737c90f3ad30c4bd.gz
2006-08-24 20:30:14 +10:00
axel
d1a3e6abf5 Complete --do-complete argument should be optional
darcs-hash:20060824005315-ac50b-fa4fb8177bc11cf20f2f95fff43cd674a439bae0.gz
2006-08-24 10:53:15 +10:00
axel
1a29979bbd Ignore return code of exec_subshell when doing command substitution
darcs-hash:20060824005217-ac50b-9de976e1fe2d396b08b59619e46669bad6598ec2.gz
2006-08-24 10:52:17 +10:00
axel
69814e5066 Add documentation about new backslash escapes, and correct a broken link in the docs
darcs-hash:20060824005117-ac50b-39a1f56891c92e6a9b64b20fdd4bfd7d60090949.gz
2006-08-24 10:51:17 +10:00
axel
4dbac8f941 Add support for \a \f \v escape sequences, and make supåport for \e standards compliant
darcs-hash:20060824002609-ac50b-a1a9150d096647d9ab4c39d3245b528d7e75cd57.gz
2006-08-24 10:26:09 +10:00
axel
303473f20c Fix incorrect usage of the term subshell when command substitution was meant
darcs-hash:20060822143831-ac50b-cb5267a6434adcbd5bafb452d688bee06c23d4d6.gz
2006-08-23 00:38:31 +10:00
axel
480a29594e Minor tweaks to previous fish_pager patch to fix two bugs
darcs-hash:20060822135815-ac50b-35d9f643385ec29f9d8f93ca83d01e060de93cc7.gz
2006-08-22 23:58:15 +10:00
stew
dfe3dc1429 fish_pager_via_stdin
darcs-hash:20060822012451-2edb7-d8939fab708d8c605d2c7d0683c71f11db659bc9.gz
2006-08-22 11:24:51 +10:00
axel
2ea00ce444 help --help should be same as help help
darcs-hash:20060822005230-ac50b-b82c0665cae7427c09992f51e128e33cea44b41e.gz
2006-08-22 10:52:30 +10:00
axel
ac13bdeaa7 Work around Doxygen bug in man-file generation
darcs-hash:20060822004853-ac50b-3c5036484961825304059567670eea0ccb3cd643.gz
2006-08-22 10:48:53 +10:00
axel
22cb7dd2d7 Add horizontal ruler between documentation for builtins and commands
darcs-hash:20060822004810-ac50b-aa75e233685ce4e0c22cde27411550a13efbeff6.gz
2006-08-22 10:48:10 +10:00
axel
20698cc813 Remove duplicate include
darcs-hash:20060817155050-ac50b-bbbd5130688d1f3f5f4e4d48c4319faf4413995a.gz
2006-08-18 01:50:50 +10:00
axel
1ebf571da5 Update french translation, thanks to Xavier Douville
darcs-hash:20060814181448-ac50b-08e5a5e8eff3316411469730d03d756170e4b01a.gz
2006-08-15 04:14:48 +10:00
axel
7c822cbf30 Add a message to stdout in the help function describing where the help went if help opens an external browser window
darcs-hash:20060814181135-ac50b-6d9b05b714bc9576c260e87b5706e7d94dd73e39.gz
2006-08-15 04:11:35 +10:00
axel
90302d9232 Documentation correction
darcs-hash:20060814120540-ac50b-25daddbd1130d1b57837affa6c58542fd91ff59e.gz
2006-08-14 22:05:40 +10:00
axel
bee6805ff9 Check return value of del_curterm
darcs-hash:20060813230502-ac50b-2b7e30d3560097725789bf6aa659835e30c7a81b.gz
2006-08-14 09:05:02 +10:00
netocrat
65035c4dc7 Change null function to #define for del_curterm() - solves build problem on some BSDs.
darcs-hash:20060813030853-344c5-7aa2cc3c70044214d90263999f2312f8f10296a4.gz
2006-08-13 13:08:53 +10:00
netocrat
2b0d64184a Switch back to using -D for _POSIX_C_SOURCE and _XOPEN_SOURCE - solves build problem on Solaris 10
darcs-hash:20060813030806-344c5-ad0eec62d3ce93d98adcad4b93318b06538eef95.gz
2006-08-13 13:08:06 +10:00
axel
51d7159ba7 Update fish_pager interface, first try - this is the second patch to redo the fish_pager interface. Both this one and the previous one breaks the display of completions
darcs-hash:20060813014602-ac50b-3d30e3486021b1ffddf3f1a69e86ee51a6aac611.gz
2006-08-13 11:46:02 +10:00
axel
0a4819be27 Add support for buffering of input to a command, the first step to piping data to fish_pager instead of using the argument list
darcs-hash:20060813013803-ac50b-f8000d4c96162023411f84643f47221860b350b2.gz
2006-08-13 11:38:03 +10:00
axel
72ad4e0d3b Make fish pager use non-universal variables as well for getting it's colors
darcs-hash:20060811145528-ac50b-26be05f363f353d87ebceccf73385cd1af1c88f2.gz
2006-08-12 00:55:28 +10:00
axel
21de293a44 Fix missing quote in configure.ac
darcs-hash:20060811142930-ac50b-52d1bb6faf07b6a0ddac754cee16e899dd196679.gz
2006-08-12 00:29:30 +10:00
axel
8b395d05ef Switch to using AC_DEFINE instead of using -D switces in CFLAGS for a few macros that don't need to be passed through the Makefile
darcs-hash:20060811134859-ac50b-6efc59b9214909aa6804bed9c5919ed0e29ddf81.gz
2006-08-11 23:48:59 +10:00
axel
8392902cec Remove unneded include in Autoconf test. Thanks to Netocrat.
darcs-hash:20060811101005-ac50b-275a1240e7802f70eb763be42683b4d1f816a9b0.gz
2006-08-11 20:10:05 +10:00
axel
a5abdd2792 Always redefine del_curterm to be a no-op under bsd, seeme the double free bug can surface under ncurses as well. Thanks to Netocrat.
darcs-hash:20060811100756-ac50b-1b1010b696fdd9acf45ef85ab19e75f574e5198b.gz
2006-08-11 20:07:56 +10:00
axel
e784683b8a Comment away currently unused function to avoid warning. Thanks to Netocrat.
darcs-hash:20060811093051-ac50b-d025c406234bb31e36c0b0b7951b54c6fc62ed07.gz
2006-08-11 19:30:51 +10:00
axel
7fadf6c083 Do not call closedir on directories that failed to open. Avoids crash bug. Thanks to Netocrat.
darcs-hash:20060811092639-ac50b-6615f51aad8c2a81917db08e2dc8f4da3d7db2ef.gz
2006-08-11 19:26:39 +10:00
axel
7ff76476ed Remove non-unicode character in documentation file. Thanks to Netocrat.
darcs-hash:20060811092603-ac50b-59a68550fa3279662113ec080b18e7930bb02fe2.gz
2006-08-11 19:26:03 +10:00
axel
cd9102214b Rearrange includes so that config.h is always the first file to be included
darcs-hash:20060811011835-ac50b-847fc790288e3bb3f3a0ee7734ff278d2dc65bef.gz
2006-08-11 11:18:35 +10:00
axel
8da54a1955 Add two BSD-specific preprocessor macros to get additional prototypes. Thanks to Netocrat.
darcs-hash:20060810203756-ac50b-21259e610fc738c6ad990d88b0af74d56d6a38f8.gz
2006-08-11 06:37:56 +10:00
axel
6899e4e734 Do not use ! to negate shellscript results, this is unsupported on Solaris. Thanks to Netocrat.
darcs-hash:20060810194951-ac50b-7baee5f1ab962fac6fbb37f13e0a8ba134e910e2.gz
2006-08-11 05:49:51 +10:00
axel
486e0dbe84 Remove Solaris circular dependency in init file. Thanks to Netocrat.
darcs-hash:20060810193338-ac50b-2f1f68170610e1669fc20298fcce50a920c3f38f.gz
2006-08-11 05:33:38 +10:00
axel
441c109afb Remove unneded includes in autoconf tesst and add possibly needed one. Thanks to Netocrat.
darcs-hash:20060810192359-ac50b-8e38e24ada59928cf6f37e7ed625fe40a34fd5d7.gz
2006-08-11 05:23:59 +10:00
axel
4b0810d7e9 Added missing include in input_common.c, needed under FreeBSD. Thanks to Netocrat.
darcs-hash:20060810190246-ac50b-190b0b2e1fbcab0bd742f5b98f7e1e173b793800.gz
2006-08-11 05:02:46 +10:00
axel
51d58a6a7c Added missing line continuation. Thanks to Netocrat.
darcs-hash:20060810185244-ac50b-944f18d3bed557061e0625b805e51a6a743835ae.gz
2006-08-11 04:52:44 +10:00
axel
7a884e11a6 Avoid circular dependency in ls autoload. Second try.
darcs-hash:20060809231155-ac50b-52b1b1609307fb05d3d8f32c972b0a22476a1da8.gz
2006-08-10 09:11:55 +10:00
axel
c4acfdd87c Add missing files to make uninstall
darcs-hash:20060809230749-ac50b-2948357bb000b47b49b6310dabd84410fde3b461.gz
2006-08-10 09:07:49 +10:00
axel
41f8007a03 More header/autoconf fixes, improve winsize checking
darcs-hash:20060809225338-ac50b-7162a690e44e2272f4760723f5bf8cc135dc5952.gz
2006-08-10 08:53:38 +10:00
axel
8207030b21 Fix typo in seq.in
darcs-hash:20060809225230-ac50b-8371f5fd1a22526325d46f5a0565e3a38d51bb78.gz
2006-08-10 08:52:30 +10:00
axel
a2c70f495e Use string.h not strings.h in all cases
darcs-hash:20060809223452-ac50b-67c4b5af37ebd17ff6d7c1403ff3231272f35465.gz
2006-08-10 08:34:52 +10:00
axel
b11f366bb0 Add SIGUSR1 as fallback if SIGIO doesn't exist
darcs-hash:20060809222656-ac50b-9a1f5a202f012c836570041acb6064849e7b0de5.gz
2006-08-10 08:26:56 +10:00
axel
0e1a3c7c4a Add missing sys/select.h header needed on FreeBSD
darcs-hash:20060809222605-ac50b-7914c1eb0509a01bfb6d07a04e29e126218f89dc.gz
2006-08-10 08:26:05 +10:00
axel
d3a75a354a A new faq question and some minor documentation edits
darcs-hash:20060809114048-ac50b-0fe667bfe9cdcade6480137f2cf5982cc743288c.gz
2006-08-09 21:40:48 +10:00
axel
afc49dded2 Minor edits to the spec file
darcs-hash:20060809113614-ac50b-ab6ca380a48586ef95256ab8acb77da42854829b.gz
2006-08-09 21:36:14 +10:00
axel
49b232df84 Add a few missing dependencies for the spec file
darcs-hash:20060809113554-ac50b-cbc408698f102c3e3170a119acfafe7569c56592.gz
2006-08-09 21:35:54 +10:00
axel
248d11c462 Only write out titlebar message if it is of non-zero length
darcs-hash:20060809113424-ac50b-59988efa4dd788d6623023b642fd96989c4c9ada.gz
2006-08-09 21:34:24 +10:00
axel
6b1570b745 Tweak spec file as per suggestions from Michael Schwendt
darcs-hash:20060801135709-ac50b-07c6191b7464ba90dd64c78ae18df8b59e8e18ad.gz
2006-08-01 23:57:09 +10:00
axel
dc3634dc94 Add posix macros in configure.ac, not in Makefile, so that they will be honored by the configure tests
darcs-hash:20060801013123-ac50b-0c561ad5afd6e71230e29a25d467ed63c47b9f17.gz
2006-08-01 11:31:23 +10:00
axel
696b4df1c6 Add __EXTENSIONS__ macro when under Solaris
darcs-hash:20060801013018-ac50b-08925f5e5239e48ca3024717d5fec2e82138ca5a.gz
2006-08-01 11:30:18 +10:00
axel
65f4d6e866 The xpg4-path was mistyped. Fix it.
darcs-hash:20060801005736-ac50b-ef8389777e012f9f0b6edcb3df3d638158f87373.gz
2006-08-01 10:57:36 +10:00
axel
8833e8f4ea Fix minor nit in comment
darcs-hash:20060801005246-ac50b-56cb6d2245ce81d16807028749495b8e5a86cc3c.gz
2006-08-01 10:52:46 +10:00
axel
f29026b767 Fix another typo in common.c
darcs-hash:20060801004648-ac50b-4177620e4ee37ab1ad6f942faa3023cedeee9055.gz
2006-08-01 10:46:48 +10:00
axel
7ecf7c1fac Fix typo in common.c
darcs-hash:20060801003556-ac50b-fb20d6405d2d8fc8d343d040afbf3863bac07b2f.gz
2006-08-01 10:35:56 +10:00
axel
4a2fa5ea34 Fix typo in signal.c
darcs-hash:20060801002550-ac50b-3412377a694aac72d04e6eae3173ac0980724e60.gz
2006-08-01 10:25:50 +10:00
axel
03f6656af6 Use S_IS* macros instead of S_IF*, which are non-posix
darcs-hash:20060801002411-ac50b-e5afcbfe4adfc54333c982b43309091c1cbcc1c9.gz
2006-08-01 10:24:11 +10:00
axel
8e6dbe245c Changes to the fish spec file, written by Paul Howarth. Fixes spelling and broken dependencies.
darcs-hash:20060731212954-ac50b-630beb87b4563118c132dbf1c525d492b30df3eb.gz
2006-08-01 07:29:54 +10:00
axel
daf171aa86 Make grep call in seq fallback implementation Posix compliant
darcs-hash:20060731165626-ac50b-5560aebc877f49f4942b2c730273d8c2424bec24.gz
2006-08-01 02:56:26 +10:00
axel
d1bbb89389 Move over a few more objects to the new array_list functions
darcs-hash:20060731165511-ac50b-7858829e6a612e0c737d82d3d71d6833dc97f078.gz
2006-08-01 02:55:11 +10:00
axel
bd0c1573df Fix bug when using same array index more than once in a single array expansion, e.g. $PATH[1 1 1]
darcs-hash:20060731164816-ac50b-d3fc56b425035a4cbcf93a91435f9df9ca5997ac.gz
2006-08-01 02:48:16 +10:00
axel
2700a9b697 Use the new array_list functions in exec.c
darcs-hash:20060731163548-ac50b-3b503e0457b33c6bb2eda0040a9fa7f15e6afe32.gz
2006-08-01 02:35:48 +10:00
axel
474f6e90ff Use maxi not max in test suite when comaparing ints
darcs-hash:20060731163119-ac50b-94134f758d9cd7e87746fb93f187aa100c1b820d.gz
2006-08-01 02:31:19 +10:00
axel
7cbc11f1c3 Minor documentation additions
darcs-hash:20060731163027-ac50b-8532ecadc755400fc1be1f029fcec49412764da2.gz
2006-08-01 02:30:27 +10:00
axel
09f9d43be3 Drup minf/maxf from util.h, they are unused
darcs-hash:20060731162550-ac50b-6b4d29d73ef7d672c3c0f9070b528b96b9ec0c16.gz
2006-08-01 02:25:50 +10:00
axel
109e7455a8 Use the new array_list functions in builtin.c
darcs-hash:20060731162339-ac50b-e8a6bd2c327b8fa5527b739fba544994e1a809e3.gz
2006-08-01 02:23:39 +10:00
axel
9b95332aa9 Use the new array_list functions in builtin_set.c
darcs-hash:20060731161719-ac50b-28a669e7a83f966dba3527a148ff0fa0813fbd6b.gz
2006-08-01 02:17:19 +10:00
axel
cccd13db92 Add long and function pointer versions of all array_list_t calls
darcs-hash:20060731161641-ac50b-1850b9c2464ce1aa7ff2f1aa74140b526a6825f2.gz
2006-08-01 02:16:41 +10:00
axel
2c8a2c9f61 Add _POSIX_C_SOURCE macro, to enable Posix mode of various headers. Should help under Solaris. Thanks to Netocrat for the suggestion.
darcs-hash:20060731153213-ac50b-14f8402a743dd67f34e3699e993cef329fdd9427.gz
2006-08-01 01:32:13 +10:00
axel
f05e1f6e48 Always check strings sent to tparm
darcs-hash:20060731004804-ac50b-ddede984cbc114b5e79745aef768f85a587d3dc6.gz
2006-07-31 10:48:04 +10:00
axel
f439c4a484 Make calls to grep Posix compliant
darcs-hash:20060731003354-ac50b-5916d6d862fe8b4f31b64840296d24615b52d175.gz
2006-07-31 10:33:54 +10:00
axel
2fba53b113 Make PATH validation only run for interactive shells to avoid infinite loop
darcs-hash:20060731003311-ac50b-da0b49830e5a9042fbe7952a63ced2c86b8978fe.gz
2006-07-31 10:33:11 +10:00
axel
8a2846ed44 Add Solaris xpg4 PATH test
darcs-hash:20060731003111-ac50b-d8945adca50bbe9e86041835ed52a88e09f65701.gz
2006-07-31 10:31:11 +10:00
axel
91b63e4989 Make sure install-sh is executable in the Makefile
darcs-hash:20060730210506-ac50b-9869e637a768aefd6ec7db33cec5f2defb29eb36.gz
2006-07-31 07:05:06 +10:00
axel
89d876d0f7 Provide fallback of killpg function
darcs-hash:20060730205941-ac50b-ddcec32cc5ab74770b743fed3d131460ee576191.gz
2006-07-31 06:59:41 +10:00
axel
e79fdcb194 Provide fallback is struct winsize is not defined
darcs-hash:20060730205544-ac50b-26f34eb04b56924baa34f560fd274cf38413b5f5.gz
2006-07-31 06:55:44 +10:00
axel
60f0533821 Include siginfo.h in all signal-using files to make Solaris happy. Thanks to Netocrat for the report and a description of the solution.
darcs-hash:20060730202659-ac50b-1840aff40ec2467242bd107676c7426cdb14f643.gz
2006-07-31 06:26:59 +10:00
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
axel
ec58ffa641 Bump version number
darcs-hash:20060531154529-ac50b-92c8377b8b3164fa280c02b4752243295c4b7c40.gz
2006-06-01 01:45:29 +10:00
axel
2c44ecb4a3 Drop debug message
darcs-hash:20060531154456-ac50b-2367291f440bff21b3029829ff7dff86be5b5ec1.gz
2006-06-01 01:44:56 +10:00
axel
2eebb6e7ed Revert addition of the seq file to repo - only seq.in should be there. Also apply earlier fix to seq.in
darcs-hash:20060531154428-ac50b-7ddeef083d3d965eb484cb11a71c1291660fee89.gz
2006-06-01 01:44:28 +10:00
axel
1a3ab8a189 Make validation code show offening parameter on perameter expansion problems
darcs-hash:20060531154147-ac50b-dd9b9a3e000352b045a4a9c3122a45a312c43f19.gz
2006-06-01 01:41:47 +10:00
axel
4722ddc373 Increase size of buffer for parser error string. Should change this to a dynamically allocated string.
darcs-hash:20060531154028-ac50b-ada120ecfe65bcf1ad1b3d1a5fad41ae9dec133c.gz
2006-06-01 01:40:28 +10:00
axel
25365dbc54 Minor change to the strings to a printf comman, since it seems to work differently under different platforms
darcs-hash:20060530091417-ac50b-4eead9f39433b54ab66dea1c336b533689d85c46.gz
2006-05-30 19:14:17 +10:00
axel
6a5f11879b Minor code simplifications in highlighting code
darcs-hash:20060530003535-ac50b-6babcc9880a018a669e123c2acdb548adb4406ce.gz
2006-05-30 10:35:35 +10:00
axel
b028e41f7f Slightly updated fusermount completions - Thanks to Sean Higgins
darcs-hash:20060529135227-ac50b-ffce282fc850a895da75f64cd8a151277f42a937.gz
2006-05-29 23:52:27 +10:00
axel
86593cd6a2 Add highlighting to a few missing escape sequences
darcs-hash:20060529134659-ac50b-48de59c1c84e4e3d3a6cf6283ec8a652986c380d.gz
2006-05-29 23:46:59 +10:00
axel
6cae5c8b0a Minor rewordings and additions to the manual
darcs-hash:20060529134607-ac50b-097cf23e8009b13afa456cf3946cc0799b0fd471.gz
2006-05-29 23:46:07 +10:00
axel
29cd62ab6e Check documentation for listing of external commands instead of relying on out of date static lists in various places
darcs-hash:20060529133239-ac50b-48392cfa1e5817ed8df452f0632658af7fe47a28.gz
2006-05-29 23:32:39 +10:00
axel
4c7e06e752 Add missing event trigger when non-universal variable is erased
darcs-hash:20060529131217-ac50b-feb2034230297d9edc120369d8f3c1cfff6acfcd.gz
2006-05-29 23:12:17 +10:00
axel
433169dca4 Avoid using the pwd command in favour of the $PWD variable, since the pwd command does not seem to work well with fuse
darcs-hash:20060529130753-ac50b-0d32fe0924dbf9e83520d26402e9daae77789419.gz
2006-05-29 23:07:53 +10:00
axel
d46dade284 Rename function expand_variable_array to tokenize_variable_array and move it from expand.c to common.c, since it is used by fish_pager, which should not depend on expand.o
darcs-hash:20060529111342-ac50b-315d7dcf04e05fa8f32e16801e6793ac4e4e022e.gz
2006-05-29 21:13:42 +10:00
axel
79b466441b Fix major memory leak in highlighting code and a minor leak in the parser
darcs-hash:20060528110630-ac50b-94a83ec6731b39ebcf864b7491ec3c372e28a135.gz
2006-05-28 21:06:30 +10:00
axel
9f14d50974 Extend manual section on highlighting colors
darcs-hash:20060528105437-ac50b-c1c703206e855e5a4b5d7cf48bc19c48e12d2833.gz
2006-05-28 20:54:37 +10:00
axel
990803009e Minor edits
darcs-hash:20060527134918-ac50b-b244916fc6649e1abb4832bdaa3fff81fcbe3937.gz
2006-05-27 23:49:18 +10:00
axel
6dfd629fc5 Update todo list
darcs-hash:20060527134859-ac50b-3890023bb4003bbf773bf68dbcb9588c6ec55600.gz
2006-05-27 23:48:59 +10:00
axel
d97f8f3fde Add missing completion for complete builtin
darcs-hash:20060527134741-ac50b-dd50e408384d48b4b859240ac4fb6ad1ea8d25a5.gz
2006-05-27 23:47:41 +10:00
axel
95ca3d1c69 Minor clarifications for documentation for the set builtin
darcs-hash:20060527134723-ac50b-8ad44bf44a8537f12b45281950fcaf85abbdd8f4.gz
2006-05-27 23:47:23 +10:00
axel
c8b04f70cf Add highlighting of a few missing escapes
darcs-hash:20060527134026-ac50b-3ff05d1fe0246d37c1be6e4a6d4492bf411808b7.gz
2006-05-27 23:40:26 +10:00
axel
bffff77d17 Add support for bold highligting
darcs-hash:20060527133930-ac50b-515d0887567c0e89fdfe10fe8310d6ebb4485974.gz
2006-05-27 23:39:30 +10:00
axel
6bdb0cde8b Add support for highligting qutes in a special color - defaults to blue
darcs-hash:20060527123516-ac50b-d6e0cf08bd9dfe8514e64004d93dc4035e73fad8.gz
2006-05-27 22:35:16 +10:00
axel
42a260f1e6 Use ahead of time validator to make sure that commands entered on the command line are valid
darcs-hash:20060527111456-ac50b-1bc070467029b851d34a1b99457415e3f0b24429.gz
2006-05-27 21:14:56 +10:00
axel
148cb68700 Add Parenthesis and braces to list of highlighted operators, and do minor code cleanup
darcs-hash:20060527005618-ac50b-272d096796b732b7d6c000c30be1a9ca1e1995a6.gz
2006-05-27 10:56:18 +10:00
axel
18c185c256 Add support for highlighting operators and escaped sequences
darcs-hash:20060526164638-ac50b-2259579e0460df0641683ce6127bb8516fca8c7e.gz
2006-05-27 02:46:38 +10:00
axel
b5b49e7a4d Make sure that getopt flags are only written down once
darcs-hash:20060526145551-ac50b-5411809433e277cd0bdebc34907ee3312a8a0263.gz
2006-05-27 00:55:51 +10:00
axel
28ea5ce732 Add missing N_.fish file to repo
darcs-hash:20060526120906-ac50b-5c903a99dfcb176c454bec2abc25360e8a7bf79a.gz
2006-05-26 22:09:06 +10:00
axel
eccba7626d Properly exit ca_mode terminal mode on exit
darcs-hash:20060526120331-ac50b-bbddd181b0784072a47e0f852012b9588c4fc3d6.gz
2006-05-26 22:03:31 +10:00
axel
79d3207d51 The fallback seq implementation was missing in the darcs repo, add it and fix a bug in it
darcs-hash:20060526114722-ac50b-4b75ac32c6490b358bb1003736fdc47198f37030.gz
2006-05-26 21:47:22 +10:00
axel
d6bf879675 Move jobs builtin to its own file
darcs-hash:20060526113811-ac50b-9c0ed1aa26cd2f247978e406bea86e8c36d73710.gz
2006-05-26 21:38:11 +10:00
axel
051f557e8f Minor code polish for the validation code
darcs-hash:20060526112525-ac50b-d15f974d7abc5ffdc61273c1642c1cb711bc23fd.gz
2006-05-26 21:25:25 +10:00
axel
17171c3277 If a help page for a builtin is showed in response to an error, make sure it fits on screen, or only print the synopsis - this patch also contains a huge number of tweaks to where and when the help pages are printed
darcs-hash:20060526112402-ac50b-88993e45f411b2f1c45b3202c393c5328f1c7429.gz
2006-05-26 21:24:02 +10:00
axel
18a59291ed Bugfix for previous patch to simplify configuration checks for ulimit builtin
darcs-hash:20060526111934-ac50b-ae9e85cd3e18994d2c56c2f6c69df6a1d93f9ea6.gz
2006-05-26 21:19:34 +10:00
axel
29e86254d0 Allow tab completion of empty command names
darcs-hash:20060521223213-ac50b-5201b7f0dfe5227f93aae6db94450e165c9a5a34.gz
2006-05-22 08:32:13 +10:00
axel
b746a803a9 Add validator check to make sure the second argument to 'for' is 'in'
darcs-hash:20060521221604-ac50b-5bc4ce217a08304f68b97b20e908ea1279fe26e9.gz
2006-05-22 08:16:04 +10:00
axel
07e14ed7a8 Rewrite small amount of code in parameter expansion to use wide character strings, not narrow
darcs-hash:20060521214601-ac50b-bb3937f5abd2780a7ecf8ab13975a0f6b622323f.gz
2006-05-22 07:46:01 +10:00
axel
df5cc6f858 Fix bugs detected by the ahead-of-time syntax checking in the complete builtin
darcs-hash:20060521192705-ac50b-b4304328fb4b9cce853055a2f231c48050a17471.gz
2006-05-22 05:27:05 +10:00
axel
409a407ca0 Use ahead-of-time syntax checker to validate input for complete builtin
darcs-hash:20060521192630-ac50b-c469f5bb3bd2afddce3ffa80adba0589d515b938.gz
2006-05-22 05:26:30 +10:00
axel
1c2cbb00bc Major update to the ahead-of-time syntax checker
darcs-hash:20060521192524-ac50b-48713f826558e66ef21046d1bb779623cc2fd97a.gz
2006-05-22 05:25:24 +10:00
axel
bbf2a3836f Simplify code for detecting which macros are defined in sys/resource.h, no configure-time tests are needed
darcs-hash:20060519151443-ac50b-c87dba2175f5bf8d652c783559c3a9992247aa01.gz
2006-05-20 01:14:43 +10:00
217 changed files with 40349 additions and 9356 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

23
INSTALL
View File

@@ -32,17 +32,22 @@ separate build directories or any other fancy configure options.
Simple install procedure
========================
If you have downloaded the darcs repository of fish, you need to run
the autoconf command first. Then use the following commands to compile
fish:
Always begin by uninstalling any previous fish versions. This is done
by running the command 'make uninstall' in the source directory of
your previous fish installation.
% ./configure
% make # Compile fish
% make install # Install fish
% echo /usr/local/bin/fish >>/etc/shells # Add fish to list of shells
Next, if you have downloaded a fresh copy of the darcs repository of
fish, you need to run the 'autoconf' command.
If you wish to use fish as your default shell, use the following
command:
Then, use following commands to compile fish:
./configure
make # Compile fish
make install # Install fish
echo /usr/local/bin/fish >>/etc/shells # Add fish to list of shells
Finally, if you wish to use fish as your default shell, use the
following command:
% chsh -s /usr/local/bin/fish

File diff suppressed because it is too large Load Diff

967
builtin.c

File diff suppressed because it is too large Load Diff

View File

@@ -57,6 +57,34 @@ enum
*/
#define BUILTIN_ERR_VARNAME_ZERO _( L"%ls: Variable name can not be the empty string\n" )
/**
Error message when second argument to for isn't 'in'
*/
#define BUILTIN_FOR_ERR_IN _( L"%ls: Second argument must be 'in'\n" )
/**
Error message for insufficient number of arguments
*/
#define BUILTIN_FOR_ERR_COUNT _( L"%ls: Expected at least two arguments, got %d\n")
#define BUILTIN_FOR_ERR_NAME _( L"%ls: '%ls' is not a valid variable name\n" )
/**
Error message when too many arguments are supplied to a builtin
*/
#define BUILTIN_ERR_TOO_MANY_ARGUMENTS _( L"%ls: Too many arguments\n" )
/**
Error message when block types mismatch in the end builtin, e.g. 'begin; end for'
*/
#define BUILTIN_END_BLOCK_MISMATCH _( L"%ls: Block mismatch: '%ls' vs. '%ls'\n" )
/**
Error message for unknown block type in the end builtin, e.g. 'begin; end beggin'
*/
#define BUILTIN_END_BLOCK_UNKNOWN _( L"%ls: Unknown block type '%ls'\n" )
#define BUILTIN_ERR_NOT_NUMBER _( L"%ls: Argument '%ls' is not a number\n" )
/**
Stringbuffer used to represent standard output
*/
@@ -126,46 +154,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.
*/
int builtin_complete(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

@@ -3,6 +3,8 @@
Functions used for implementing the commandline builtin.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
@@ -11,8 +13,6 @@ Functions used for implementing the commandline builtin.
#include <termios.h>
#include <signal.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -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"
/**
@@ -52,24 +52,23 @@ enum
}
;
static wchar_t *current_buffer=0;
static int current_cursor_pos = -1;
/**
Returns the current commandline buffer.
*/
static const wchar_t *get_buffer()
static wchar_t *get_buffer()
{
const wchar_t *buff = builtin_complete_get_temporary_buffer();
if( !buff )
buff = reader_get_buffer();
return buff;
return current_buffer;
}
/**
Returns the position of the cursor
*/
static int get_cursor_pos()
{
const wchar_t *buff = builtin_complete_get_temporary_buffer();
if( buff )
return wcslen( buff );
else
return reader_get_cursor_pos();
return current_cursor_pos;
}
@@ -195,7 +194,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;
@@ -207,6 +206,20 @@ int builtin_commandline( wchar_t **argv )
int function_mode = 0;
int tokenize = 0;
int cursor_mode = 0;
wchar_t *begin, *end;
current_buffer = (wchar_t *)builtin_complete_get_temporary_buffer();
if( current_buffer )
{
current_cursor_pos = wcslen( current_buffer );
}
else
{
current_buffer = reader_get_buffer();
current_cursor_pos = reader_get_cursor_pos();
}
if( !get_buffer() )
{
@@ -265,6 +278,18 @@ int builtin_commandline( wchar_t **argv )
L"tokenize", no_argument, 0, 'o'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
L"input", required_argument, 0, 'I'
}
,
{
L"cursor", no_argument, 0, 'C'
}
,
{
0, 0, 0, 0
}
@@ -275,7 +300,7 @@ int builtin_commandline( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"aijpctwfor",
L"aijpctwforhI:C",
long_options,
&opt_index );
if( opt == -1 )
@@ -330,6 +355,19 @@ int builtin_commandline( wchar_t **argv )
tokenize=1;
break;
case 'I':
current_buffer = woptarg;
current_cursor_pos = wcslen( woptarg );
break;
case 'C':
cursor_mode = 1;
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case L'?':
builtin_print_help( argv[0], sb_err );
return 1;
@@ -343,16 +381,13 @@ int builtin_commandline( wchar_t **argv )
/*
Check for invalid switch combinations
*/
if( buffer_part || cut_at_cursor || append_mode || tokenize )
if( buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode )
{
sb_printf(sb_err,
BUILTIN_ERR_COMBO,
argv[0] );
sb_append2(sb_err,
parser_current_line(),
L"\n",
(void *)0);
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -363,10 +398,6 @@ int builtin_commandline( wchar_t **argv )
BUILTIN_ERR_MISSING,
argv[0] );
sb_append2( sb_err,
parser_current_line(),
L"\n",
(void *)0 );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -375,7 +406,6 @@ int builtin_commandline( wchar_t **argv )
wint_t c = input_get_code( argv[i] );
if( c != -1 )
{
// fwprintf( stderr, L"Add function %ls (%d)\n", argv[i], c );
/*
input_unreadch inserts the specified keypress or
readline function at the top of the stack of unused
@@ -385,15 +415,10 @@ int builtin_commandline( wchar_t **argv )
}
else
{
// fwprintf( stderr, L"BLUR %ls %d\n", argv[i], c );
sb_append2( sb_err,
argv[0],
L": Unknown readline function '",
argv[i],
L"'\n",
parser_current_line(),
L"\n",
(void *)0 );
sb_printf( sb_err,
_(L"%ls: Unknown readline function '%ls'\n"),
argv[0],
argv[i] );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -405,7 +430,7 @@ int builtin_commandline( wchar_t **argv )
/*
Check for invalid switch combinations
*/
if( argc-woptind > 1 )
if( cursor_mode && (argc-woptind > 1) )
{
sb_append2( sb_err,
@@ -416,9 +441,19 @@ int builtin_commandline( wchar_t **argv )
return 1;
}
if( (buffer_part || tokenize || cut_at_cursor) && cursor_mode )
{
sb_printf( sb_err,
BUILTIN_ERR_COMBO,
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
}
if( (tokenize || cut_at_cursor) && (argc-woptind) )
{
sb_printf( sb_err,
BUILTIN_ERR_COMBO2,
argv[0],
@@ -452,9 +487,39 @@ int builtin_commandline( wchar_t **argv )
{
buffer_part = STRING_MODE;
}
if( cursor_mode )
{
if( argc-woptind )
{
wchar_t *endptr;
int new_pos;
errno = 0;
new_pos = wcstol( argv[woptind], &endptr, 10 );
if( *endptr || errno )
{
sb_printf( sb_err,
BUILTIN_ERR_NOT_NUMBER,
argv[0],
argv[woptind] );
builtin_print_help( argv[0], sb_err );
}
current_buffer = reader_get_buffer();
new_pos = maxi( 0, mini( new_pos, wcslen( current_buffer ) ) );
reader_set_buffer( current_buffer, new_pos );
return 0;
}
else
{
sb_printf( sb_out, L"%d\n", reader_get_cursor_pos() );
return 0;
}
const wchar_t *begin, *end;
}
switch( buffer_part )
{
case STRING_MODE:
@@ -505,7 +570,28 @@ int builtin_commandline( wchar_t **argv )
case 1:
{
replace_part( begin, end, argv[woptind], append_mode );
break;
break;
}
default:
{
string_buffer_t sb;
int i;
sb_init( &sb );
sb_append( &sb, argv[woptind] );
for( i=woptind+1; i<argc; i++ )
{
sb_append( &sb, L"\n" );
sb_append( &sb, argv[i] );
}
replace_part( begin, end, (wchar_t *)sb.buff, append_mode );
sb_destroy( &sb );
break;
}
}

View File

@@ -3,6 +3,8 @@
Functions used for implementing the complete builtin.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
@@ -11,8 +13,6 @@ Functions used for implementing the complete builtin.
#include <termios.h>
#include <signal.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -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;
@@ -338,7 +364,11 @@ int builtin_complete( wchar_t **argv )
}
,
{
L"do-complete", required_argument, 0, 'C'
L"do-complete", optional_argument, 0, 'C'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
@@ -351,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:",
L"a:c:p:s:l:o:d:frxeun:C::h",
long_options,
&opt_index );
if( opt == -1 )
@@ -369,7 +399,7 @@ int builtin_complete( wchar_t **argv )
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
res = 1;
@@ -388,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;
@@ -431,10 +469,14 @@ int builtin_complete( wchar_t **argv )
do_complete = woptarg?woptarg:reader_get_buffer();
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case '?':
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
res = 1;
break;
@@ -443,6 +485,42 @@ int builtin_complete( wchar_t **argv )
}
if( !res )
{
if( condition && wcslen( condition ) )
{
if( parser_test( condition, 0, 0, 0 ) )
{
sb_printf( sb_err,
L"%ls: Condition '%ls' contained a syntax error\n",
argv[0],
condition );
parser_test( condition, 0, sb_err, argv[0] );
res = 1;
}
}
}
if( !res )
{
if( comp && wcslen( comp ) )
{
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, sb_err, argv[0] );
res = 1;
}
}
}
if( !res )
{
if( do_complete )
@@ -470,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--;
}
@@ -485,7 +563,7 @@ int builtin_complete( wchar_t **argv )
argv[0] );
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
res = 1;
}
@@ -522,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

@@ -5,33 +5,41 @@
various help files in the doc_src directory.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <string.h>
#include <wchar.h>
#include <sys/types.h>
#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 );

351
builtin_jobs.c Normal file
View File

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

View File

@@ -3,6 +3,8 @@
Functions used for implementing the set builtin.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
@@ -11,8 +13,6 @@ Functions used for implementing the set builtin.
#include <termios.h>
#include <signal.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -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
@@ -81,7 +81,7 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
show_perror = 1;
}
if( !( S_IFDIR & buff.st_mode ) )
if( !( S_ISDIR(buff.st_mode) ) )
{
error = 1;
@@ -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,15 +233,19 @@ static int parse_index( array_list_t *indexes,
{
wchar_t *end;
long l_ind = wcstol(src, &end, 10);
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) l_ind;
al_push(indexes, ind);
al_push_long(indexes, l_ind);
src = end;
count++;
while (iswspace(*src)) src++;
@@ -248,8 +261,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,
@@ -260,29 +272,38 @@ static int update_values( array_list_t *list,
/* Replace values where needed */
for( i = 0; i < al_get_count(indexes); i++ )
{
int ind = *(int *) al_get(indexes, i) - 1;
/*
The '- 1' below is because the indices in fish are
one-based, but the array_lsit_t uses zero-based indices
*/
long ind = al_get_long(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;
}
/**
Return 1 if an array list of int* pointers contains the specified
Return 1 if an array list of longs contains the specified
value, 0 otherwise
*/
static int al_contains_int( array_list_t *list,
int val)
static int al_contains_long( array_list_t *list,
long val)
{
int i;
for (i = 0; i < al_get_count(list); i++)
{
int *current = (int *) al_get(list, i);
if( current != 0 && *current == val )
long current = al_get_long(list, i);
if( current != 0 && current == val )
{
return 1;
}
@@ -297,20 +318,20 @@ static int al_contains_int( array_list_t *list,
*/
static void erase_values(array_list_t *list, array_list_t *indexes)
{
int i;
long i;
array_list_t result;
al_init(&result);
for (i = 0; i < al_get_count(list); i++)
{
if (!al_contains_int(indexes, i + 1))
if (!al_contains_long(indexes, i + 1))
{
al_push(&result, al_get(list, i));
}
else
{
free((void *) al_get(list, i));
free( (void *)al_get(list, i));
}
}
@@ -337,7 +358,7 @@ static void print_variables(int include_values, int esc, int scope)
for( i = 0; i < al_get_count(&names); i++ )
{
wchar_t *key = (wchar_t *)al_get( &names, i );
wchar_t *e_key = esc ? escape(key, 1) : wcsdup(key);
wchar_t *e_key = esc ? escape(key, 0) : wcsdup(key);
sb_append(sb_out, e_key);
@@ -345,9 +366,32 @@ static void print_variables(int include_values, int esc, int scope)
{
wchar_t *value = env_get(key);
wchar_t *e_value;
e_value = esc ? expand_escape_variable(value) : wcsdup(value);
sb_append2(sb_out, L" ", e_value, (void *)0);
free(e_value);
if( value )
{
int shorten = 0;
if( wcslen( value ) > 64 )
{
shorten = 1;
value = wcsndup( value, 60 );
if( !value )
{
DIE_MEM();
}
}
e_value = esc ? expand_escape_variable(value) : wcsdup(value);
sb_append2(sb_out, L" ", e_value, (void *)0);
free(e_value);
if( shorten )
{
sb_append(sb_out, L"\u2026");
free( value );
}
}
}
sb_append(sb_out, L"\n");
@@ -362,7 +406,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 )
{
/**
@@ -373,35 +417,47 @@ int builtin_set( wchar_t **argv )
{
{
L"export", no_argument, 0, 'x'
},
}
,
{
L"global", no_argument, 0, 'g'
},
}
,
{
L"local", no_argument, 0, 'l'
},
}
,
{
L"erase", no_argument, 0, 'e'
},
}
,
{
L"names", no_argument, 0, 'n'
} ,
}
,
{
L"unexport", no_argument, 0, 'u'
} ,
}
,
{
L"universal", no_argument, 0, 'U'
} ,
}
,
{
L"query", no_argument, 0, 'q'
} ,
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
}
;
const wchar_t *short_options = L"+xglenuUq";
const wchar_t *short_options = L"+xglenuUqh";
int argc = builtin_count_args(argv);
@@ -422,6 +478,8 @@ int builtin_set( wchar_t **argv )
int slice=0;
int i;
wchar_t *bad_char;
/* Parse options to obtain the requested operation and the modifiers */
woptind = 0;
@@ -438,32 +496,47 @@ int builtin_set( wchar_t **argv )
{
case 0:
break;
case 'e':
erase = 1;
break;
case 'n':
list = 1;
break;
case 'x':
export = 1;
break;
case 'l':
local = 1;
break;
case 'g':
global = 1;
break;
case 'u':
unexport = 1;
break;
case 'U':
universal = 1;
break;
case 'q':
query = 1;
break;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
default:
break;
}
@@ -485,7 +558,7 @@ int builtin_set( wchar_t **argv )
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -498,7 +571,7 @@ int builtin_set( wchar_t **argv )
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -511,7 +584,7 @@ int builtin_set( wchar_t **argv )
BUILTIN_ERR_GLOCAL,
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -524,7 +597,7 @@ int builtin_set( wchar_t **argv )
BUILTIN_ERR_EXPUNEXP,
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
return 1;
}
@@ -536,13 +609,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++;
}
@@ -551,6 +624,13 @@ int builtin_set( wchar_t **argv )
return retcode;
}
if( list )
{
/* Maybe we should issue an error if there are any other arguments? */
print_variables(0, 0, scope);
return 0;
}
if( woptind == argc )
{
/*
@@ -564,7 +644,7 @@ int builtin_set( wchar_t **argv )
argv[0],
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
builtin_print_help( argv[0], sb_err );
retcode = 1;
}
else
@@ -575,16 +655,9 @@ int builtin_set( wchar_t **argv )
return retcode;
}
if( list )
{
/* Maybe we should issue an error if there are any other arguments? */
print_variables(0, 0, scope);
return 0;
}
if( !(dest = wcsdup(argv[woptind])))
{
die_mem();
DIE_MEM();
}
if( wcschr( dest, L'[' ) )
@@ -597,9 +670,25 @@ 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( (bad_char = wcsvarname( dest ) ) )
{
sb_printf( sb_err, BUILTIN_ERR_VARCHAR, argv[0], *bad_char );
builtin_print_help( argv[0], sb_err );
free( dest );
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
@@ -615,14 +704,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;
}
@@ -635,6 +729,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;
}
@@ -652,10 +747,6 @@ int builtin_set( wchar_t **argv )
Slice indexes have been calculated, do the actual work
*/
array_list_t result;
al_init(&result);
expand_variable_array( env_get(dest), &result );
if( erase )
{
erase_values(&result, &indexes);
@@ -671,9 +762,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,
@@ -682,11 +778,11 @@ 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_destroy(&indexes);
al_destroy(&values);
@@ -706,11 +802,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
@@ -63,13 +63,13 @@ const static struct resource_t resource_arr[] =
RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024
}
,
#if HAVE_RLIMIT_MEMLOCK
#ifdef RLIMIT_MEMLOCK
{
RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024
}
,
#endif
#if HAVE_RLIMIT_RSS
#ifdef RLIMIT_RSS
{
RLIMIT_RSS, L"Maximum resident set size", L'm', 1024
}
@@ -87,13 +87,13 @@ const static struct resource_t resource_arr[] =
RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1
}
,
#if HAVE_RLIMIT_NPROC
#ifdef RLIMIT_NPROC
{
RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1
}
,
#endif
#if HAVE_RLIMIT_AS
#ifdef RLIMIT_AS
{
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
}
@@ -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;
@@ -326,6 +330,10 @@ int builtin_ulimit( wchar_t ** argv )
L"virtual-memory-size", no_argument, 0, 'v'
}
,
{
L"help", no_argument, 0, 'h'
}
,
{
0, 0, 0, 0
}
@@ -337,7 +345,7 @@ int builtin_ulimit( wchar_t ** argv )
int opt = wgetopt_long( argc,
argv,
L"aHScdflmnptuv",
L"aHScdflmnptuvh",
long_options,
&opt_index );
if( opt == -1 )
@@ -379,13 +387,13 @@ int builtin_ulimit( wchar_t ** argv )
case L'f':
what=RLIMIT_FSIZE;
break;
#if HAVE_RLIMIT_MEMLOCK
#ifdef RLIMIT_MEMLOCK
case L'l':
what=RLIMIT_MEMLOCK;
break;
#endif
#if HAVE_RLIMIT_RSS
#ifdef RLIMIT_RSS
case L'm':
what=RLIMIT_RSS;
break;
@@ -403,18 +411,22 @@ int builtin_ulimit( wchar_t ** argv )
what=RLIMIT_CPU;
break;
#if HAVE_RLIMIT_NPROC
#ifdef RLIMIT_NPROC
case L'u':
what=RLIMIT_NPROC;
break;
#endif
#if HAVE_RLIMIT_AS
#ifdef RLIMIT_AS
case L'v':
what=RLIMIT_AS;
break;
#endif
case L'h':
builtin_print_help( argv[0], sb_out );
return 0;
case L'?':
builtin_print_help( argv[0], sb_err );
return 1;

575
common.c
View File

@@ -7,6 +7,16 @@ parts of fish.
#include "config.h"
#include <unistd.h>
#ifdef HAVE_STROPTS_H
#include <stropts.h>
#endif
#ifdef HAVE_SIGINFO_H
#include <siginfo.h>
#endif
#include <stdlib.h>
#include <termios.h>
#include <wchar.h>
@@ -14,7 +24,15 @@ parts of fish.
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#ifdef HAVE_SYS_TERMIOS_H
#include <sys/termios.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include <sys/stat.h>
#include <unistd.h>
#include <wctype.h>
@@ -61,31 +79,19 @@ 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
*/
#define LOCKPOLLINTERVAL 10
/**
Highest legal ascii value
*/
#define ASCII_MAX 127u
/**
Highest legal 16-bit unicode value
*/
#define UCS2_MAX 0xffffu
/**
Highest legal byte value
*/
#define BYTE_MAX 0xffu
struct termios shell_modes;
int error_max=1;
wchar_t ellipsis_char;
char *profile=0;
@@ -104,27 +110,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++ )
{
@@ -141,12 +133,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 */
@@ -156,7 +142,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
{
@@ -228,7 +214,7 @@ wchar_t *str2wcs( const char *in )
if( !out )
{
die_mem();
DIE_MEM();
}
return str2wcs_internal( in, out );
@@ -240,8 +226,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] )
@@ -252,12 +243,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:
{
@@ -285,7 +276,7 @@ char *wcs2str( const wchar_t *in )
if( !out )
{
die_mem();
DIE_MEM();
}
return wcs2str_internal( in, out );
@@ -297,11 +288,18 @@ 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] )
{
if( ( in[in_pos] >= ENCODE_DIRECT_BASE) &&
if( in[in_pos] == INTERNAL_SEPARATOR )
{
}
else if( ( in[in_pos] >= ENCODE_DIRECT_BASE) &&
( in[in_pos] < ENCODE_DIRECT_BASE+256) )
{
out[out_pos++] = in[in_pos]- ENCODE_DIRECT_BASE;
@@ -312,7 +310,7 @@ char *wcs2str_internal( const wchar_t *in, char *out )
if( res == (size_t)(-1) )
{
debug( 1, L"Wide character has no narrow representation" );
debug( 1, L"Wide character %d has no narrow representation", in[in_pos] );
memset( &state, 0, sizeof(state) );
}
else
@@ -337,7 +335,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++ )
@@ -351,7 +349,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, ... )
@@ -372,7 +370,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 );
@@ -398,7 +396,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++ )
@@ -410,19 +408,30 @@ wchar_t **strv2wcsv( const char **in )
}
wchar_t *wcsvarname( wchar_t *str )
wchar_t *wcsvarname( const wchar_t *str )
{
while( *str )
{
if( (!iswalnum(*str)) && (*str != L'_' ) )
{
return str;
return (wchar_t *)str;
}
str++;
}
return 0;
}
wchar_t *wcsfuncname( const wchar_t *str )
{
return wcschr( str, L'/' );
}
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.
@@ -443,26 +452,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;
}
}
}
@@ -490,8 +501,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 );
@@ -506,11 +516,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 )
@@ -539,32 +545,23 @@ 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;
sb_init( &sb );
sb_init( &sb2 );
va_start( va, msg );
sb_printf( &sb, L"%ls: ", program_name );
va_start( va, msg );
sb_vprintf( &sb, msg, va );
va_end( va );
@@ -582,6 +579,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;
@@ -596,7 +596,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
*/
while( *pos && ( !wcschr( L" \n\r\t", *pos ) ) )
{
/*
Check is token is wider than one line.
If so we mark it as an overflow and break the token.
@@ -621,7 +621,7 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
else if( overflow )
{
/*
In case of overflow, we print a newline, except if we alreade are at position 0
In case of overflow, we print a newline, except if we already are at position 0
*/
wchar_t *token = wcsndup( start, pos-start );
if( line_width != 0 )
@@ -645,12 +645,15 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff )
free( token );
line_width += (line_width!=0?1:0) + tok_width;
}
/*
Break on end of string
*/
if( !*pos )
{
break;
}
start=pos;
}
}
@@ -664,10 +667,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 )
{
@@ -691,74 +704,79 @@ 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'~':
{
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++;
@@ -772,13 +790,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;
@@ -797,46 +821,22 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
{
switch( in[++in_pos] )
{
/*
A null character after a backslash is an
error, return null
*/
case L'\0':
{
free(in);
return 0;
}
case L'n':
{
in[out_pos]=L'\n';
break;
}
/*
Numeric escape sequences. No prefix means
octal escape, otherwise hexadecimal.
*/
case L'r':
{
in[out_pos]=L'\r';
break;
}
case L't':
{
in[out_pos]=L'\t';
break;
}
case L'b':
{
in[out_pos]=L'\b';
break;
}
case L'e':
{
in[out_pos]=L'\e';
break;
}
case L'u':
case L'U':
case L'x':
case L'X':
case L'0':
case L'1':
case L'2':
@@ -845,6 +845,10 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
case L'5':
case L'6':
case L'7':
case L'u':
case L'U':
case L'x':
case L'X':
{
int i;
long long res=0;
@@ -917,8 +921,107 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
break;
}
/*
\a means bell (alert)
*/
case L'a':
{
in[out_pos]=L'\a';
break;
}
/*
\b means backspace
*/
case L'b':
{
in[out_pos]=L'\b';
break;
}
/*
\cX means control sequence X
*/
case L'c':
{
in_pos++;
if( in[in_pos] >= L'a' &&
in[in_pos] <= (L'a'+32) )
{
in[out_pos]=in[in_pos]-L'a'+1;
}
else if( in[in_pos] >= L'A' &&
in[in_pos] <= (L'A'+32) )
{
in[out_pos]=in[in_pos]-L'A'+1;
}
else
{
free(in);
return 0;
}
break;
}
/*
\e means escape
*/
case L'e':
{
in[out_pos]=L'\x1b';
break;
}
/*
\f means form feed
*/
case L'f':
{
in[out_pos]=L'\f';
break;
}
/*
\n means newline
*/
case L'n':
{
in[out_pos]=L'\n';
break;
}
/*
\r means carriage return
*/
case L'r':
{
in[out_pos]=L'\r';
break;
}
/*
\t means tab
*/
case L't':
{
in[out_pos]=L'\t';
break;
}
/*
\v means vetrical tab
*/
case L'v':
{
in[out_pos]=L'\v';
break;
}
default:
{
if( unescape_special )
in[out_pos++] = INTERNAL_SEPARATOR;
in[out_pos]=in[in_pos];
break;
}
@@ -926,7 +1029,8 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
}
else
{
switch( in[in_pos]){
switch( in[in_pos])
{
case L'~':
{
if( unescape_special && (in_pos == 0) )
@@ -1042,14 +1146,16 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
case L'\'':
{
mode = 1;
in[out_pos] = INTERNAL_SEPARATOR;
if( unescape_special )
in[out_pos] = INTERNAL_SEPARATOR;
break;
}
case L'\"':
{
mode = 2;
in[out_pos] = INTERNAL_SEPARATOR;
if( unescape_special )
in[out_pos] = INTERNAL_SEPARATOR;
break;
}
@@ -1074,6 +1180,7 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
{
case '\\':
case L'\'':
case L'\n':
{
in[out_pos]=in[in_pos];
break;
@@ -1095,7 +1202,8 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
}
if( c == L'\'' )
{
in[out_pos] = INTERNAL_SEPARATOR;
if( unescape_special )
in[out_pos] = INTERNAL_SEPARATOR;
mode = 0;
}
else
@@ -1116,7 +1224,8 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
case '"':
{
mode = 0;
in[out_pos] = INTERNAL_SEPARATOR;
if( unescape_special )
in[out_pos] = INTERNAL_SEPARATOR;
break;
}
@@ -1133,6 +1242,7 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
case '\\':
case L'$':
case '"':
case '\n':
{
in[out_pos]=in[in_pos];
break;
@@ -1286,13 +1396,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;
}
@@ -1319,6 +1429,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 )
{
@@ -1401,10 +1514,15 @@ int acquire_lock_file( const char *lockfile, const int timeout, int force )
void common_handle_winch( int signal )
{
#ifdef HAVE_WINSIZE
if (ioctl(1,TIOCGWINSZ,&termsize)!=0)
{
return;
}
#else
termsize.ws_col = 80;
termsize.ws_row = 24;
#endif
}
int common_get_width()
@@ -1418,3 +1536,68 @@ int common_get_height()
return termsize.ws_row;
}
void tokenize_variable_array( const wchar_t *val, array_list_t *out )
{
if( val )
{
wchar_t *cpy = wcsdup( val );
wchar_t *pos, *start;
if( !cpy )
{
DIE_MEM();
}
for( start=pos=cpy; *pos; pos++ )
{
if( *pos == ARRAY_SEP )
{
*pos=0;
al_push( out, start==cpy?cpy:wcsdup(start) );
start=pos+1;
}
}
al_push( out, start==cpy?cpy:wcsdup(start) );
}
}
int create_directory( wchar_t *d )
{
int ok = 0;
struct stat buf;
int stat_res = 0;
while( (stat_res = wstat(d, &buf ) ) != 0 )
{
if( errno != EAGAIN )
break;
}
if( stat_res == 0 )
{
if( S_ISDIR( buf.st_mode ) )
{
ok = 1;
}
}
else
{
if( errno == ENOENT )
{
wchar_t *dir = wcsdup( d );
dir = wdirname( dir );
if( !create_directory( dir ) )
{
if( !wmkdir( d, 0700 ) )
{
ok = 1;
}
}
free(dir);
}
}
return ok?0:-1;
}

186
common.h
View File

@@ -20,22 +20,26 @@
*/
#define MAX_UTF8_BYTES 6
/**
Color code for set_color. Does not update the color.
*/
#define FISH_COLOR_IGNORE -1
/**
Color code for set_color. Sets the default color.
*/
#define FISH_COLOR_RESET -2
/**
This is in the unicode private use area.
*/
#define ENCODE_DIRECT_BASE 0xf100
/**
Highest legal ascii value
*/
#define ASCII_MAX 127u
/**
Highest legal 16-bit unicode value
*/
#define UCS2_MAX 0xffffu
/**
Highest legal byte value
*/
#define BYTE_MAX 0xffu
/**
Save the shell mode on startup so we can restore them on exit
*/
@@ -48,12 +52,8 @@ 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
The verbosity level of fish. If a call to debug has a severity
level higher than \c debug_level, it will not be printed.
*/
extern int debug_level;
@@ -68,6 +68,75 @@ 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 return value 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); \
}
/**
Cause fish to crash. This should only be used for debugging. If
this function is ever called in shipped code, this is a bug.
*/
#define CRASH() \
{ \
int *n = 0; \
*n = 1; \
}
/**
Check if signals are blocked. If so, print an error message and
return from the function performing this check.
*/
#define CHECK_BLOCK( retval ) \
if( signal_is_blocked() ) \
{ \
debug( 0, \
L"function %s called while blocking signals. " \
L"This is a bug. " \
L"If you can reproduce it, please send a bug report to %s.", \
__func__, \
PACKAGE_BUGREPORT ); \
return retval; \
}
/**
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
@@ -91,24 +160,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 );
/**
@@ -132,7 +224,7 @@ wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b );
Returns a newly allocated concatenation of the specified wide
character strings. The last argument must be a null pointer.
*/
wchar_t *wcsdupcat2( const wchar_t *a, ... );
__sentinel wchar_t *wcsdupcat2( const wchar_t *a, ... );
/**
Test if the given string is a valid variable name
@@ -145,7 +237,24 @@ wchar_t *wcsdupcat2( const wchar_t *a, ... );
\return null if this is a valid name, and a pointer to the first invalid character otherwise
*/
wchar_t *wcsvarname( wchar_t *str );
wchar_t *wcsvarname( const wchar_t *str );
/**
Test if the given string is a valid function name.
\return null if this is a valid name, and a pointer to the first invalid character otherwise
*/
wchar_t *wcsfuncname( const 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 );
/**
@@ -160,7 +269,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
@@ -187,7 +296,7 @@ const wchar_t *wsetlocale( int category, const wchar_t *locale );
\return zero is needle is not found, of if needle is null, non-zero otherwise
*/
int contains_str( const wchar_t *needle, ... );
__sentinel int contains_str( const wchar_t *needle, ... );
/**
Call read while blocking the SIGCHLD signal. Should only be called
@@ -195,20 +304,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
@@ -292,6 +387,23 @@ void common_handle_winch( int signal );
*/
void write_screen( const wchar_t *msg, string_buffer_t *buff );
/**
Tokenize the specified string into the specified array_list_t.
Each new element is allocated using malloc and must be freed by the
caller.
\param val the input string. The contents of this string is not changed.
\param out the list in which to place the elements.
*/
void tokenize_variable_array( const wchar_t *val, array_list_t *out );
/**
Make sure the specified direcotry exists. If no, try to create it.
\return 0 if the directory exists, -1 otherwise.
*/
int create_directory( wchar_t *d );
#endif

File diff suppressed because it is too large Load Diff

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,42 +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();
/**
Add a completion.

View File

@@ -1,7 +1,25 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(fish,1.21.7,fish-users@lists.sf.net)
#
# This file is the main build configuration file for fish. It is used
# to determine your systems capabilities, and tries to adapt fish to
# take maximum advantage of the services your system offers.
#
# Process this file using the 'autoconf' command to produce a working
# configure script, which should in turn be executed in order to
# configure the build process.
#
AC_INIT(fish,1.22.1,fish-users@lists.sf.net)
#
# If needed, run autoconf to regenerate the configure file
#
# This makes sure that after running autoconf once to create the first
# version of configure, we never again need to worry about manually
# running autoconf to handle an updates configure.ac.
#
AC_MSG_CHECKING([if autoconf needs to be run])
if test configure -ot configure.ac; then
AC_MSG_RESULT([yes])
@@ -11,38 +29,55 @@ if test configure -ot configure.ac; then
AC_MSG_NOTICE([running autoconf])
if autoconf; then
./configure "$@"
exit
fi
exit
exit 1
else
AC_MSG_ERROR( [cannot find the autoconf program in your path.
AC_MSG_ERROR(
[cannot find the autoconf program in your path.
This program needs to be run whenever the configure.ac file is modified.
Please install it and try again.])
Please install it and try again.]
)
fi
else
AC_MSG_RESULT([no])
fi
#
# If needed, run autoheader to regenerate config.h.in
#
# This makes sure we never ever have to run autoheader manually. It
# will be run whenever needed automatically.
#
AC_MSG_CHECKING([if autoheader needs to be run])
if test ! -f ./config.h.in -o config.h.in -ot configure.ac; then
AC_MSG_RESULT([yes])
if which autoheader >/dev/null; then
AC_MSG_NOTICE([running autoheader])
autoheader
autoheader || exit 1
else
AC_MSG_ERROR( [cannot find the autoheader program in your path.
AC_MSG_ERROR(
[cannot find the autoheader program in your path.
This program needs to be run whenever the configure.ac file is modified.
Please install it and try again.])
Please install it and try again.]
)
fi
else
AC_MSG_RESULT([no])
fi
#
# Detect directories which may contain additional headers, libraries
# and commands. This needs to be done early - before Autoconf starts
# to mess with CFLAGS and all the other environemnt variables.
#
# This mostly helps OS X users, since fink usually installs out of
# tree and doesn't update CFLAGS.
#
for i in /usr/pkg /sw /opt /opt/local; do
AC_MSG_CHECKING([for $i/include include directory])
@@ -74,33 +109,80 @@ done
AC_SUBST( optbindirs, $optbindirs )
#
# Tell autoconf to create config.h header
#
AC_CONFIG_HEADERS(config.h)
#
# This adds markup to the code that results in a few extra compile
# time checks on recent GCC versions. It helps stop a few common bugs.
#
AH_BOTTOM([#if __GNUC__ >= 3
#define __warn_unused __attribute__ ((warn_unused_result))
#define __sentinel __attribute__ ((sentinel))
#else
#define __warn_unused
#define __sentinel
#endif])
#
# Set up various programs needed for install
#
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
# implementation is installed.
#
AC_CHECK_PROG( SEQ_FALLBACK, seq, [ ], [seq])
if test "$SEQ_FALLBACK"; then
#
# We already have seq. Check if the seq version is installed by an
# earlier fish version. If it is, we'll replace it.
#
file=`which seq`
if test -f "$file"; then
AC_MSG_CHECKING([if seq comes from a previous fish version])
shebang=`grep "\(^#!/.*/fish\|^#!/usr/bin/env fish\)" $file`
if test "$shebang"; then
AC_SUBST( SEQ_FALLBACK, seq )
AC_MSG_RESULT(yes, replace it)
else
AC_MSG_RESULT(no, keep it)
fi
fi
fi
#
# Optionally drop xsel command
AC_ARG_WITH( xsel,
AC_HELP_STRING([--without-xsel],
[do not build the xsel program needed for X clipboard integration]),
[xsel=$withval],
[xsel=with_xsel] )
#
AC_ARG_WITH(
xsel,
AC_HELP_STRING(
[--without-xsel],
[do not build the xsel program needed for X clipboard integration]
),
[xsel=$withval],
[xsel=with_xsel]
)
if [[ "$xsel" = "with_xsel" ]]; then
AC_SUBST( XSEL,[xsel-0.9.6/xsel])
@@ -112,31 +194,46 @@ else
AC_SUBST( XSEL_MAN_PATH,[ ])
fi
#
# Test if the compiler accepts the -std=c99 flag. If so, using it
# increases the odds of correct compilation, since we want to use the
# *wprintf functions, which where defined in C99.
# *wprintf functions, which where defined in C99.
#
XCFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -std=c99"
XCPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS -std=c99"
AC_MSG_CHECKING(if -std=c99 works)
AC_CACHE_VAL(local_cv_has__std_c99,[
AC_TRY_RUN([
#include <stdlib.h>
#include <stdio.h>
int main() {
return 0;
}],
local_cv_has__std_c99=yes,
local_cv_has__std_c99=no,
)])
AC_CACHE_VAL(
local_cv_has__std_c99,
[
AC_TRY_RUN(
[
#include <stdlib.h>
#include <stdio.h>
int main()
{
return 0;
}
],
local_cv_has__std_c99=yes,
local_cv_has__std_c99=no,
)
]
)
AC_MSG_RESULT($local_cv_has__std_c99)
case x$local_cv_has__std_c99 in
xno) CFLAGS="$XCFLAGS" ;;
xno)
CFLAGS="$XCFLAGS"
CPPFLAGS="$XCPPFLAGS" ;;
esac
#
# If we are using gcc, set some flags that increase the odds of the
# compiler producing a working binary...
@@ -146,7 +243,7 @@ if test "$CC" = gcc; then
#
# -fno-optimize-sibling-calls seems to work around a bug where
# sending a SIGWINCH to fish on NetBSD causes fish to exit when
# sending a SIGWINCH to fish on NetBSD 3.0 causes fish to exit when
# compiled with GCC 3.3.3. This is probably either a compiler bug
# or a libc bug, but adding this flag seems to fix things for
# now. Long term, the real problem should be tracked down and
@@ -165,6 +262,7 @@ if test "$CC" = gcc; then
fi
#
# If we are compiling against glibc, set some flags to work around
# some rather stupid attempts to hide prototypes for *wprintf
@@ -173,16 +271,24 @@ fi
AC_MSG_CHECKING([if we are compiling against glibc])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([
#include <stdlib.h>
#ifdef __GLIBC__
#define STATUS 0
#else
#define STATUS 1
#endif],
[return STATUS;])],
[
AC_LANG_PROGRAM(
[
#include <stdlib.h>
#ifdef __GLIBC__
#define STATUS 0
#else
#define STATUS 1
#endif
],
[
return STATUS;
]
)
],
[glibc=yes],
[glibc=no] )
[glibc=no]
)
if test "$glibc" = yes; then
AC_MSG_RESULT(yes)
@@ -194,12 +300,13 @@ if test "$glibc" = yes; then
# fallback.h, in order to keep fish working on non-gnu platforms.
#
CFLAGS="$CFLAGS -D _GNU_SOURCE -D _ISOC99_SOURCE"
CFLAGS="$CFLAGS -D_GNU_SOURCE=1 -D_ISO99_SOURCE=1"
else
AC_MSG_RESULT(no)
fi
#
# Test cpu for special handling of ppc
#
# This is used to skip use of tputs on ppc systems, since it seemed to
@@ -209,6 +316,7 @@ fi
# hardware available to narrow this problem down, and in practice, it
# seems that tputs is never really needed.
#
AC_CANONICAL_TARGET
if test $target_cpu = powerpc; then
@@ -216,187 +324,451 @@ if test $target_cpu = powerpc; then
fi
#
# Solaris-specific flags go here
#
AC_MSG_CHECKING([if we are under Solaris])
case $target_os in
solaris*)
AC_DEFINE( __EXTENSIONS__, 1, [Macro to enable additional prototypes under Solaris])
AC_MSG_RESULT(yes)
;;
*)
AC_MSG_RESULT(no)
;;
esac
#
# BSD-specific flags go here
#
AC_MSG_CHECKING([if we are under BSD])
case $target_os in
*bsd*)
AC_DEFINE( __BSD_VISIBLE, 1, [Macro to enable additional prototypes under BSD])
AC_DEFINE( _NETBSD_SOURCE, 1, [Macro to enable additional prototypes under BSD])
AC_MSG_RESULT(yes)
;;
*)
AC_MSG_RESULT(no)
;;
esac
#
# Set up PREFIX and related preprocessor symbols. Fish needs to know
# where it will be installed. One of the reasons for this is so that
# 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
# installed
#
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.
#
AC_CHECK_FILES([/proc/self/stat])
#
# This is ued to tell the wgetopt library to translate strings. This
# way wgetopt can be dropped into any project without requiring i18n.
#
AC_DEFINE([HAVE_TRANSLATE_H], [1],
[Define to 1 if the wgettext function should be used for translating strings.])
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] ) )
#
# Check presense of various libraries
#
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])] )
AC_SEARCH_LIBS( iconv_open, iconv, , [AC_MSG_ERROR([Could not find an iconv 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_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 presense of various header files
#
# Check for presense of various functions
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp gettext fwprintf )
AC_CHECK_FUNCS( futimes wcwidth wcswidth getopt_long wcstok fputwc fgetwc )
AC_CHECK_FUNCS( wcstol dcgettext wcslcat wcslcpy )
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h term.h ncurses/term.h libintl.h ncurses.h curses.h stropts.h siginfo.h sys/select.h sys/ioctl.h sys/termios.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])
]
)
#
# On some platforms (Solaris 10) adding -std=c99 in turn requires that
# _POSIX_C_SOURCE be defined to 200112L otherwise several
# POSIX-specific, non-ISO-C99 types/prototypes are made unavailable
# e.g. siginfo_t. Defining _XOPEN_SOURCE to 600 is compatible with
# the _POSIX_C_SOURCE value and provides a little assurance that
# extension functions' prototypes are available, e.g. killpg().
#
# Some other platforms (OS X), will remove types/prototypes/macros
# e.g. SIGWINCH if either _POSIX_C_SOURCE or _XOPEN_SOURCE is defined.
#
# This test adds these macros only if they enable a program that uses
# both Posix and non-standard features to compile, and that program
# does not compile without these macros.
#
# We try to make everyone happy.
#
# The ordering of the various autoconf tests is very critical as well:
#
# * This test needs to be run _after_ header detection tests, so that
# the proper headers are included.
#
# * This test needs to be run _before_ testing for the presense of any
# prototypes or other language functinality.
#
# * This test should be (but does not need to be) run after the
# conditional definition of __EXTENSIONS__, to avoid redundant tests.
#
XCFLAGS="$CFLAGS"
echo Checking how to use -D_XOPEN_SOURCE=600 and -D_POSIX_C_SOURCE=200112L...
local_found_posix_switch=no
for i in "" "-D_POSIX_C_SOURCE=200112L" "-D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=200112L"; do
AC_MSG_CHECKING( if switches \"$i\" works)
CFLAGS="$XCFLAGS $i"
#
# Try to run this program, which should test various extensions
# and Posix functionality. If this program works, then everything
# should work. Hopefully.
#
AC_TRY_LINK(
[
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
/* POSIX, C89 and C99: POSIX extends this header.
* For: kill(), killpg(), siginfo_t, sigset_t,
* struct sigaction, sigemptyset(), sigaction(),
* SIGIO and SIGWINCH. */
#include <signal.h>
#ifdef HAVE_SIGINFO_H
/* Neither POSIX, C89 nor C99: Solaris-specific (others?).
* For: siginfo_t (also defined by signal.h when in
* POSIX/extensions mode). */
#include <siginfo.h>
#endif
#ifdef HAVE_SYS_TERMIOS_H
/* Neither POSIX, C89 nor C99: a common extension.
* For: TIOCGWINSZ and struct winsize (under at least
* Solaris, NetBSD and (dual-listed) FreeBSD). */
#include <sys/termios.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
/* As above (under at least Linux and FreeBSD). */
#include <sys/ioctl.h>
#endif
],
[
/* Avert high-level optimisation, by making the program's
* return value depend on all tested identifiers. */
int ret = 0;
/* POSIX only: might be unhidden by _POSIX_C_SOURCE. */
struct sigaction sa;
sigset_t ss;
siginfo_t info;
ret += (int)(void *)&info + kill( 0, 0 ) +
sigaction( 0, &sa, 0 ) + sigemptyset( &ss );
/* Extended-POSIX: might be unhidden by _XOPEN_SOURCE. */
ret += killpg( 0, 0 );
/* Non-standard: might be hidden by the macros. */
{
struct winsize termsize;
ret += (int)(void *)&termsize;
ret += SIGWINCH + TIOCGWINSZ + SIGIO;
}
return ret;
],
local_cv_use__posix_c_source=yes,
local_cv_use__posix_c_source=no,
)
if test x$local_cv_use__posix_c_source = xyes; then
AC_MSG_RESULT( yes )
local_found_posix_switch=yes
break;
else
AC_MSG_RESULT( no )
fi
done
#
# We didn't find any combination of switches that worked - revert to
# no switches and hope that the fallbacks work. A warning will be
# printed at the end of the configure script.
#
if test ! x$local_found_posix_switch = xyes; then
CFLAGS="$XCFLAGS"
fi
#
# Check for presense of various functions used by fish
#
AC_CHECK_FUNCS( gettext wcsdup wcsndup wcslen wcscasecmp wcsncasecmp fwprintf )
AC_CHECK_FUNCS( futimes wcwidth wcswidth wcstok fputwc fgetwc )
AC_CHECK_FUNCS( wcstol dcgettext wcslcat wcslcpy lrand48_r killpg)
#
# 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
#
#
# Check if realpath accepts null for its second argument
#
AC_MSG_CHECKING([if realpath accepts null for its second argument])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([
#include <limits.h>
#include <errno.h>
#include <stdlib.h>],
[int status; char *res; res = realpath( "somefile", 0 ); status = !(res != 0 || errno == ENOENT); exit( status );])],
[
AC_LANG_PROGRAM(
[
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
],
[
int status;
char *res;
res = realpath( "somefile", 0 );
status = !(res != 0 || errno == ENOENT);
exit( status );
]
)
],
[have_realpath_null=yes],
[have_realpath_null=no] )
[have_realpath_null=no]
)
if test "$have_realpath_null" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_REALPATH_NULL], [1],
[Define to 1 if realpath accepts null for its second argument.])
AC_DEFINE(
[HAVE_REALPATH_NULL],
[1],
[Define to 1 if realpath accepts null for its second argument.]
)
else
AC_MSG_RESULT(no)
fi
#
# Check if struct winsize and TIOCGWINSZ exist
#
AC_MSG_CHECKING([if struct winsize and TIOCGWINSZ exist])
AC_LINK_IFELSE(
[
AC_LANG_PROGRAM(
[
#ifdef HAVE_SYS_TERMIOS_H
#include <sys/termios.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
],
[
struct winsize termsize = {0};
TIOCGWINSZ;
]
)
],
[
AC_MSG_RESULT(yes);
AC_DEFINE([HAVE_WINSIZE], [1], [Define to 1 if the winsize struct and TIOCGWINSZ macro exist])
],
[
AC_MSG_RESULT(no)
]
)
#
# If we have a fwprintf in libc, test that it actually works. As of
# March 2006, it is broken under Dragonfly BSD.
#
if test "$ac_cv_func_fwprintf" = yes; then
AC_MSG_CHECKING([if fwprintf is broken])
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
],
[
setlocale( LC_ALL, "" );
fwprintf( stderr, L"%ls%ls", L"", L"fish:" );
])],
[
AC_LANG_PROGRAM(
[
#include <stdlib.h>
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
],
[
setlocale( LC_ALL, "" );
fwprintf( stderr, L"%ls%ls", L"", L"fish:" );
]
)
],
[
AC_MSG_RESULT(no)
],
[
AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_BROKEN_FWPRINTF], [1], [Define to 1 one if the implemented fwprintf is broken])
] )
]
)
fi
# Check for RLIMIT_NPROC in sys/resource.h.
AC_MSG_CHECKING([for RLIMIT_NPROC in sys/resource.h])
AC_TRY_COMPILE([#include <sys/resource.h>],
[int tmp; tmp=RLIMIT_NPROC;], have_rlimit_as=yes, have_rlimit_as=no)
if test "$have_rlimit_as" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RLIMIT_NPROC], [1],
[Define to 1 if HAVE_RLIMIT_NPROC is defined in <sys/resource.h>.])
else
AC_MSG_RESULT(no)
fi
# Check for RLIMIT_AS in sys/resource.h.
AC_MSG_CHECKING([for RLIMIT_AS in sys/resource.h])
AC_TRY_COMPILE([#include <sys/resource.h>],
[int tmp; tmp=RLIMIT_AS;], have_rlimit_as=yes, have_rlimit_as=no)
if test "$have_rlimit_as" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RLIMIT_AS], [1],
[Define to 1 if HAVE_RLIMIT_AS is defined in <sys/resource.h>.])
else
AC_MSG_RESULT(no)
fi
# Check for RLIMIT_MEMLOCK in sys/resource.h.
AC_MSG_CHECKING([for RLIMIT_MEMLOCK in sys/resource.h])
AC_TRY_COMPILE([#include <sys/resource.h>],
[int tmp; tmp=RLIMIT_MEMLOCK;], have_rlimit_as=yes, have_rlimit_as=no)
if test "$have_rlimit_as" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RLIMIT_MEMLOCK], [1],
[Define to 1 if HAVE_RLIMIT_MEMLOCK is defined in <sys/resource.h>.])
else
AC_MSG_RESULT(no)
fi
# Check for RLIMIT_RSS in sys/resource.h.
AC_MSG_CHECKING([for RLIMIT_RSS in sys/resource.h])
AC_TRY_COMPILE([#include <sys/resource.h>],
[int tmp; tmp=RLIMIT_RSS;], have_rlimit_as=yes, have_rlimit_as=no)
if test "$have_rlimit_as" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE_RLIMIT_RSS], [1],
[Define to 1 if HAVE_RLIMIT_RSS is defined in <sys/resource.h>.])
else
AC_MSG_RESULT(no)
fi
# Check for _nl_msg_cat_cntr symbol
AC_MSG_CHECKING([for _nl_msg_cat_cntr symbol])
AC_TRY_LINK([#if HAVE_LIBINTL_H]
[#include <libintl.h>]
[#endif],
[extern int _nl_msg_cat_cntr;]
[int tmp = _nl_msg_cat_cntr; exit(tmp);], have__nl_msg_cat_cntr=yes, have__nl_msg_cat_cntr=no)
AC_TRY_LINK(
[
#if HAVE_LIBINTL_H
#include <libintl.h>
#endif
],
[
extern int _nl_msg_cat_cntr;
int tmp = _nl_msg_cat_cntr;
exit(tmp);
],
have__nl_msg_cat_cntr=yes,
have__nl_msg_cat_cntr=no
)
if test "$have__nl_msg_cat_cntr" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE([HAVE__NL_MSG_CAT_CNTR], [1],
[Define to 1 if the _nl_msg_cat_cntr symbol is exported.])
AC_DEFINE(
[HAVE__NL_MSG_CAT_CNTR],
[1],
[Define to 1 if the _nl_msg_cat_cntr symbol is exported.]
)
else
AC_MSG_RESULT(no)
fi
# Check if we are using basic BSD curses - in that case we redefine
# Check if getopt_long exists and works
AC_MSG_CHECKING([if getopt_long exists and works])
AC_TRY_LINK(
[
#if HAVE_GETOPT_H
#include <getopt.h>
#endif
],
[
static struct option
long_options[] =
{
0, 0, 0, 0
}
;
int opt = getopt_long( 0,
0,
0,
long_options,
0 );
],
have_working_getopt_long=yes,
have_working_getopt_long=no
)
if test "$have_working_getopt_long" = yes; then
AC_MSG_RESULT(yes)
AC_DEFINE(
[HAVE_WORKING_GETOPT_LONG],
[1],
[Define to 1 if getopt_long exists and works.]
)
else
AC_MSG_RESULT(no)
fi
# Check if del_curterm is broken - in that case we redefine
# del_curterm as a no-op, to avoid a double-free
AC_MSG_CHECKING([If we are using BSD curses])
AC_MSG_CHECKING([If del_curterm is broken])
case $target_os in
*bsd*)
AC_MSG_RESULT(yes)
AC_CHECK_LIB( ncurses, del_curterm, true, [AC_DEFINE([HAVE_BROKEN_DEL_CURTERM],[1],[We are using basic BSD curses, redefine del_curterm to a no-op to avoid a double-free bug])])
AC_DEFINE(
[HAVE_BROKEN_DEL_CURTERM],
[1],
[del_curterm is broken, redefine it to a no-op to avoid a double-free bug]
)
;;
*)
AC_MSG_RESULT(no)
@@ -404,8 +776,14 @@ 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/Doxyfile seq])
AC_OUTPUT
if test ! x$local_found_posix_switch = xyes; then
echo "Can't find a combination of switches to enable common extensions like detecting window size."
echo "Some fish features may be disabled."
fi
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,6 +2,8 @@
The length command, used for determining the number of items in an
environment variable array.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>

121
create_wajig_completions.py Executable file
View File

@@ -0,0 +1,121 @@
#!/usr/bin/env python
# -*- python -*-
# Program to generate fish completion function for wajig.
# It runs 'wajig command' and analyzes the output to build a
# completion file which it writes to stdout.
# To use the result, direct stdout to
# ~/.fish.d/completions/wajig.fish.
# Author Reuben Thomas, from Don Rozenberg's bash_completion.py and
# fish's apt-get.fish.
import os
import re
import pprint
pp = pprint.PrettyPrinter()
def escape_quotes(s):
return re.sub('\'', '\\\'', s)
# Run wajig command
f = os.popen('wajig commands', 'r')
lines = f.readlines()
option_patt = r'^-([a-z]*)\|--([a-z]*) +([^ ].*)'
option_patt_r = re.compile(option_patt)
command_patt = r'^([a-z-]*) +([^ ].*)'
command_patt_r = re.compile(command_patt)
os_str = []
os_str.append('')
ol_str = []
ol_str.append('')
oh_str = []
oh_str.append('')
o_i = 0
c_str = []
c_str.append('')
ch_str = []
ch_str.append('')
c_i = 0
for l in lines:
l = l.strip()
if l == '' or l.find(':') > -1 or l.find('Run') == 0:
continue
if l.find('-') == 0:
mo = option_patt_r.search(l)
if mo == None:
continue
os_str[o_i] = mo.group(1)
os_str.append('')
ol_str[o_i] = mo.group(2)
ol_str.append('')
oh_str[o_i] = escape_quotes(mo.group(3))
oh_str.append('')
o_i += 1
else:
mo = command_patt_r.search(l)
if mo == None:
continue
c_str[c_i] = mo.group(1)
c_str.append('')
ch_str[c_i] = escape_quotes(mo.group(2))
ch_str.append('')
c_i += 1
# For debugging, print the commands and options.
#print
#pp.pprint(c_str)
#print
#pp.pprint(os_str)
#print
#pp.pprint(ol_str)
part1 = '''function __fish_wajig_no_subcommand -d (N_ 'Test if wajig has yet to be given the subcommand')
for i in (commandline -opc)
if contains -- $i'''
part2 = '''
return 1
end
end
return 0
end
function __fish_wajig_use_package -d (N_ 'Test if wajig command should have packages as potential completion')
for i in (commandline -opc)
if contains -- $i contains bug build build-depend changelog dependents describe detail hold install installr installrs installs list list-files news package purge purge-depend readme recursive recommended reconfigure reinstall remove remove-depend repackage show showinstall showremove showupgrade size sizes source suggested unhold upgrade versions whatis
return 0
end
end
return 1
end
complete -c wajig -n '__fish_wajig_use_package' -a '(__fish_print_packages)' -d (N_ 'Package')'''
wajig = part1
#add the commands.
for i in range(0, len(c_str) - 1):
wajig = "%s %s" % (wajig, c_str[i])
#add part2
wajig = "%s%s" % (wajig, part2)
#add the options.
wajig = "%s%s" % (wajig, os_str[0].lstrip())
for i in range(1, len(os_str) - 1):
wajig = "%s\ncomplete -c apt-get -s %s -l %s -d (N_ '%s')" % (wajig, os_str[i], ol_str[i], oh_str[i])
#add the commands.
for i in range(0, len(c_str) - 1):
wajig = "%s\ncomplete -f -n '__fish_wajig_no_subcommand' -c wajig -a '%s' -d(N_ '%s')" % (wajig, c_str[i], ch_str[i])
#print it all
print wajig

View File

@@ -1,17 +1,27 @@
\section and and - Conditionally execute a command
\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 0.
The and command does not change the current exit status.
The exit status of the last foreground command to exit can always be
accessed using the <a href="index.html#variables-status">$status</a>
variable.
\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

@@ -1,17 +1,19 @@
\section begin begin - Start a new block of code
\section begin begin - start a new block of code
\subsection begin-synopsis Synopsis
<tt>begin; [COMMAND;...] end </tt>
<tt>begin; [COMMANDS...;] end</tt>
\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 +30,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

@@ -1,14 +1,21 @@
\section bind bind - Handle key bindings.
\section bind bind - handle key bindings
\subsection bind-synopsis Synopsis
<tt>bind [OPTIONS] [BINDINGS...] </tt>
<tt>bind [OPTIONS] [BINDINGS...]</tt>
The <tt>bind</tt> builtin causes fish to add the readline style bindings specified by <tt>BINDINGS</tt> to the list of key bindings. For more information on specifying keyboard bindings, use <tt>man readline</tt> to access the readline documentation.
The <tt>bind</tt> builtin causes fish to add the readline style bindings specified by BINDINGS to the list of key bindings, as if they appeared in your <tt>~/.fish_inputrc</tt> file.
For more information on the syntax keyboard bindings, use <tt>man
readline</tt> to access the readline documentation. The availiable commands
are listed in the <a href="index.html#editor">Command Line Editor</a> section
of the fish manual - but you may also use any fish command! To write such
commands, see the <a href="#commandline">commandline</a> builtin. It's good
practice to put the code into a <tt><a href="#function">function</a> -b</tt>
and bind to the function name.
\subsection bind-description Description
- <tt>-M MODE</tt> or <tt>--set-mode=MODE</tt> sets the current input mode to MODE.
\subsection bind-example Example
<tt>bind -M vi</tt> changes to the vi input mode

View File

@@ -1,5 +1,4 @@
\section block block - Temporarily block delivery of events
\section block block - temporarily block delivery of events
\subsection block-synopsis Synopsis
<tt>block [OPTIONS...]</tt>
@@ -12,7 +11,8 @@
\subsection block-example Example
<pre>block -g
<pre>
block -g
\#Do something that should not be interrupted
block -e
</pre>

View File

@@ -1,4 +1,3 @@
\section break break - stop the innermost currently evaluated loop
\subsection break-synopsis Synopsis
@@ -9,13 +8,12 @@ The \c break builtin is used to halt a currently running loop, such as a <a href
\subsection break-example Example
The following code searches all .c files for smurfs, and halts at the first occurrence.
<p>
<tt>for i in *.c;
<br>&nbsp;&nbsp;&nbsp;&nbsp;if grep smurf $i;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo Smurfs are present in $i;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;
<br>&nbsp;&nbsp;&nbsp;&nbsp;end;
<br>end;
</tt>
</p>
<pre>
for i in *.c
if grep smurf $i
echo Smurfs are present in $i
break
end
end
</pre>

View File

@@ -1,4 +1,3 @@
\section builtin builtin - run a builtin command
\subsection builtin-synopsis Synopsis

View File

@@ -1,7 +1,7 @@
\section case case - conditionally execute a block of commands
\subsection case-synopsis Synopsis
<tt>switch VALUE; [case [WILDCARD...]; [COMMANDS...];...] end</tt>
<tt>switch VALUE; [case [WILDCARD...]; [COMMANDS...]; ...] end</tt>
\subsection case-description Description
@@ -32,7 +32,6 @@ forms of parameter expansion have been performed for the case command.
If the variable \$animal contains the name of an animal, the following
code would attempt to classify it:
<p>
<pre>
switch $animal
case cat
@@ -47,7 +46,7 @@ switch $animal
echo I have no idea what a $animal is
end
</pre>
</p>
<p>
If the above code was run with \c \$animal set to \c whale, the output would be \c mammal.
</p>
If the above code was run with \c \$animal set to \c whale, the output
would be \c mammal.

View File

@@ -1,4 +1,4 @@
\section commandline commandline - Set or get the current commandline buffer
\section commandline commandline - set or get the current commandline buffer
\subsection commandline-synopsis Synopsis
<tt>commandline [OPTIONS] [CMD]</tt>
@@ -9,8 +9,22 @@
- \c CMD is the new value of the commandline. If unspecified, the
current value of the commandline is written to standard output.
The following switches change what the commandline builtin does
- \c -C or \c --cursor set or get the current cursor position, not
the contents of the buffer. If no argument is given, the current
cursor position is printed, otherwise the argument is interpreted
as the new cursor position.
- \c -f or \c --function inject readline functions into the
reader. This option can not be combined with any other option. It
will cause any additional arguments to be interpreted as readline
functions, and these functions will be injected into the reader, so
that they will be returned to the reader before any additional
actual keypresses are read.
The following switches change the way \c commandline updates the
commandline
commandline buffer
- \c -a or \c --append do not remove the current commandline, append
the specified string at the end of it
@@ -25,23 +39,15 @@ or updated
- \c -b or \c --current-buffer select the entire buffer (default)
- \c -j or \c --current-job select the current job
- \c -p or \c --current-process select the current process
- \c -t or \c --current_token select the current token.
- \c -t or \c --current-token select the current token.
The following switch changes the way \c commandline prints the current
commandline
commandline buffer
- \c -c or \c --cut-at-cursor only print selection up until the
current cursor position
- \c -o or \c --tokenize tokenize the selection and print one string-type token per line
Other switches
- \c -f or \c --function inject readline functions into the
reader. This option can not be combined with any other option. It
will cause any additional arguments to be interpreted as readline
functions, and these functions will be injected into the reader, so
that they will be returned to the reader before any additional
actual keypresses are read.
If commandline is called during a call to complete a given string
using <code>complete -C STRING</code>, commandline will consider the

View File

@@ -1,5 +1,4 @@
\section contains contains - Test if a word is present in a list
\section contains contains - test if a word is present in a list
\subsection contains-synopsis Synopsis
<code>contains [OPTIONS] KEY [VALUES...]</code>

View File

@@ -1,20 +1,19 @@
\section continue continue - skip the rest of the current lap of the innermost currently evaluated loop
\subsection continue-synopsis Synopsis
<tt>LOOP_CONSTRUCT; [COMMANDS...] continue; [COMMANDS...] end</tt>
<tt>LOOP_CONSTRUCT; [COMMANDS...;] continue; [COMMANDS...;] end</tt>
\subsection continue-description Description
The \c continue builtin is used to skip the current lap of the innermost currently running loop, such as a <a href="#for">for</a> loop or a <a href="#while">while</a> loop. 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.
\subsection continue-example Example
The following code removes all tmp files without smurfs.
<p>
<tt>for i in *.tmp;
<br>&nbsp;&nbsp;&nbsp;&nbsp;if grep smurf $i;
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;continue;
<br>&nbsp;&nbsp;&nbsp;&nbsp;end;
<br>&nbsp;&nbsp;&nbsp;&nbsp;rm $i;
<br>end;
</tt>
</p>
<pre>
for i in *.tmp
if grep smurf $i
continue
end
rm $i
end
</pre>

View File

@@ -1,12 +1,11 @@
\section count count - Count the number of elements of an array
\section count count - count the number of elements of an array
\subsection count-synopsis Synopsis
<tt>count $VARIABLE</tt>
\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 +17,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>

155
doc_src/design.hdr Normal file
View File

@@ -0,0 +1,155 @@
/** \page design Design document
\section design-overview Overview
This is a description of the design principles that have been used to
design fish. The fish design has three high level goals. These are:
-# Everything that can be done in other shell languages should be
possible to do in fish, though fish may rely on external commands in
doing so.
-# Fish should be user friendly, but not at the expense of expressiveness.
Most tradeoffs between power and ease of use can be avoided with careful design.
-# Whenever possible without breaking the above goals, fish should
follow the Posix syntax.
To achive these high-level goals, the fish design relies on a number
of more specific design principles. These are presented below,
together with a rationale and a few examples for each.
\section ortho The law of orthogonality
The shell language should have a small set of orthogonal features. Any
situation where two features are related but not identical, one of them
should be removed, and the other should be made powerful and general
enough to handle all common use cases of either feature.
Rationale:
Related features make the language larger, which makes it harder to
learn. It also increases the size of the sourcecode, making the
program harder to maintain and update.
Examples:
- Here documents are too similar to using echo inside of a pipeline.
- Subshells, command substitution and process substitution are strongly related. \c fish only supports command substitution, the others can be achived either using a block or the psub shellscript function.
- Having both aliases and functions is confusing, especially since both of them have limitations and problems. \c fish functions have none of the drawbacks of either syntax.
- The many Posix quoting styles are silly, especially \$''.
\section sep The law of minimalism
The shell should only contain features that cannot be implemented in
a reasonable way outside of the shell. A large performance decrease,
as well as some program complexity increase is acceptable in order to
improve separation.
Rationale:
A modular project is easier to maintain since smaller programs are far
easier to understand than larger ones. A modular project is also more
future proof since the modules can be individually
replaced. Modularity also decreases the severity of bugs, since there
is good hope that a bug, even a serious one, in one module, does not
take the whole system down.
Examples:
- Builtin commands should only be created when it cannot be
avoided. \c echo, \c kill, \c printf and \c time are among the commands
that fish does not implement internally since they can be provided as
external commands. Several other commands that are commonly implemented
as builtins and can not be implemented as external commands,
including \c type, \c vared, \c pushd and \c popd are implemented as shellscript
functions in fish.
- Mathematical calculations, regex matching, generating lists of numbers
and many other funtions can easily be done in external programs. They
should not be supported internally by the shell.
The law of minimalism does not imply that a large feature set is
bad. So long as a feature is not part of the shell itself, but a
separate command or at least a shellscript function, bloat is fine.
\section conf Configurability is the root of all evil
Every configuration option in a program is a place where the program
is too stupid to figure out for itself what the user really wants, and
should be considered a failiure of both the program and the programmer
who implemented it.
Rationale:
Different configuration options are a nightmare to maintain, since the
number of potential bugs caused by specific configuration combinations
quickly becomes an issue. Configuration options often imply
assumptions about the code which change when reimplementing the code,
causing issues with backwards compatibility. But mostly, configuration
options should be avoided since they simply should not exist, as the
program should be smart enough to do what is best, or at least a good
enough approximation of it.
Examples:
- Fish allows the user to set various syntax highlighting colors. This is needed because fish does not know what colors the terminal uses by default, which might make some things unreadable. The proper solution would be for text color preferences to be defined centrally by the user for all programs, and for the terminal emulator to send these color properties to fish.
- Fish does not allow you to set the history filename, the number of history entries, different language substyles or any number of other common shell configuration options.
A special note on the evils of configurability is the long list of
very useful features found in some shells, that are not turned on by
default. Both zsh and bash support command specific completions, but
no such completions are shipped with bash by default, and they are
turned of by default in zsh. Other features that zsh support that are
disabled by default include tab-completion of strings containing
wildcards, a sane completion pager and a history file.
\section user The law of user focus
When designing a program, one should first think about how to make a
intuitive and powerful program. Implementation issues should only be
considered once a user interface has been designed.
Rationale:
This design rule is different than the others, since it describes how
one should go about designing new features, not what the features
should be. The problem with focusing on what can be done, and what is
easy to do, is that to much of the implementation is exposed. This
means that the user must know a great deal about the underlying system
to be able to guess how the shell works, it also means that the
language will often be rather low-level.
Examples:
- There should only be one type of input to the shell, lists of commands. Loops, conditionals and variable assignments are all performed through regular commands.
- The differences between builtin commands, shellscript functions and builtin commands should be made as small as possible. Builtins and shellscript functions should have exactly the same types of argument expansion as other commands, should be possible to use in any position in a pipeline, and should support any io redirection.
- Instead of forking when performing command substitution to provide a fake variable scope, all fish commands are performed from the same process, and fish instead supports true scoping
- All blocks end with the \c end builtin
\section disc The law of discoverability
A program should be designed to make its features as
easy as possible to discover for the user.
Rationale:
A program whose features are discoverable turns a new user into an
expert in a shorter span of time, since the user will become an expert
on the program simply by using it.
The main benefit of a graphical program over a command line-based
program is discoverability. In a graphical program, one can discover
all the common features by simply looking at the user interface and
guessing what the different buttons, menus and other widgets do. The
traditional way to discover features in commandline programs is
through manual pages. This requires both that the user starts to use a
different program, and the she/he then remembers the new information
until the next time she/he uses the same program.
Examples:
- Everything should be tab-completable, and every tab completion should have a description
- Every syntax error and error in a builtin command should contain an error message describing what went wrong and a relevant help page. Whenever possible, errors should be flagged red by the syntax highlighter.
- The help manual should be easy to read, easily available from the shell, complete and contain many examples
- The language should be uniform, so that once the user understands the command/argument syntax, he will know the whole language, and be able to use tab-completion to discover new featues.
*/

View File

@@ -1,4 +1,4 @@
\section dirh dirh
\section dirh dirh - print directory history
\subsection dirh-synopsis Synopsis
<tt>dirh</tt>

View File

@@ -1,4 +1,4 @@
\section dirs dirs
\section dirs dirs - print directory stack
\subsection dirs-synopsis Synopsis
<tt>dirs</tt>

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
\section else else - execute command if a condition is not met.
\section else else - execute command if a condition is not met
\subsection else-synopsis Synopsis
<tt>if CONDITION; COMMAND_TRUE [else; COMMAND_FALSE] end;</tt>
<tt>if CONDITION; COMMANDS_TRUE...; [else; COMMANDS_FALSE...;] end</tt>
\subsection else-description Description
<tt>if</tt> will execute the command CONDITION. If the commands exit
status is zero, the command COMMAND_TRUE will execute. If it is
not zero and COMMAND_FALSE is specified, COMMAND_FALSE will be
executed.
<tt>if</tt> will execute the command CONDITION. If the condition's exit
status is 0, the commands COMMANDS_TRUE will execute. If it is not 0 and
<tt>else</tt> is given, COMMANDS_FALSE will be executed. Hint: use
<a href="#begin"><tt>begin; ...; end</tt></a> for complex conditions.
\subsection else-example Example

View File

@@ -1,13 +1,17 @@
\section end end - end a block of commands.
\subsection end-synopsis Synopsis
<pre>for VARNAME in [VALUES...]; COMMANDS; end
if CONDITION; COMMAND_TRUE [else; COMMAND_FALSE] end
while CONDITION; COMMANDS; end
switch VALUE; [case [WILDCARD...]; [COMMANDS...];...] end
<pre>
begin; [COMMANDS...] end
if CONDITION; COMMANDS_TRUE...; [else; COMMANDS_FALSE...;] end
while CONDITION; COMMANDS...; end
for VARNAME in [VALUES...]; COMMANDS...; end
switch VALUE; [case [WILDCARD...]; [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

@@ -1,5 +1,4 @@
\section exec exec - Execute command in current process
\section exec exec - execute command in current process
\subsection exec-synopsis Synopsis
<tt>exec COMMAND [OPTIONS...]</tt>

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.

136
doc_src/faq.hdr Normal file
View File

@@ -0,0 +1,136 @@
/** \page faq Frequently asked questions
- <a href='#faq-cwd-symlink'>Why does cd, pwd and other fish commands always resolve symlinked directories to their canonical path?</a>
- <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>
- <a href='#faq-titlebar'>I'm seeing weird output before each prompt when using screen. What's wrong?</a>
- <a href='#faq-greeting'>How do I change the greeting message?</a>
<hr>
\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 ~/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
unresolved. It is indeed possible to do this partially, and many other
shells do so. But it was felt there are enough serious corner cases
that this is a bad idea. Most such issues have to do with how '..' is
handled, and are varitations of the following example:
Writing <code>cd images; ls ..</code> given the above directory
structure would list the contents of ~/Documents, not of ~, even
though using <code>cd ..</code> changes the current direcotry to ~,
and the prompt, the pwd builtin and many other directory information
sources suggest that the the current directory is ~/images and it's
parent is ~. This issue is not possible to fix without either making
every single command into a builtin, breaking Unix semantics or
implementing kludges in every single command.
This issue can also be seen when doing IO redirection.
Another related issue is that many programs that operate on recursive
directory trees, like the find command, silently ignore symlinked
directories. For example, <code>find $PWD -name '*.txt'</code>
silently fails in shells that don't resolve symlinked paths.
<hr>
\section faq-cd-autocomplete Why does the cd command autocompletion list the subdirectories of my home directory as completions?
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
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, write <code>set CDPATH .</code> on the commandline.
<hr>
\section faq-cd-implicit I accidentally entered a directory path and fish changed directory. What happened?
If fish is unable to locate a command with a given name, fish will
test if a directory of that name exists. If it does, it is implicitly
assumed that you want to change working directory. For example, the
fastest way to switch to your home directory is to simply type
<code>~</code>.
<hr>
\section faq-open The open command doesn't work.
The open command uses the mimetype database and the .desktop files
used by Gnome and KDE to identify filetypes and default actions. If
at least one of these two desktops are installed, but the open command is
not working, this probably means that the relevant files are installed
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:
\section faq-titlebar I'm seeing weird output before each prompt when using screen. What's wrong?
Quick answer:
Run the following command in fish:
<pre>
echo function fish_title;end ~/.config/fish/config.fish
</pre>
Problem solved!
The long answer:
Fish is trying to set the titlebar message of your terminal. While
screen itself supports this feature, your terminal does
not. Unfortuntaly, when the underlying terminal doesn't support
setting the titlebar, screen simply passes through the escape codes
and text to the underlying terminal instead of ignoring them. It is
impossible detect and resolve this problem from inside fish since fish
has no way of knowing what the underlying terminal type is. For now,
the only way to fix this is to unset the titlebar message, as
suggested above.
Note that fish has a default titlebar message, which will be used if
the fish_title function is undefined. So simply unsetting the
fish_title function will not work.
<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.
<hr>
\section faq-greeting How do I change the greeting message?
Change the value of the variable fish_greeting. For example, to remove
the greeting use:
<pre>
set fish_greeting
</pre>
*/

23
doc_src/fish.txt Normal file
View File

@@ -0,0 +1,23 @@
\section fish fish - the friendly interactive shell
\subsection fish-synopsis Synopsis
fish [-h] [-v] [-c command] [FILE [ARGUMENTS...]]
\subsection fish-description Description
A commandline shell written mainly with interactive use in mind. The
full manual is available <a href='index.html'>in html</a> by using the
<a href='#help'>help</a> command from inside fish.
- <code>-c</code> or <code>--command=COMMANDS</code> evaluate the specified commands instead of reading from the commandline
- <code>-d</code> or <code>--debug-level=DEBUG_LEVEL</code> specify the verbosity level of fish. A higher number means higher verbosity. The default level is 1.
- <code>-h</code> or <code>--help</code> display help and exit
- <code>-i</code> or <code>--interactive</code> specify that fish is to run in interactive mode
- <code>-l</code> or <code>--login</code> specify that fish is to run as a login shell
- <code>-n</code> or <code>--no-execute</code> do not execute any commands, only perform syntax checking
- <code>-p</code> or <code>--profile=PROFILE_FILE</code> when fish exits, output timing information on all executed commands to the specified file
- <code>-v</code> or <code>--version</code> display version and exit
The fish exit status is generally the exit status of the last
foreground command. If fish is exiting because of a parse error, the
exit status is 127.

View File

@@ -1,5 +1,4 @@
\section fish_pager fish_pager - Internal command used by fish
\section fish_pager fish_pager - internal command used by fish
\subsection fish_pager-description Description

View File

@@ -1,5 +1,4 @@
\section fishd fishd - Universal variable daemon
\section fishd fishd - universal variable daemon
\subsection fishd-synopsis Synopsis
<tt>fishd [(-h|--help|-v|--version)]</tt>
@@ -18,8 +17,15 @@ When no clients are connected, fishd will automatically shut down.
\subsection fishd-files Files
~/.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
(which is generally the case), manual modifications to ~/.fishd.HOSTNAME
will be lost.
\c ~/.config/fish/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. The file must always be
stored in ASCII format. If an instance of fishd is running (which is
generally the case), manual modifications to ~/.fishd.HOSTNAME will be
lost. Do NOT edit this file manually!
\c /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,13 +1,13 @@
\section for for - perform a set of commands multiple times.
\subsection for-synopsis Synopsis
<tt>for VARNAME in [VALUES...]; [COMMANDS...]; end</tt>
<tt>for VARNAME in [VALUES...]; COMMANDS...; end</tt>
\subsection for-description Description
<tt>for</tt> is a loop construct. It will perform the commands specified
by <tt>COMMANDS</tt> multiple times. Each time the environment variable
specified by <tt>VARNAME</tt> is assigned a new value from <tt>VALUES</tt>.
<tt>for</tt> is a loop construct. It will perform the commands specified by
COMMANDS multiple times. Each time the environment variable specified by
VARNAME is assigned a new value from VALUES. If VALUES is empty, COMMANDS will
not be executed at all.
\subsection for-example Example
@@ -17,7 +17,9 @@ The command
would output:
<pre>foo
<pre>
foo
bar
baz</pre>
baz
</pre>

View File

@@ -1,18 +1,17 @@
\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,14 +21,15 @@ 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
<pre>function ll
<pre>
function ll
ls -l $argv
end
</pre>

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, not their definition
- <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,5 +1,4 @@
\section help help - Display fish documentation
\section help help - display fish documentation
\subsection help-synopsis Synopsis
<tt>help [SECTION]</tt>
@@ -8,8 +7,11 @@
The \c help command is used to display a section of the fish help documentation.
If the BROWSER environment variable is set, it will be used to display
the documentation, otherwise fish will search for a suitable browser.
If the BROWSER environment variable is set, it will be used to display the
documentation, otherwise fish will search for a suitable browser.
Note also that most builtin commands display their help in the terminal when
given the <tt>--help</tt> option.
\subsection help-example Example

View File

@@ -1,13 +1,23 @@
\section if if - Conditionally execute a command
\section if if - conditionally execute a command
\subsection if-synopsis Synopsis
<tt>if CONDITION; COMMAND_TRUE [else; COMMAND_FALSE] end;</tt>
<tt>if CONDITION; COMMANDS_TRUE...; [else; COMMANDS_FALSE...;] end</tt>
\subsection if-description Description
<tt>if</tt> will execute the command CONDITION. If the commands exit
status is zero, the command COMMAND_TRUE will execute. If it is
not zero and COMMAND_FALSE is specified, COMMAND_FALSE will be
executed.
<tt>if</tt> will execute the command CONDITION. If the condition's
exit status is 0, the commands COMMANDS_TRUE will execute. If the
exit status is not 0 and <tt>else</tt> is given, COMMANDS_FALSE will
be executed.
In order to use the exit status of mutiple commands as the condition
of an if block, use <a href="#begin"><tt>begin; ...; end</tt></a> and
the short circut commands <a href="commands.html#and">and</a> and <a
href="commands.html#or">or</a>.
The exit status of the last foreground command to exit can always be
accessed using the <a href="index.html#variables-status">$status</a>
variable.
\subsection if-example Example

1362
doc_src/index.hdr Normal file

File diff suppressed because it is too large Load Diff

12
doc_src/isatty.txt Normal file
View File

@@ -0,0 +1,12 @@
\section isatty isatty - test if the specidied file descriptor is a tty
\subsection isatty-synopsis Synopsis
<tt>isatty [FILE DESCRIPTOR]</tt>
where FILE DESCRIPTOR may be either the number of a file descriptor, or one
of the strings stdin, stdout and stderr.
If the specified file descriptor is a tty, the exit status of the
command is zero, otherwise, it is non-zero.

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

989
doc_src/license.hdr Normal file
View File

@@ -0,0 +1,989 @@
/** \page license Licenses
Fish Copyright (C) 2005-2006 Axel Liljencrantz. Fish is released under
the GNU General Public License, version 2. The license agreement is
included below.
Fish contains code under the BSD license, namely versions of the
two functions strlcat and strlcpy, modified for use with wide
character strings. This code is copyrighted by Todd C. Miller. The
license agreement is included below.
The XSel command, written and copyrighted by Conrad Parker, is
distributed together with, and used by fish. It is released under the MIT
license. The license agreement is included below.
The xdgmime library, written and copyrighted by Red Hat, Inc, is used
by the mimedb command, which is a part of fish. It is released under
the LGPL. The license agreement is included below.
Fish contains code from the glibc library, namely the wcstok
function. This code is licensed under the LGPL. The license agreement
is included below.
<HR>
<H2><A NAME="SEC1" HREF="gpl.html#TOC1">GNU GENERAL PUBLIC LICENSE</A></H2>
<P>
Version 2, June 1991
</P>
<PRE>
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
</PRE>
<H2><A NAME="SEC2" HREF="gpl.html#TOC2">Preamble</A></H2>
<P>
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
</P>
<P>
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
</P>
<P>
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
</P>
<P>
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
</P>
<P>
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
</P>
<P>
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
</P>
<P>
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
</P>
<P>
The precise terms and conditions for copying, distribution and
modification follow.
</P>
<H2><A NAME="SEC3" HREF="gpl.html#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A></H2>
<P>
<STRONG>0.</STRONG>
This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
<P>
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
<P>
<STRONG>1.</STRONG>
You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
<P>
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
<P>
<STRONG>2.</STRONG>
You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
<P>
<DL>
<DT>
<DD>
<STRONG>a)</STRONG>
You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
</DD>
</DT>
</DL>
<P>
<DL>
<DT>
<DD>
<STRONG>b)</STRONG>
You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
</DD>
</DT>
</DL>
<P>
<DL>
<DT>
<DD>
<STRONG>c)</STRONG>
If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
</DD>
</DT>
</DL>
<P>
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
<P>
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
<P>
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
<P>
<STRONG>3.</STRONG>
You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
<!-- we use this doubled UL to get the sub-sections indented, -->
<!-- while making the bullets as unobvious as possible. -->
<DL>
<DT>
<DD>
<STRONG>a)</STRONG>
Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
</DD>
</DT>
</DL>
<P>
<DL>
<DT>
<DD>
<STRONG>b)</STRONG>
Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
</DD>
</DT>
</DL>
<P>
<DL>
<DT>
<DD>
<STRONG>c)</STRONG>
Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
</DD>
</DT>
</DL>
<P>
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
<P>
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
<P>
<STRONG>4.</STRONG>
You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
<P>
<STRONG>5.</STRONG>
You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
<P>
<STRONG>6.</STRONG>
Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
<P>
<STRONG>7.</STRONG>
If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
<P>
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
<P>
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
<P>
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
<P>
<STRONG>8.</STRONG>
If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
<P>
<STRONG>9.</STRONG>
The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
<P>
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
<P>
<STRONG>10.</STRONG>
If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
<P><STRONG>NO WARRANTY</STRONG></P>
<P>
<STRONG>11.</STRONG>
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
<P>
<STRONG>12.</STRONG>
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
<P>
<HR>
<h2>License for wcslcat and wcslcpy</h2>
\c fish also contains small amounts of code under the BSD
license, namely versions of the two functions strlcat and strlcpy,
modified for use with wide character strings. This code is copyrighted
by Todd C. Miller.
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
<HR>
<h2>License for XSel</h2>
The XSel command, written and copyrighted by Conrad Parker, is
distributed together with \c fish.
It is Copyright (C) 2001 Conrad Parker <conrad@vergenet.net>
Permission to use, copy, modify, distribute, and sell this software
and its documentation for any purpose is hereby granted without fee,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation. No representations are made about the
suitability of this software for any purpose. It is provided "as is"
without express or implied warranty.
<HR>
<H2><A NAME="SEC1" HREF="#TOC1">GNU LESSER GENERAL PUBLIC LICENSE</A></H2>
<P>
Version 2.1, February 1999
<P>
<PRE>
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
</PRE>
<H2><A NAME="SEC2" HREF="#TOC2">Preamble</A></H2>
<P>
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
<P>
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
<P>
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
<P>
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
<P>
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
<P>
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
<P>
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
<P>
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
<P>
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
<P>
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
<P>
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
<P>
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
<P>
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
<P>
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
<P>
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
<P>
<H2><A NAME="SEC3" HREF="#TOC3">TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</A></H2>
<P>
<STRONG>0.</STRONG>
This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
<P>
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
<P>
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
<P>
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
<P>
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
<P>
<STRONG>1.</STRONG>
You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
<P>
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
<P>
<STRONG>2.</STRONG>
You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
<P>
<UL>
<LI><STRONG>a)</STRONG>
The modified work must itself be a software library.
<LI><STRONG>b)</STRONG>
You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
<LI><STRONG>c)</STRONG>
You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
<LI><STRONG>d)</STRONG>
If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
<P>
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
<P>
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
<P>
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
<P>
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
</UL>
<P>
<STRONG>3.</STRONG>
You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
<P>
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
<P>
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
<P>
<STRONG>4.</STRONG>
You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
<P>
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
<P>
<STRONG>5.</STRONG>
A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
<P>
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
<P>
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
<P>
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
<P>
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
<P>
<STRONG>6.</STRONG>
As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
<P>
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
<P>
<UL>
<LI><STRONG>a)</STRONG> Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
<LI><STRONG>b)</STRONG> Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
<LI><STRONG>c)</STRONG> Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
<LI><STRONG>d)</STRONG> If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
<LI><STRONG>e)</STRONG> Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
</UL>
<P>
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
<P>
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
<P>
<STRONG>7.</STRONG> You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
<P>
<UL>
<LI><STRONG>a)</STRONG> Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
<LI><STRONG>b)</STRONG> Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
</UL>
<P>
<STRONG>8.</STRONG> You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
<P>
<STRONG>9.</STRONG>
You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
<P>
<STRONG>10.</STRONG>
Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
<P>
<STRONG>11.</STRONG>
If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
<P>
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
<P>
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
<P>
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
<P>
<STRONG>12.</STRONG>
If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
<P>
<STRONG>13.</STRONG>
The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
<P>
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
<P>
<STRONG>14.</STRONG>
If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
<P>
<STRONG>NO WARRANTY</STRONG>
<P>
<STRONG>15.</STRONG>
BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
<P>
<STRONG>16.</STRONG>
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
<P>
*/

View File

@@ -1,5 +1,4 @@
\section mimedb mimedb - Lookup file information via the mime database
\section mimedb mimedb - lookup file information via the mime database
\subsection mimedb-synopsis Synopsis
<tt>mimedb [OPTIONS] FILES...</tt>
@@ -14,6 +13,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

@@ -1,10 +1,10 @@
\section nextd nextd
\section nextd nextd - move forward through directory history
\subsection nextd-synopsis Synopsis
<tt>nextd [-l | --list] [pos]</tt>
\subsection nextd-description Description <tt>nextd</tt> moves
forwards <tt>pos</tt> positions in the history of visited directories;
if the end of the history has been hit, a warning is printed. If the
<code>-l></code> or <code>--list</code> flag is specified, the current
\subsection nextd-description Description
<tt>nextd</tt> moves forwards <tt>pos</tt> positions in the history of visited
directories; if the end of the history has been hit, a warning is printed. If
the <code>-l></code> or <code>--list</code> flag is specified, the current
history is also displayed.

View File

@@ -1,14 +1,12 @@
\section not not - Negate the exit status of a job
\section not not - negate the exit status of a job
\subsection not-synopsis Synopsis
<tt>not COMMAND [OPTIONS...]</tt>
<tt>not COMMAND [OPTIONS...]</tt>
\subsection not-description Description
The \c not builtin is used to negate the exit status of another command.
\subsection not-example Example
The following code reports an error and exits if no file named spoon can be found.

View File

@@ -1,5 +1,4 @@
\section open open - Open file in it's default application
\section open open - open file in it's default application
\subsection open-synopsis Synopsis
<tt>open FILES...</tt>

View File

@@ -1,17 +1,27 @@
\section or or - Conditionally execute a command
\section or or - conditionally execute a command
\subsection or-synopsis Synopsis
<tt>COMMAND1; or COMMAND2</tt>
\subsection or-description Description
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 \c or builtin is used to execute a command if the current exit
status (as set by the last previous command) is not 0.
The or command does not change the current exit status.
The exit status of the last foreground command to exit can always be
accessed using the <a href="index.html#variables-status">$status</a>
variable.
\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

@@ -1,4 +1,4 @@
\section popd popd
\section popd popd - move through directory stack
\subsection popd-synopsis Synopsis
<tt>popd</tt>

View File

@@ -1,10 +1,11 @@
\section prevd prevd
\section prevd prevd - move backward through direcotry history
\subsection prevd-synopsis Synopsis
<tt>prevd [-l | --list] [pos]</tt>
\subsection prevd-description Description <tt>prevd</tt> moves
backwards <tt>pos</tt> positions in the history of visited
directories; if the beginning of the history has been hit, a warning
is printed. If the <code>-l</code> or <code>--list</code> flag is
specified, the current history is also displayed.
\subsection prevd-description Description
<tt>prevd</tt> moves backwards <tt>pos</tt> positions in the history
of visited directories; if the beginning of the history has been hit,
a warning is printed. If the <code>-l</code> or <code>--list</code>
flag is specified, the current history is also displayed.

View File

@@ -1,5 +1,4 @@
\section psub psub - Perform process substitution
\section psub psub - perform process substitution
\subsection psub-synopsis Synopsis
<tt>COMMAND1 (COMMAND2|psub) </tt>

View File

@@ -1,4 +1,4 @@
\section pushd pushd
\section pushd pushd - push directory to directory stack
\subsection pushd-synopsis Synopsis
<tt>pushd [DIRECTORY]</tt>

View File

@@ -1,5 +1,4 @@
\section random random - Generate random number
\section random random - generate random number
\subsection random-synopsis Synopsis
<tt>random [SEED]</tt>

View File

@@ -1,22 +1,26 @@
\section return return - Stop the innermost currently evaluated function
\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
<p>
<pre>function false
return 1
end</pre>
</p>
The following code is an implementation of the false command as a fish function
<pre>
function false
return 1
end
</pre>

View File

@@ -1,18 +1,25 @@
\section set set - Handle environment variables.
\section set set - handle environment variables.
\subsection set-synopsis Synopsis
<code>set [OPTIONS] [VARIABLE_NAME [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>-n</code> or <code>--names</code> List only the names of all defined variables
- <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, not their value
- <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
@@ -20,22 +27,54 @@ 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.
If the variable name is one or more array elements, such as
<code>PATH[1 3 7]</code>, only those array elements specified will be
changed.
changed. When array indices are specified to set, multiple arguments
may be used to specify additional indexes, e.g. <code>set PATH[1]
PATH[4] /bin /sbin</code>. 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

@@ -1,5 +1,4 @@
\section set_color set_color - Set the terminal color
\section set_color set_color - set the terminal color
\subsection set_color-synopsis Synopsis
<tt>set_color [-v --version] [-h --help] [-b --background COLOR] [COLOR]</tt>
@@ -10,10 +9,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 +25,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

@@ -1,4 +1,4 @@
\section source . - Evaluate contents of file.
\section source . - evaluate contents of file.
\subsection source-synopsis Synopsis
<tt>. FILENAME</tt>

View File

@@ -1,5 +1,4 @@
\section status status - Display fish runtime information
\section status status - query fish runtime information
\subsection status-synopsis Synopsis
<tt>status [OPTION]</tt>

View File

@@ -1,8 +1,7 @@
\section switch switch - conditionally execute a block of commands
\subsection switch-synopsis Synopsis
<tt>switch VALUE; [case [WILDCARD...]; [COMMANDS...];...] end</tt>
<tt>switch VALUE; [case [WILDCARD...]; [COMMANDS...]; ...] end</tt>
\subsection switch-description Description
@@ -22,12 +21,17 @@ Note that fish does not fall through on case statements. Though the
syntax may look a bit like C switch statements, it behaves more like
the case stamantes of traditional shells.
Also note that command substitutions in a case statement will be
evaluated even if it's body is not taken. This may seem
counterintuitive at first, but it is unavoidable, since it would be
impossible to know if a case command will evaluate to true before all
forms of parameter expansion have been performed for the case command.
\subsection switch-example Example
If the variable \$animal contains the name of an animal, the
following code would attempt to classify it:
If the variable \$animal contains the name of an animal, the following
code would attempt to classify it:
<p>
<pre>
switch $animal
case cat
@@ -42,10 +46,7 @@ switch $animal
echo I have no idea what a $animal is
end
</pre>
</p>
<p>
If the above code was run with \c \$animal set to \c whale, the output
would be \c mammal.
</p>

View File

@@ -1,4 +1,3 @@
\section trap trap - perform an action when the shell receives a signal
\subsection trap-synopsis Synopsis
@@ -7,8 +6,8 @@
\subsection trap-description Description
Trap is a shellscript wrapper around the fish event delivery
framework. IT is defined for backwards compatibility reasons. For
other uses, it is recommended to define a <a
framework. It exists for backwards compatibility with Posix
shells. For other uses, it is recommended to define a <a
href='index.html#event'>event handler</a>.
- ARG is the command to be executed on signal delivery

View File

@@ -1,5 +1,4 @@
\section type type - Indicate how a name would be interpreted if used as a command name
\section type type - indicate how a name would be interpreted if used as a command name
\subsection type-synopsis Synopsis
<tt>type [OPTIONS] name [name ...]</tt>
@@ -15,6 +14,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'.

View File

@@ -1,5 +1,4 @@
\section ulimit ulimit - Set or get the shells resource usage limits
\section ulimit ulimit - set or get the shells resource usage limits
\subsection ulimit-synopsis Synopsis
<tt>ulimit [OPTIONS] [LIMIT]</tt>
@@ -22,7 +21,7 @@ value. Other options are interpreted as follows:
- <code>-a</code> or <code>--all</code> Set or get all current limits
- <code>-c</code> or <code>--core-size</code> The maximum size of core files created
- <code>-d</code> or <code>--data-size</code> The maximum size of a process’s data segment
- <code>-d</code> or <code>--data-size</code> The maximum size of a process's data segment
- <code>-f</code> or <code>--file-size</code> The maximum size of files created by the shell
- <code>-l</code> or <code>--lock-size</code> The maximum size that may be locked into memory
- <code>-m</code> or <code>--resident-set-size</code> The maximum resident set size

View File

@@ -1,5 +1,4 @@
\section umask umask - Set or get the shells resource usage limits
\section umask umask - set or get the shells resource usage limits
\subsection umask-synopsis Synopsis
<code>umask [OPTIONS] [MASK]</code>

View File

@@ -1,5 +1,4 @@
\section vared vared - Interactively edit the value of an environment variable
\section vared vared - interactively edit the value of an environment variable
\subsection vared-synopsis Synopsis
<tt>vared VARIABLE_NAME</tt>

View File

@@ -1,13 +1,19 @@
\section while while - perform a command multiple times
\subsection while-synopsis Synopsis
<tt>while CONDITION; COMMANDS; end</tt>
<tt>while CONDITION; COMMANDS...; end</tt>
\subsection while-synopsis Synopsis
The <tt>while</tt> builtin causes fish to continually execute the command COMMANDS while the command CONDITION returns with status 0.
\subsection while-description Description
The <tt>while</tt> builtin causes fish to continually execute CONDITION and
execute COMMANDS as long as CONDITION returned with status 0. If CONDITION is
false on the first time, COMMANDS will not be executed at all. Hints: use
<a href="#begin"><tt>begin; ...; end</tt></a> for complex conditions; more
complex control can be achieved with <tt>while true</tt> containing a
<a href="#break">break</a>.
\subsection while-example Example
<tt>while test -f foo.txt; echo file exists; sleep 10; end</tt>
causes fish to print the line 'file exists' at 10 second intervals as long as the file foo.txt exists.
causes fish to print the line 'file exists' at 10 second intervals as long as
the file foo.txt exists.

253
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"fishd ^/tmp/fishd.log.%s"
/**
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") );
}
}
@@ -396,7 +402,7 @@ static void setup_path()
al_init( &l );
if( path )
expand_variable_array( path, &l );
tokenize_variable_array( path, &l );
for( j=0; path_el[j]; j++ )
{
@@ -435,22 +441,45 @@ 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 );
expand_variable_array( path, &l );
tokenize_variable_array( path, &l );
}
}
al_foreach( &l, (void (*)(const void *))&free );
al_foreach( &l, &free );
al_destroy( &l );
}
static void env_set_defaults()
{
if( !env_get( L"USER" ) )
{
struct passwd *pw = getpwuid( getuid());
wchar_t *unam = str2wcs( pw->pw_name );
env_set( L"USER", unam, ENV_GLOBAL );
free( unam );
}
if( !env_get( L"HOME" ) )
{
wchar_t *unam = env_get( L"USER" );
char *unam_narrow = wcs2str( unam );
struct passwd *pw = getpwnam( unam_narrow );
wchar_t *dir = str2wcs( pw->pw_dir );
env_set( L"HOME", dir, ENV_GLOBAL );
free( dir );
free( unam_narrow );
}
}
void env_init()
{
char **p;
struct passwd *pw;
wchar_t *uname;
wchar_t *version;
sb_init( &dyn_var );
b_init( &export_buffer );
@@ -462,6 +491,7 @@ void env_init()
hash_put( &env_read_only, L"status", L"" );
hash_put( &env_read_only, L"history", L"" );
hash_put( &env_read_only, L"version", L"" );
hash_put( &env_read_only, L"_", L"" );
hash_put( &env_read_only, L"LINES", L"" );
hash_put( &env_read_only, L"COLUMNS", L"" );
@@ -549,12 +579,23 @@ void env_init()
env_set( L"USER", uname, ENV_GLOBAL | ENV_EXPORT );
free( uname );
}
/*
Set up the version variable
*/
version = str2wcs( PACKAGE_VERSION );
env_set( L"version", version, ENV_GLOBAL );
free( version );
env_universal_init( env_get( L"FISHD_SOCKET_DIR"),
env_get( L"USER" ),
&start_fishd,
&universal_callback );
/*
Set correct defaults for e.g. USER and HOME variables
*/
env_set_defaults();
}
void env_destroy()
@@ -623,6 +664,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 ) )
{
@@ -675,7 +718,7 @@ int env_set( const wchar_t *key,
env_universal_set( key, val, export );
is_universal = 1;
}
else
{
@@ -703,6 +746,7 @@ int env_set( const wchar_t *key,
(var_mode & ENV_GLOBAL) )
{
node = ( var_mode & ENV_GLOBAL )?global_env:top;
}
else
{
@@ -757,7 +801,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 );
@@ -797,6 +841,7 @@ int env_set( const wchar_t *key,
al_init( &ev.arguments );
al_push( &ev.arguments, L"VARIABLE" );
al_push( &ev.arguments, L"SET" );
al_push( &ev.arguments, key );
// debug( 1, L"env_set: fire events on variable %ls", key );
@@ -817,12 +862,16 @@ int env_set( const wchar_t *key,
/**
Attempt to remove/free the specified key/value pair from the
specified hash table.
\return zero if the variable was not found, non-zero otherwise
*/
static int try_remove( env_node_t *n,
const wchar_t *key )
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;
@@ -847,29 +896,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 ) )
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;
}
@@ -879,6 +971,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;
@@ -893,15 +987,11 @@ wchar_t *env_get( const wchar_t *key )
sb_append( &dyn_var, current );
}
for( i=add_current; i<8; i++ )
for( i=add_current;; i++ )
{
wchar_t *next = history_get( i-add_current );
if( !next )
{
/*
This is not an error - it simply means the user has
a short history
*/
break;
}
@@ -909,6 +999,7 @@ wchar_t *env_get( const wchar_t *key )
sb_append( &dyn_var, ARRAY_SEP_STR );
sb_append( &dyn_var, next );
}
return (wchar_t *)dyn_var.buff;
}
else if( wcscmp( key, L"COLUMNS" )==0 )
@@ -971,40 +1062,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;
}
/**
@@ -1086,8 +1199,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;
@@ -1101,7 +1214,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,
@@ -1111,8 +1224,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 );
@@ -1128,6 +1241,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 =
@@ -1196,7 +1311,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 )
@@ -1212,7 +1327,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;
@@ -1226,7 +1341,7 @@ static void export_func2( const void *k, const void *v, void *aux )
if( !ks || !vs )
{
die_mem();
DIE_MEM();
}
/*
@@ -1249,7 +1364,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)
{

27
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,12 +76,12 @@ 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,
const wchar_t *val,
int mode );
const wchar_t *val,
int mode );
/**
@@ -89,18 +94,23 @@ int env_set( const wchar_t *key,
wchar_t *env_get( const wchar_t *key );
/**
Returns 1 if the specified key exists. This can't be reliable done
Returns 1 if the specified key exists. This can't be reliably 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.
@@ -119,7 +129,6 @@ char **env_export_arr( int recalc );
/**
Insert all variable names into l. These are not copies of the strings and should not be freed after use.
*/
void env_get_names( array_list_t *l, int flags );

View File

@@ -4,7 +4,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -25,6 +25,10 @@
#include <ncurses/term.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <signal.h>
#include "fallback.h"
@@ -160,7 +164,6 @@ static void callback( int type, const wchar_t *name, const wchar_t *val )
{
if( type == BARRIER_REPLY )
{
debug( 3, L"Got barrier reply" );
barrier_reply = 1;
}
else
@@ -182,10 +185,15 @@ 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 );
env_universal_server.input.used=0;
env_universal_read_all();
}
}
@@ -203,6 +211,7 @@ static void reconnect()
debug( 3, L"Get new fishd connection" );
init = 0;
env_universal_server.buffer_consumed = env_universal_server.buffer_used = 0;
env_universal_server.fd = get_socket(1);
init = 1;
if( env_universal_server.fd >= 0 )
@@ -217,26 +226,21 @@ void env_universal_init( wchar_t * p,
void (*sf)(),
void (*cb)( int type, const wchar_t *name, const wchar_t *val ))
{
debug( 3, L"env_universal_init()" );
path=p;
user=u;
start_fishd=sf;
external_callback = cb;
connection_init( &env_universal_server, -1 );
env_universal_server.fd = -1;
env_universal_server.killme = 0;
env_universal_server.fd = get_socket(1);
memset (&env_universal_server.wstate, '\0', sizeof (mbstate_t));
q_init( &env_universal_server.unsent );
env_universal_common_init( &callback );
sb_init( &env_universal_server.input );
env_universal_read_all();
init = 1;
if( env_universal_server.fd >= 0 )
{
env_universal_barrier();
}
debug( 3, L"end env_universal_init()" );
}
void env_universal_destroy()
@@ -250,12 +254,11 @@ void env_universal_destroy()
{
wperror( L"fcntl" );
}
try_send_all( &env_universal_server );
try_send_all( &env_universal_server );
}
close( env_universal_server.fd );
connection_destroy( &env_universal_server );
env_universal_server.fd =-1;
q_destroy( &env_universal_server.unsent );
sb_destroy( &env_universal_server.input );
env_universal_common_destroy();
init = 0;
}
@@ -269,8 +272,6 @@ int env_universal_read_all()
if( !init)
return 0;
debug( 3, L"env_universal_read_all()" );
if( env_universal_server.fd == -1 )
{
reconnect();
@@ -295,17 +296,19 @@ wchar_t *env_universal_get( const wchar_t *name )
{
if( !init)
return 0;
if( !name )
return 0;
debug( 3, L"env_universal_get( \"%ls\" )", name );
CHECK( name, 0 );
return env_universal_common_get( name );
}
int env_universal_get_export( const wchar_t *name )
{
debug( 3, L"env_universal_get_export()" );
if( !init)
return 0;
CHECK( name, 0 );
return env_universal_common_get_export( name );
}
@@ -349,7 +352,7 @@ void env_universal_barrier()
FD_SET( env_universal_server.fd, &fds );
select( env_universal_server.fd+1, 0, &fds, 0, 0 );
}
/*
Wait for barrier reply
*/
@@ -377,7 +380,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 +400,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 +420,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

@@ -11,7 +11,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
#include <strings.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -21,6 +21,7 @@
#include <sys/stat.h>
#include <dirent.h>
#include <wctype.h>
#include <iconv.h>
#include <errno.h>
#include <locale.h>
@@ -28,6 +29,10 @@
#include <signal.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include "fallback.h"
#include "util.h"
@@ -65,6 +70,21 @@
*/
#define PARSE_ERR L"Unable to parse universal variable message: '%ls'"
/**
ERROR string for internal buffered reader
*/
#define ENV_UNIVERSAL_ERROR 0x100
/**
EAGAIN string for internal buffered reader
*/
#define ENV_UNIVERSAL_AGAIN 0x101
/**
EOF string for internal buffered reader
*/
#define ENV_UNIVERSAL_EOF 0x102
/**
A variable entry. Stores the value of a variable and whether it
should be exported. Obviously, it needs to be allocated large
@@ -106,9 +126,163 @@ static int get_names_show_exported;
static int get_names_show_unexported;
wchar_t *utf2wcs( const char *in )
{
iconv_t cd=(iconv_t) -1;
int i,j;
wchar_t *out;
char *to_name[]=
{
"wchar_t", "WCHAR_T", "wchar", "WCHAR", 0
}
;
char *from_name[]=
{
"utf-8", "UTF-8", "utf8", "UTF8", 0
}
;
size_t in_len = strlen( in );
size_t out_len = sizeof( wchar_t )*(in_len+1);
size_t nconv;
char *nout;
out = malloc( out_len );
nout = (char *)out;
if( !out )
return 0;
for( i=0; to_name[i]; i++ )
{
for( j=0; from_name[j]; j++ )
{
cd = iconv_open ( to_name[i], from_name[j] );
if( cd != (iconv_t) -1)
{
goto start_conversion;
}
}
}
start_conversion:
if (cd == (iconv_t) -1)
{
/* Something went wrong. */
debug( 0, L"Could not perform utf-8 conversion" );
if(errno != EINVAL)
wperror( L"iconv_open" );
/* Terminate the output string. */
free(out);
return 0;
}
nconv = iconv( cd, (char **)&in, &in_len, &nout, &out_len );
if (nconv == (size_t) -1)
{
debug( 0, L"Error while converting from utf string" );
return 0;
}
*((wchar_t *) nout) = L'\0';
if (iconv_close (cd) != 0)
wperror (L"iconv_close");
return out;
}
char *wcs2utf( const wchar_t *in )
{
iconv_t cd=(iconv_t) -1;
int i,j;
char *char_in = (char *)in;
char *out;
char *from_name[]=
{
"wchar_t", "WCHAR_T", "wchar", "WCHAR", 0
}
;
char *to_name[]=
{
"utf-8", "UTF-8", "utf8", "UTF8", 0
}
;
size_t in_len = wcslen( in );
size_t out_len = sizeof( char )*( (MAX_UTF8_BYTES*in_len)+1);
size_t nconv;
char *nout;
out = malloc( out_len );
nout = (char *)out;
in_len *= sizeof( wchar_t );
if( !out )
return 0;
for( i=0; to_name[i]; i++ )
{
for( j=0; from_name[j]; j++ )
{
cd = iconv_open ( to_name[i], from_name[j] );
if( cd != (iconv_t) -1)
{
goto start_conversion;
}
}
}
start_conversion:
if (cd == (iconv_t) -1)
{
/* Something went wrong. */
debug( 0, L"Could not perform utf-8 conversion" );
if(errno != EINVAL)
wperror( L"iconv_open" );
/* Terminate the output string. */
free(out);
return 0;
}
nconv = iconv( cd, &char_in, &in_len, &nout, &out_len );
if (nconv == (size_t) -1)
{
debug( 0, L"%d %d", in_len, out_len );
debug( 0, L"Error while converting from to string" );
return 0;
}
*nout = '\0';
if (iconv_close (cd) != 0)
wperror (L"iconv_close");
return out;
}
void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) )
{
debug( 3, L"Init env_universal_common" );
callback = cb;
hash_init( &env_universal_var, &hash_wcs_func, &hash_wcs_cmp );
}
@@ -116,8 +290,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 );
@@ -130,69 +304,118 @@ void env_universal_common_destroy()
hash_destroy( &env_universal_var );
}
static int read_byte( connection_t *src )
{
if( src->buffer_consumed >= src->buffer_used )
{
int res;
res = read( src->fd, src->buffer, ENV_UNIVERSAL_BUFFER_SIZE );
// debug(4, L"Read chunk '%.*s'", res, src->buffer );
if( res < 0 )
{
if( errno == EAGAIN ||
errno == EINTR )
{
return ENV_UNIVERSAL_AGAIN;
}
return ENV_UNIVERSAL_ERROR;
}
if( res == 0 )
{
return ENV_UNIVERSAL_EOF;
}
src->buffer_consumed = 0;
src->buffer_used = res;
}
return src->buffer[src->buffer_consumed++];
}
void read_message( connection_t *src )
{
while( 1 )
{
char b;
int read_res = read( src->fd, &b, 1 );
wchar_t res=0;
if( read_res < 0 )
int ib = read_byte( src );
char b;
switch( ib )
{
if( errno != EAGAIN &&
errno != EINTR )
case ENV_UNIVERSAL_AGAIN:
{
return;
}
case ENV_UNIVERSAL_ERROR:
{
debug( 2, L"Read error on fd %d, set killme flag", src->fd );
wperror( L"read" );
if( debug_level > 2 )
wperror( L"read" );
src->killme = 1;
return;
}
return;
}
if( read_res == 0 )
{
src->killme = 1;
debug( 3, L"Fd %d has reached eof, set killme flag", src->fd );
if( src->input.used > 0 )
case ENV_UNIVERSAL_EOF:
{
debug( 1,
L"Universal variable connection closed while reading command. Partial command recieved: '%ls'",
(wchar_t *)src->input.buff );
src->killme = 1;
debug( 3, L"Fd %d has reached eof, set killme flag", src->fd );
if( src->input.used > 0 )
{
char c = 0;
b_append( &src->input, &c, 1 );
debug( 1,
L"Universal variable connection closed while reading command. Partial command recieved: '%s'",
(wchar_t *)src->input.buff );
}
return;
}
return;
}
int sz = mbrtowc( &res, &b, 1, &src->wstate );
b = (char)ib;
if( sz == -1 )
{
debug( 1, L"Error while reading universal variable after '%ls'", (wchar_t *)src->input.buff );
wperror( L"mbrtowc" );
}
else if( sz > 0 )
if( b == '\n' )
{
if( res == L'\n' )
wchar_t *msg;
b = 0;
b_append( &src->input, &b, 1 );
msg = utf2wcs( src->input.buff );
/*
Before calling parse_message, we must empty reset
everything, since the callback function could
potentially call read_message.
*/
src->input.used=0;
if( msg )
{
/*
Before calling parse_message, we must empty reset
everything, since the callback function could
potentially call read_message.
*/
wchar_t *msg = wcsdup( (wchar_t *)src->input.buff );
sb_clear( &src->input );
memset (&src->wstate, '\0', sizeof (mbstate_t));
parse_message( msg, src );
free( msg );
}
else
{
sb_append_char( &src->input, res );
debug( 0, _(L"Could not convert message '%s' to wide character string"), src->input.buff );
}
free( msg );
}
else
{
b_append( &src->input, &b, 1 );
}
}
}
@@ -205,8 +428,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 );
}
@@ -232,7 +455,7 @@ static int match( const wchar_t *msg, const wchar_t *cmd )
static void parse_message( wchar_t *msg,
connection_t *src )
{
debug( 3, L"parse_message( %ls );", msg );
// debug( 3, L"parse_message( %ls );", msg );
if( msg[0] == L'#' )
return;
@@ -261,7 +484,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 );
@@ -339,7 +562,16 @@ static int try_send( message_t *msg,
L"before write of %d chars to fd %d", strlen(msg->body), fd );
int res = write( fd, msg->body, strlen(msg->body) );
if( res != -1 )
{
debug( 4, L"Wrote message '%s'", msg->body );
}
else
{
debug( 4, L"Failed to write message '%s'", msg->body );
}
if( res == -1 )
{
switch( errno )
@@ -348,10 +580,11 @@ static int try_send( message_t *msg,
return 0;
default:
debug( 1,
debug( 2,
L"Error while sending universal variable message to fd %d. Closing connection",
fd );
wperror( L"write" );
if( debug_level > 2 )
wperror( L"write" );
return -1;
}
@@ -367,9 +600,9 @@ static int try_send( message_t *msg,
void try_send_all( connection_t *c )
{
debug( 3,
/* debug( 3,
L"Send all updates to connection on fd %d",
c->fd );
c->fd );*/
while( !q_empty( &c->unsent) )
{
switch( try_send( (message_t *)q_peek( &c->unsent), c->fd ) )
@@ -379,7 +612,7 @@ void try_send_all( connection_t *c )
break;
case 0:
debug( 1,
debug( 4,
L"Socket full, send rest later" );
return;
@@ -390,6 +623,33 @@ void try_send_all( connection_t *c )
}
}
static wchar_t *full_escape( const wchar_t *in )
{
string_buffer_t out;
sb_init( &out );
for( ; *in; in++ )
{
if( *in < 32 )
{
sb_printf( &out, L"\\x%.2x", *in );
}
else if( *in < 128 )
{
sb_append_char( &out, *in );
}
else if( *in < 65536 )
{
sb_printf( &out, L"\\u%.4x", *in );
}
else
{
sb_printf( &out, L"\\U%.8x", *in );
}
}
return (wchar_t *)out.buff;
}
message_t *create_message( int type,
const wchar_t *key_in,
const wchar_t *val_in )
@@ -398,10 +658,18 @@ message_t *create_message( int type,
char *key=0;
size_t sz;
// debug( 4, L"Crete message of type %d", type );
if( key_in )
{
key = wcs2str(key_in);
if( wcsvarname( key_in ) )
{
debug( 0, L"Illegal variable name: '%ls'", key_in );
return 0;
}
key = wcs2utf(key_in);
if( !key )
{
debug( 0,
@@ -422,18 +690,18 @@ message_t *create_message( int type,
val_in=L"";
}
wchar_t *esc = escape(val_in,1);
wchar_t *esc = full_escape( val_in );
if( !esc )
break;
char *val = wcs2str(esc );
char *val = wcs2utf(esc );
free(esc);
sz = strlen(type==SET?SET_MBS:SET_EXPORT_MBS) + strlen(key) + strlen(val) + 4;
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 +721,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 +734,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 +744,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;
}
@@ -491,6 +759,9 @@ message_t *create_message( int type,
if( msg )
msg->count=0;
// debug( 4, L"Message body is '%s'", msg->body );
return msg;
}
@@ -498,8 +769,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 +817,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;
@@ -568,3 +839,22 @@ void enqueue_all( connection_t *c )
try_send_all( c );
}
void connection_init( connection_t *c, int fd )
{
memset (c, 0, sizeof (connection_t));
c->fd = fd;
b_init( &c->input );
q_init( &c->unsent );
c->buffer_consumed = c->buffer_used = 0;
}
void connection_destroy( connection_t *c)
{
q_destroy( &c->unsent );
b_destroy( &c->input );
if( close( c->fd ) )
{
wperror( L"close" );
}
}

View File

@@ -49,6 +49,11 @@ enum
}
;
/**
The size of the buffer used for reading from the socket
*/
#define ENV_UNIVERSAL_BUFFER_SIZE 1024
/**
This struct represents a connection between a universal variable server/client
*/
@@ -66,16 +71,28 @@ typedef struct connection
Set to one when this connection should be killed
*/
int killme;
/**
The state used for character conversions
*/
mbstate_t wstate;
/**
The input string. Input from the socket goes here. When a
newline is encountered, the buffer is parsed and cleared.
*/
string_buffer_t input;
buffer_t input;
/**
The read buffer.
*/
char buffer[ENV_UNIVERSAL_BUFFER_SIZE];
/**
Number of bytes that have already been consumed.
*/
int buffer_consumed;
/**
Number of bytes that have been read into the buffer.
*/
int buffer_used;
/**
Link to the next connection
*/
@@ -147,5 +164,8 @@ int env_universal_common_get_export( const wchar_t *name );
*/
void enqueue_all( connection_t *c );
void connection_init( connection_t *c, int fd );
void connection_destroy( connection_t *c);
#endif

View File

@@ -3,13 +3,6 @@
#
# @configure_input@
#
# 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 default field separators
#
@@ -66,6 +59,8 @@ end
# Load additional initialization files
#
for i in fish.d/*.fish
. $i
end
if test -d include
for i in include/*.fish
. $i
end
end

View File

@@ -1,106 +0,0 @@
#
# Initializations that should only be performed when in interactive mode
#
# @configure_input@
if not status --is-interactive
exit
end
#
# Print a greeting
#
printf (_ 'Welcome to fish, the friendly interactive shell\n')
printf (_ 'Type %shelp%s for instructions on how to use fish\n') (set_color green) (set_color normal)
#
# Set exit message
#
function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process %self
printf (_ "Good bye\n")
end
#
# Set INPUTRC to something nice
#
# We override INPUTRC if already set, since it may be set by a shell
# other than fish, which may use a different file. The new value should
# be exported, since the fish inputrc file plays nice with other files
# by including them when found.
# Give priority to the default file installed with fish in
# @SYSCONFDIR@/fish_inputrc.
#
for i in ~/.fish_inputrc @SYSCONFDIR@/fish_inputrc ~/.inputrc /etc/inputrc
if test -f $i
set -xg INPUTRC $i
break
end
end
#
# Set various defaults using these throwaway functions
#
function set_default -d "Set an universal variable, unless it has already been set"
if not set -q $argv[1]
set -U -- $argv
end
if not set -q $argv[1]
set -g -- $argv
end
end
function set_exported_default -d "Set an exported universal variable, unless it has already been set"
if not set -q $argv[1]
set -Ux -- $argv
end
if not set -q $argv[1]
set -gx -- $argv
end
end
# Regular syntax highlighting colors
set_default fish_color_normal normal
set_default fish_color_command green
set_default fish_color_redirection normal
set_default fish_color_comment brown
set_default fish_color_error red
set_default fish_color_cwd green
# Background color for matching quotes and parenthesis
set_default fish_color_match cyan
# Background color for search matches
set_default fish_color_search_match purple
# Pager colors
set_default fish_pager_color_prefix cyan
set_default fish_pager_color_completion normal
set_default fish_pager_color_description normal
set_default fish_pager_color_progress cyan
#
# Directory history colors
#
set_default fish_color_history_current cyan
#
# Setup the CDPATH variable
#
set_default CDPATH . ~
#
# Remove temporary functions for setting default variable values
#
functions -e set_exported_default
functions -e set_default

51
event.c
View File

@@ -3,6 +3,8 @@
Functions for handling event triggers
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
@@ -11,8 +13,6 @@
#include <signal.h>
#include <string.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -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 )
{
@@ -435,7 +444,8 @@ static void event_fire_internal( event_t *event )
for( i=0; i<al_get_count( fire ); i++ )
{
event_t *criterion = (event_t *)al_get( fire, i );
int prev_status;
/*
Check if this event has been removed, if so, dont fire it
*/
@@ -464,14 +474,16 @@ 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);
prev_status = proc_get_last_status();
parser_push_block( EVENT );
current_block->param1.event = event;
eval( (wchar_t *)b->buff, 0, TOP );
parser_pop_block();
proc_pop_interactive();
proc_set_last_status( prev_status );
}
if( b )
@@ -501,6 +513,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;
@@ -524,7 +543,7 @@ static void event_fire_delayed()
free( blocked );
blocked = new_blocked;
}
while( sig_list[active_list].count > 0 )
{
signal_list_t *lst;
@@ -585,7 +604,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 +646,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 +654,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 +663,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 );

374
exec.c
View File

@@ -5,6 +5,8 @@
manual, though I the changes performed have been massive.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
@@ -21,7 +23,9 @@
#include <assert.h>
#include <dirent.h>
#include "config.h"
#ifdef HAVE_SIGINFO_H
#include <siginfo.h>
#endif
#include "fallback.h"
#include "util.h"
@@ -39,7 +43,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"
@@ -65,6 +69,10 @@ pid_t getpgid( pid_t pid );
*/
#define FORK_ERROR _( L"Could not create child process - exiting" )
/**
Base open mode to pass to calls to open
*/
#define BASE_MASK 0666
/**
List of all pipes used by internal pipes. These must be closed in
@@ -75,7 +83,6 @@ static array_list_t *open_fds=0;
static int set_child_group( job_t *j, process_t *p, int print_errors );
void exec_close( int fd )
{
int i;
@@ -86,20 +93,20 @@ 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++ )
{
int n = (int)(long)al_get( open_fds, i );
int n = (int)al_get_long( open_fds, i );
if( n == fd )
{
al_set( open_fds,
i,
al_get( open_fds,
al_get_count( open_fds ) -1 ) );
al_set_long( open_fds,
i,
al_get_long( open_fds, al_get_count( open_fds ) -1 ) );
al_truncate( open_fds,
al_get_count( open_fds ) -1 );
break;
@@ -129,8 +136,8 @@ int exec_pipe( int fd[2])
open_fds = al_halloc( global_context );
}
al_push( open_fds, (void *)(long)fd[0] );
al_push( open_fds, (void *)(long)fd[1] );
al_push_long( open_fds, (long)fd[0] );
al_push_long( open_fds, (long)fd[1] );
return res;
}
@@ -175,7 +182,7 @@ static void close_unused_internal_pipes( io_data_t *io )
{
for( ;i<al_get_count( open_fds ); i++ )
{
int n = (int)(long)al_get( open_fds, i );
int n = (long)al_get_long( open_fds, i );
if( !use_fd_in_pipe( n, io) )
{
debug( 4, L"Close fd %d, used in other context", n );
@@ -260,12 +267,16 @@ 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:
{
if( (tmp=wopen( io->param1.filename,
io->param2.flags, 0777 ) )==-1 )
io->param2.flags, BASE_MASK ) )==-1 )
{
debug( 1,
FILE_ERROR,
@@ -283,8 +294,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 +322,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 +351,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 )
@@ -422,7 +445,9 @@ static void launch_process( process_t *p )
{
// debug( 1, L"exec '%ls'", p->argv[0] );
execve (wcs2str(p->actual_cmd), wcsv2strv( (const wchar_t **) p->argv), env_export_arr( 0 ) );
execve ( wcs2str(p->actual_cmd),
wcsv2strv( (const wchar_t **) p->argv),
env_export_arr( 0 ) );
debug( 0,
_( L"Failed to execute process '%ls'" ),
p->actual_cmd );
@@ -478,7 +503,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;
@@ -506,7 +531,7 @@ static io_data_t *io_transmogrify( io_data_t * in )
{
int fd;
if( (fd=wopen( in->param1.filename, in->param2.flags, 0777 ) )==-1 )
if( (fd=wopen( in->param1.filename, in->param2.flags, BASE_MASK ) )==-1 )
{
debug( 1,
FILE_ERROR,
@@ -557,7 +582,7 @@ static void internal_exec_helper( const wchar_t *def,
*/
if( io && !io_internal )
{
proc_set_last_status( 1 );
proc_set_last_status( STATUS_EXEC_FAIL );
return;
}
@@ -588,23 +613,23 @@ static int set_child_group( job_t *j, process_t *p, int print_errors )
{
int res = 0;
if( j->job_control )
if( job_get_flag( j, JOB_CONTROL ) )
{
int new_pgid=0;
if (!j->pgid)
{
new_pgid=1;
j->pgid = p->pid;
}
if( setpgid (p->pid, j->pgid) )
{
{
if( getpgid( p->pid) != j->pgid && print_errors )
{
debug( 1,
_( L"Could not send process %d from group %d to group %d" ),
p->pid,
_( L"Could not send process %d, '%ls' in job %d, '%ls' from group %d to group %d" ),
p->pid,
p->argv[0],
j->job_id,
j->command,
getpgid( p->pid),
j->pgid );
wperror( L"setpgid" );
@@ -617,7 +642,7 @@ static int set_child_group( job_t *j, process_t *p, int print_errors )
j->pgid = getpid();
}
if( j->terminal && j->fg )
if( job_get_flag( j, JOB_TERMINAL ) && job_get_flag( j, JOB_FOREGROUND ) )
{
if( tcsetpgrp (0, j->pgid) && print_errors )
{
@@ -652,6 +677,13 @@ void exec( job_t *j )
*/
int exec_error=0;
int needs_keepalive = 0;
process_t keepalive;
CHECK( j, );
CHECK_BLOCK();
if( no_exec )
return;
@@ -660,6 +692,32 @@ void exec( job_t *j )
debug( 4, L"Exec job '%ls' with id %d", j->command, j->job_id );
if( block_io )
{
if( j->io )
j->io = io_add( io_duplicate( j, block_io), j->io );
else
j->io=io_duplicate( j, block_io);
}
io_data_t *input_redirect = io_get( j->io, 0 );
if( input_redirect &&
(input_redirect->io_mode == IO_BUFFER) &&
input_redirect->is_input )
{
/*
Input redirection - create a new gobetween process to take
care of buffering
*/
process_t *fake = halloc( j, sizeof(process_t) );
fake->type = INTERNAL_BUFFER;
fake->pipe_fd = 1;
fake->next = j->first_process;
j->first_process = fake;
}
if( j->first_process->type==INTERNAL_EXEC )
{
/*
@@ -668,7 +726,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 ) )
@@ -680,11 +738,11 @@ void exec( job_t *j )
}
else
{
j->constructed=1;
job_set_flag( j, JOB_CONSTRUCTED, 1 );
j->first_process->completed=1;
return;
}
}
pipe_read.fd=0;
@@ -697,20 +755,61 @@ void exec( job_t *j )
pipe_write.next=0;
pipe_write.param1.pipe_fd[0]=pipe_write.param1.pipe_fd[1]=-1;
//fwprintf( stderr, L"Run command %ls\n", j->command );
if( block_io )
{
if( j->io )
j->io = io_add( io_duplicate( j, block_io), j->io );
else
j->io=io_duplicate( j, block_io);
}
//fwprintf( stderr, L"Run command %ls\n", j->command );
j->io = io_add( j->io, &pipe_write );
signal_block();
/*
See if we need to create a group keepalive process. This is a
process that we create to make sure that the process group
doesn't die accidentally, and is needed when a block/function is
inside a pipeline.
*/
if( job_get_flag( j, JOB_CONTROL ) )
{
for( p=j->first_process; p; p = p->next )
{
if( (p->type == INTERNAL_BLOCK ) ||
(p->type == INTERNAL_FUNCTION ) )
{
if( p->next )
{
needs_keepalive = 1;
break;
}
}
}
}
if( needs_keepalive )
{
keepalive.pid = fork();
if( keepalive.pid == 0 )
{
keepalive.pid = getpid();
set_child_group( j, &keepalive, 1 );
pause();
exit(0);
}
else if( keepalive.pid < 0 )
{
/* The fork failed. */
debug( 0, FORK_ERROR );
wperror (L"fork");
exit (1);
}
else
{
set_child_group( j, &keepalive, 0 );
}
}
/*
This loop loops over every process_t in the job, starting it as
appropriate. This turns out to be rather complex, since a
@@ -723,7 +822,7 @@ void exec( job_t *j )
{
mypipe[1]=-1;
skip_fork=0;
pipe_write.fd = p->pipe_fd;
/*
@@ -757,22 +856,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 );
@@ -783,19 +872,27 @@ void exec( job_t *j )
{
case INTERNAL_FUNCTION:
{
const wchar_t * orig_def;
wchar_t * def=0;
signal_unblock();
orig_def = function_get_definition( p->argv[0] );
signal_block();
wchar_t * def = halloc_register( j, wcsdup( function_get_definition( p->argv[0] )));
//fwprintf( stderr, L"run function %ls\n", argv[0] );
if( orig_def )
{
def = halloc_register( j, wcsdup(orig_def) );
}
if( def == 0 )
{
debug( 0, _( L"Unknown function '%ls'" ), p->argv[0] );
break;
}
parser_push_block( FUNCTION_CALL );
current_block->param2.function_call_process = p;
current_block->param1.function_name = halloc_register( current_block, wcsdup( p->argv[0] ) );
current_block->param1.function_call_name = halloc_register( current_block, wcsdup( p->argv[0] ) );
parse_util_set_argv( p->argv+1 );
@@ -803,8 +900,7 @@ void exec( job_t *j )
if( p->next )
{
// fwprintf( stderr, L"Function %ls\n", def );
io_buffer = io_buffer_create();
io_buffer = io_buffer_create( 0 );
j->io = io_add( j->io, io_buffer );
}
@@ -820,8 +916,7 @@ void exec( job_t *j )
{
if( p->next )
{
// fwprintf( stderr, L"Block %ls\n", p->argv[0] );
io_buffer = io_buffer_create();
io_buffer = io_buffer_create( 0 );
j->io = io_add( j->io, io_buffer );
}
@@ -829,7 +924,7 @@ void exec( job_t *j )
break;
}
case INTERNAL_BUILTIN:
{
int builtin_stdin=0;
@@ -848,11 +943,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,13 +953,8 @@ 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 );
in->param2.flags, BASE_MASK );
if( builtin_stdin == -1 )
{
debug( 1,
@@ -907,40 +992,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 = job_get_flag( j, JOB_FOREGROUND );
job_set_flag( j, JOB_FOREGROUND, 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.
*/
job_set_flag( j, JOB_FOREGROUND, 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;
@@ -952,6 +1034,7 @@ void exec( job_t *j )
switch( p->type )
{
case INTERNAL_BLOCK:
case INTERNAL_FUNCTION:
{
@@ -971,7 +1054,7 @@ void exec( job_t *j )
*/
if( p->next == 0 )
{
proc_set_last_status( j->negate?(status?0:1):status);
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status);
}
p->completed = 1;
break;
@@ -1021,7 +1104,7 @@ void exec( job_t *j )
{
if( p->next == 0 )
{
proc_set_last_status( j->negate?(status?0:1):status);
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!status):status);
}
p->completed = 1;
}
@@ -1032,6 +1115,46 @@ void exec( job_t *j )
break;
}
case INTERNAL_BUFFER:
{
pid = fork();
if( pid == 0 )
{
/*
This is the child process. Write out the contents of the pipeline.
*/
p->pid = getpid();
setup_child_process( j, p );
write( 1,
input_redirect->param2.out_buffer->buff,
input_redirect->param2.out_buffer->used );
exit( 0 );
}
else if( pid < 0 )
{
/* The fork failed. */
debug( 0, FORK_ERROR );
wperror (L"fork");
exit (1);
}
else
{
/*
This is the parent process. Store away
information on the child, and possibly give
it control over the terminal.
*/
p->pid = pid;
set_child_group( j, p, 0 );
}
break;
}
case INTERNAL_BUILTIN:
{
@@ -1059,7 +1182,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;
@@ -1073,7 +1195,7 @@ void exec( job_t *j )
{
debug( 3, L"Set status of %ls to %d using short circut", j->command, p->status );
proc_set_last_status( j->negate?(p->status?0:1):p->status );
proc_set_last_status( job_get_flag( j, JOB_NEGATE )?(!p->status):p->status );
}
break;
@@ -1082,9 +1204,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 +1232,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;
@@ -1129,7 +1255,7 @@ void exec( job_t *j )
p->pid = getpid();
setup_child_process( j, p );
launch_process( p );
/*
launch_process _never_ returns...
*/
@@ -1173,8 +1299,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 )
{
@@ -1182,6 +1311,15 @@ void exec( job_t *j )
}
}
/*
The keepalive process is no longer needed, so we terminate it
with extreme prejudice
*/
if( needs_keepalive )
{
kill( keepalive.pid, SIGKILL );
}
signal_unblock();
debug( 3, L"Job is constructed" );
@@ -1191,9 +1329,9 @@ void exec( job_t *j )
for( tmp = block_io; tmp; tmp=tmp->next )
j->io = io_remove( j->io, tmp );
j->constructed = 1;
job_set_flag( j, JOB_CONSTRUCTED, 1 );
if( !j->fg )
if( !job_get_flag( j, JOB_FOREGROUND ) )
{
proc_last_bg_pid = j->pgid;
}
@@ -1219,19 +1357,25 @@ int exec_subshell( const wchar_t *cmd,
debug( 1,
_( L"Sent null command to subshell. This is a fish bug. If it can be reproduced, please send a bug report to %s." ),
PACKAGE_BUGREPORT );
return 0;
return -1;
}
is_subshell=1;
io_buffer= io_buffer_create();
io_buffer= io_buffer_create( 0 );
prev_status = proc_get_last_status();
eval( cmd, io_buffer, SUBST );
if( eval( cmd, io_buffer, SUBST ) )
{
status = -1;
}
else
{
status = proc_get_last_status();
}
io_buffer_read( io_buffer );
status = proc_get_last_status();
proc_set_last_status( prev_status );
is_subshell = prev_subshell;

4
exec.h
View File

@@ -51,8 +51,8 @@ void exec( job_t *j );
\return the status of the last job to exit, or -1 if en error was encountered.
*/
int exec_subshell( const wchar_t *cmd,
array_list_t *l );
__warn_unused int exec_subshell( const wchar_t *cmd,
array_list_t *l );
/**

584
expand.c
View File

@@ -5,6 +5,8 @@ parameter expansion.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
@@ -26,8 +28,6 @@ parameter expansion.
#include <procfs.h>
#endif
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -42,10 +42,31 @@ parameter expansion.
#include "signal.h"
#include "tokenizer.h"
#include "complete.h"
#include "translate.h"
#include "parse_util.h"
#include "halloc.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
*/
@@ -76,27 +97,6 @@ parameter expansion.
*/
#define COMPLETE_LAST_DESC _( L"Last background job")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean {$VARIABLE}? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
/**
String in process expansion denoting ourself
*/
@@ -117,19 +117,13 @@ parameter expansion.
*/
#define UNCLEAN L"$*?\\\"'({})"
/**
Test if the specified argument is clean, i.e. it does not contain
any tokens which need to be expanded or otherwise altered. Clean
strings can be passed through expand_string and expand_one without
changing them. About 90% of all strings are clean, so skipping
expansion on them actually does save a small amount of time, since
it avoids multiple memory allocations during the expansion process.
*/
static int is_clean( const wchar_t *in )
int expand_is_clean( const wchar_t *in )
{
const wchar_t * str = in;
CHECK( in, 1 );
/*
Test characters that have a special meaning in the first character position
*/
@@ -159,32 +153,6 @@ static wchar_t *expand_var( wchar_t *in )
return env_get( in );
}
void expand_variable_array( const wchar_t *val, array_list_t *out )
{
if( val )
{
wchar_t *cpy = wcsdup( val );
wchar_t *pos, *start;
if( !cpy )
{
die_mem();
}
for( start=pos=cpy; *pos; pos++ )
{
if( *pos == ARRAY_SEP )
{
*pos=0;
al_push( out, start==cpy?cpy:wcsdup(start) );
start=pos+1;
}
}
al_push( out, start==cpy?cpy:wcsdup(start) );
}
}
/**
Test if the specified string does not contain character which can
not be used inside a quoted string.
@@ -216,8 +184,10 @@ wchar_t *expand_escape_variable( const wchar_t *in )
array_list_t l;
string_buffer_t buff;
CHECK( in, 0 );
al_init( &l );
expand_variable_array( in, &l );
tokenize_variable_array( in, &l );
sb_init( &buff );
switch( al_get_count( &l) )
@@ -225,7 +195,7 @@ wchar_t *expand_escape_variable( const wchar_t *in )
case 0:
sb_append( &buff, L"''");
break;
case 1:
{
wchar_t *el = (wchar_t *)al_get( &l, 0 );
@@ -281,28 +251,19 @@ wchar_t *expand_escape_variable( const wchar_t *in )
}
/**
Tests if all characters in the string are numeric
*/
static int isnumeric( const char *n )
{
if( *n == '\0' )
return 1;
if( *n < '0' || *n > '9' )
return 0;
return isnumeric( n+1 );
}
/**
Tests if all characters in the wide string are numeric
*/
static int iswnumeric( const wchar_t *n )
{
if( *n == L'\0' )
return 1;
if( *n < L'0' || *n > L'9' )
return 0;
return iswnumeric( n+1 );
for( ; *n; n++ )
{
if( *n < L'0' || *n > L'9' )
{
return 0;
}
}
return 1;
}
/**
@@ -377,9 +338,9 @@ static int find_process( const wchar_t *proc,
array_list_t *out )
{
DIR *dir;
struct dirent *next;
char *pdir_name;
char *pfile_name;
struct wdirent *next;
wchar_t *pdir_name;
wchar_t *pfile_name;
wchar_t *cmd=0;
int sz=0;
int found = 0;
@@ -515,20 +476,20 @@ static int find_process( const wchar_t *proc,
return 1;
}
pdir_name = malloc( 256 );
pfile_name = malloc( 64 );
strcpy( pdir_name, "/proc/" );
while( (next=readdir(dir))!=0 )
pdir_name = malloc( sizeof(wchar_t)*256 );
pfile_name = malloc( sizeof(wchar_t)*64 );
wcscpy( pdir_name, L"/proc/" );
while( (next=wreaddir(dir))!=0 )
{
char *name = next->d_name;
wchar_t *name = next->d_name;
struct stat buf;
if( !isnumeric( name ) )
if( !iswnumeric( name ) )
continue;
strcpy( pdir_name + 6, name );
if( stat( pdir_name, &buf ) )
wcscpy( pdir_name + 6, name );
if( wstat( pdir_name, &buf ) )
{
continue;
}
@@ -536,17 +497,17 @@ static int find_process( const wchar_t *proc,
{
continue;
}
strcpy( pfile_name, pdir_name );
strcat( pfile_name, "/cmdline" );
wcscpy( pfile_name, pdir_name );
wcscat( pfile_name, L"/cmdline" );
if( !stat( pfile_name, &buf ) )
if( !wstat( pfile_name, &buf ) )
{
/*
the 'cmdline' file exists, it should contain the commandline
*/
FILE *cmdfile;
if((cmdfile=fopen( pfile_name, "r" ))==0)
if((cmdfile=wfopen( pfile_name, "r" ))==0)
{
wperror( L"fopen" );
continue;
@@ -561,15 +522,15 @@ static int find_process( const wchar_t *proc,
else
{
#ifdef SunOS
strcpy( pfile_name, pdir_name );
strcat( pfile_name, "/psinfo" );
if( !stat( pfile_name, &buf ) )
wcscpy( pfile_name, pdir_name );
wcscat( pfile_name, L"/psinfo" );
if( !wstat( pfile_name, &buf ) )
{
psinfo_t info;
FILE *psfile;
if((psfile=fopen( pfile_name, "r" ))==0)
if((psfile=wfopen( pfile_name, "r" ))==0)
{
wperror( L"fopen" );
continue;
@@ -608,7 +569,7 @@ static int find_process( const wchar_t *proc,
}
else
{
wchar_t *res = str2wcs(name);
wchar_t *res = wcsdup(name);
if( res )
al_push( out, res );
}
@@ -634,6 +595,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 );
@@ -690,8 +655,8 @@ static int expand_pid( wchar_t *in,
free( in );
else
{
*in = L'%';
al_push( out, in );
free(in);
return 0;
}
}
else
@@ -702,6 +667,132 @@ 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;
}
}
}
static int parse_slice( wchar_t *in, wchar_t **end_ptr, array_list_t *idx )
{
wchar_t *end;
int pos = 1;
// debug( 0, L"parse_slice on '%ls'", in );
while( 1 )
{
long tmp;
while( iswspace(in[pos]) || (in[pos]==INTERNAL_SEPARATOR))
pos++;
if( in[pos] == L']' )
{
pos++;
break;
}
errno=0;
tmp = wcstol( &in[pos], &end, 10 );
if( ( errno ) || ( end == &in[pos] ) )
{
return 1;
}
// debug( 0, L"Push idx %d", tmp );
al_push_long( idx, tmp );
pos = end-in;
}
if( end_ptr )
{
// debug( 0, L"Remainder is '%ls', slice def was %d characters long", in+pos, pos );
*end_ptr = in+pos;
}
// debug( 0, L"ok, done" );
return 0;
}
/**
Expand all environment variables in the string *ptr.
@@ -727,11 +818,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
{
@@ -742,7 +836,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
{
@@ -782,44 +876,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,
in[stop_pos] );
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;
}
@@ -833,71 +891,58 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
int all_vars=1;
array_list_t var_item_list;
al_init( &var_item_list );
if( in[stop_pos] == L'[' )
{
wchar_t *end;
all_vars = 0;
stop_pos++;
while( 1 )
wchar_t *slice_end;
all_vars=0;
if( parse_slice( &in[stop_pos], &slice_end, var_idx_list ) )
{
int tmp;
while( iswspace(in[stop_pos]) || (in[stop_pos]==INTERNAL_SEPARATOR))
stop_pos++;
if( in[stop_pos] == L']' )
{
stop_pos++;
break;
}
errno=0;
tmp = wcstol( &in[stop_pos], &end, 10 );
if( ( errno ) || ( end == &in[stop_pos] ) )
{
error( SYNTAX_ERROR,
-1,
L"Expected integer or \']\'" );
is_ok = 0;
break;
}
al_push( var_idx_list, (void *)tmp );
stop_pos = end-in;
}
}
error( SYNTAX_ERROR,
-1,
L"Invalid index value" );
is_ok = 0;
}
stop_pos = (slice_end-in);
}
if( is_ok )
{
expand_variable_array( var_val, &var_item_list );
tokenize_variable_array( var_val, &var_item_list );
if( !all_vars )
{
int j;
for( j=0; j<al_get_count( var_idx_list ); j++)
{
int tmp = (int)al_get( var_idx_list, j );
long tmp = al_get_long( var_idx_list, j );
if( tmp < 0 )
{
tmp = al_get_count( &var_item_list)+tmp+1;
}
/*
Check that we are within array
bounds. If not, truncate the list to
exit.
*/
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;
}
else
{
/* Move string from list l to list idx */
al_set( var_idx_list, j, al_get( &var_item_list, tmp-1 ) );
al_set( &var_item_list, tmp-1, 0 );
/* Replace each index in var_idx_list inplace with the string value at the specified index */
al_set( var_idx_list, j, wcsdup(al_get( &var_item_list, tmp-1 ) ) );
}
}
/* Free remaining strings in list l and truncate it */
al_foreach( &var_item_list, (void (*)(const void *))&free );
/* Free strings in list var_item_list and truncate it */
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 );
@@ -950,7 +995,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
{
@@ -1046,16 +1091,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;
@@ -1064,9 +1111,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;
@@ -1084,7 +1133,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
{
@@ -1102,9 +1153,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 );
}
}
@@ -1164,29 +1212,24 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
}
/**
Perform subshell expansion
Perform cmdsubst expansion
*/
static int expand_subshell( wchar_t *in, array_list_t *out )
static int expand_cmdsubst( wchar_t *in, array_list_t *out )
{
const wchar_t *paran_begin=0, *paran_end=0;
int len1, len2;
wchar_t *paran_begin=0, *paran_end=0;
int len1;
wchar_t prev=0;
wchar_t *subcmd;
array_list_t sub_res, tail_expand;
array_list_t *sub_res, *tail_expand;
int i, j;
const wchar_t *item_begin;
wchar_t *tail_begin = 0;
void *context;
if( !in )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
CHECK( in, 0 );
CHECK( out, 0 );
if( !out )
{
debug( 2, L"Got null pointer on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
switch( parse_util_locate_cmdsubst(in,
&paran_begin,
@@ -1206,44 +1249,97 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
break;
}
context = halloc( 0, 0 );
len1 = (paran_begin-in);
len2 = wcslen(paran_end)-1;
prev=0;
item_begin = paran_begin+1;
al_init( &sub_res );
if( !(subcmd = malloc( sizeof(wchar_t)*(paran_end-paran_begin) )))
sub_res = al_halloc( context );
if( !(subcmd = halloc( context, sizeof(wchar_t)*(paran_end-paran_begin) )))
{
al_destroy( &sub_res );
halloc_free( context );
return 0;
}
wcslcpy( subcmd, paran_begin+1, paran_end-paran_begin );
subcmd[ paran_end-paran_begin-1]=0;
if( exec_subshell( subcmd, &sub_res)==-1 )
if( exec_subshell( subcmd, sub_res) == -1 )
{
al_foreach( &sub_res, (void (*)(const void *))&free );
al_destroy( &sub_res );
free( subcmd );
halloc_free( context );
error( CMDSUBST_ERROR, -1, L"Unknown error while evaulating command substitution" );
return 0;
}
al_init( &tail_expand );
expand_subshell( wcsdup(paran_end+1), &tail_expand );
tail_begin = paran_end + 1;
if( *tail_begin == L'[' )
{
array_list_t *slice_idx = al_halloc( context );
wchar_t *slice_end;
if( parse_slice( tail_begin, &slice_end, slice_idx ) )
{
halloc_free( context );
error( SYNTAX_ERROR, -1, L"Invalid index value" );
return 0;
}
else
{
array_list_t *sub_res2 = al_halloc( context );
tail_begin = slice_end;
for( i=0; i<al_get_count( slice_idx ); i++ )
{
long idx = al_get_long( slice_idx, i );
if( idx < 0 )
{
idx = al_get_count( sub_res ) + idx + 1;
}
if( idx < 1 || idx > al_get_count( sub_res ) )
{
halloc_free( context );
error( SYNTAX_ERROR, -1, L"Invalid index value" );
return 0;
}
idx = idx-1;
al_push( sub_res2, al_get( sub_res, idx ) );
// debug( 0, L"Pushing item '%ls' with index %d onto sliced result", al_get( sub_res, idx ), idx );
al_set( sub_res, idx, 0 );
}
al_foreach( sub_res, &free );
sub_res = sub_res2;
}
}
for( i=0; i<al_get_count( &sub_res ); i++ )
tail_expand = al_halloc( context );
/*
Recursively call ourselves to expand any remaining command
substitutions. The result of this recursive call usiung the tail
of the string is inserted into the tail_expand array list
*/
expand_cmdsubst( wcsdup(tail_begin), tail_expand );
/*
Combine the result of the current command substitution with the
result of the recursive tail expansion
*/
for( i=0; i<al_get_count( sub_res ); i++ )
{
wchar_t *sub_item, *sub_item2;
sub_item = (wchar_t *)al_get( &sub_res, i );
sub_item = (wchar_t *)al_get( sub_res, i );
sub_item2 = escape( sub_item, 1 );
free(sub_item);
int item_len = wcslen( sub_item2 );
for( j=0; j<al_get_count( &tail_expand ); j++ )
for( j=0; j<al_get_count( tail_expand ); j++ )
{
string_buffer_t whole_item;
wchar_t *tail_item = (wchar_t *)al_get( &tail_expand, j );
wchar_t *tail_item = (wchar_t *)al_get( tail_expand, j );
sb_init( &whole_item );
@@ -1260,16 +1356,14 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
}
free(in);
al_destroy( &sub_res );
al_foreach( &tail_expand, (void (*)(const void *))&free );
al_destroy( &tail_expand );
free( subcmd );
al_foreach( tail_expand, &free );
halloc_free( context );
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 );
@@ -1287,6 +1381,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;
@@ -1361,6 +1457,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;
@@ -1371,12 +1469,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 )
{
@@ -1403,7 +1503,6 @@ static void remove_internal_separator( const void *s, int conv )
*out=0;
}
/**
The real expansion function. expand_one is just a wrapper around this one.
*/
@@ -1416,13 +1515,14 @@ int expand_string( void *context,
array_list_t *in, *out;
int i;
int subshell_ok = 1;
int cmdsubst_ok = 1;
int res = EXPAND_OK;
int start_count = al_get_count( end_out );
// debug( 1, L"Expand %ls", str );
CHECK( str, EXPAND_ERROR );
CHECK( end_out, EXPAND_ERROR );
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( str ) )
{
halloc_register( context, str );
al_push( end_out, str );
@@ -1432,16 +1532,16 @@ int expand_string( void *context,
al_init( &list1 );
al_init( &list2 );
if( EXPAND_SKIP_SUBSHELL & flags )
if( EXPAND_SKIP_CMDSUBST & flags )
{
const wchar_t *begin, *end;
wchar_t *begin, *end;
if( parse_util_locate_cmdsubst( str,
&begin,
&end,
1 ) != 0 )
{
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
error( CMDSUBST_ERROR, -1, L"Command substitutions not allowed" );
free( str );
al_destroy( &list1 );
al_destroy( &list2 );
@@ -1451,10 +1551,10 @@ int expand_string( void *context,
}
else
{
subshell_ok = expand_subshell( str, &list1 );
cmdsubst_ok = expand_cmdsubst( str, &list1 );
}
if( !subshell_ok )
if( !cmdsubst_ok )
{
al_destroy( &list1 );
return EXPAND_ERROR;
@@ -1668,7 +1768,9 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
int res;
wchar_t *one;
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( string ) )
CHECK( string, 0 );
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string ) )
{
halloc_register( context, string );
return string;
@@ -1693,7 +1795,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

@@ -20,9 +20,9 @@
#include "util.h"
/**
Flag specifying that subshell expansion should be skipped
Flag specifying that cmdsubst expansion should be skipped
*/
#define EXPAND_SKIP_SUBSHELL 1
#define EXPAND_SKIP_CMDSUBST 1
/**
Flag specifying that variable expansion should be skipped
@@ -112,39 +112,54 @@ enum
/** String containing the character for separating two array elements */
#define ARRAY_SEP_STR L"\x1e"
/**
Error issued on array out of bounds
*/
#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),
subshell expansion and wildcard expansion. The results are inserted
(\~USER becomes the users home directory), variable expansion
(\$VAR_NAME becomes the value of the environment variable VAR_NAME),
cmdsubst 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 flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_CMDSUBST 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 );
__warn_unused int expand_string( void *context, wchar_t *in, array_list_t *out, int flag );
/**
expand_one is identical to expand_string, except it will fail if in
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
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
\return The expanded parameter, or 0 on failiure
*/
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 );
@@ -153,18 +168,36 @@ 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);
/**
Tokenize the specified string into the specified array_list_t.
Each new element is allocated using malloc and must be freed by the
caller.
\param val the input string. The contents of this string is not changed.
\param out the list in which to place the elements.
Test if the specified argument is clean, i.e. it does not contain
any tokens which need to be expanded or otherwise altered. Clean
strings can be passed through expand_string and expand_one without
changing them. About two thirds of all strings are clean, so
skipping expansion on them actually does save a small amount of
time, since it avoids multiple memory allocations during the
expansion process.
\param in the string to test
*/
void expand_variable_array( const wchar_t *val, array_list_t *out );
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"
@@ -21,6 +25,7 @@
#include <dirent.h>
#include <stdarg.h>
#include <limits.h>
#include <assert.h>
#if HAVE_NCURSES_H
#include <ncurses.h>
@@ -65,7 +70,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;
@@ -997,11 +1006,88 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
#endif
#ifdef HAVE_BROKEN_DEL_CURTERM
#ifndef HAVE_LRAND48_R
int del_curterm(TERMINAL *oterm)
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
#ifndef HAVE_KILLPG
int killpg( int pgr, int sig )
{
assert( pgr > 1 );
return kill( -pgr, sig );
}
#endif
#ifndef HAVE_WORKING_GETOPT_LONG
int getopt_long( int argc,
char * const argv[],
const char *optstring,
const struct option *longopts,
int *longindex )
{
return getopt( argc, argv, optstring );
}
#endif

View File

@@ -8,6 +8,9 @@
#include <wctype.h>
#include <wchar.h>
#include <limits.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#ifndef WCHAR_MAX
/**
@@ -16,6 +19,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
@@ -29,6 +45,24 @@ typedef int tputs_arg_t;
typedef char tputs_arg_t;
#endif
#ifndef SIGIO
#define SIGIO SIGUSR1
#endif
#ifndef SIGWINCH
#define SIGWINCH SIGUSR2
#endif
#ifndef HAVE_WINSIZE
struct winsize
{
unsigned short ws_row;
unsigned short ws_col;
}
;
#endif
#ifdef TPUTS_KLUDGE
/**
@@ -276,7 +310,118 @@ size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
/**
BSD del_curterm seems to do a double-free. We redefine it as a no-op
*/
int del_curterm(TERMINAL *oterm);
#define del_curterm(oterm) OK
#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
#ifndef HAVE_KILLPG
int killpg( int pgr, int sig );
#endif
#ifndef HAVE_WORKING_GETOPT_LONG
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
}
;
#ifndef no_argument
#define no_argument 0
#endif
#ifndef required_argument
#define required_argument 1
#endif
#ifndef optional_argument
#define optional_argument 2
#endif
int getopt_long(int argc,
char * const argv[],
const char *optstring,
const struct option *longopts,
int *longindex);
#endif
#endif

View File

@@ -1,5 +1,3 @@
%define xinclude %( if test -d /usr/X11R6/include; then echo /usr/X11R6/include; else echo /usr/include; fi )
Summary: A friendly interactive shell
Name: @PACKAGE_NAME@
@@ -8,25 +6,57 @@ Release: 0%{?dist}
License: GPL
Group: System Environment/Shells
URL: http://roo.no-ip.org/fish/
URL: http://www.fishshell.org
Source0: http://roo.no-ip.org/%{name}/files/%{version}/%{name}-%{version}.tar.bz2
Source0: http://www.fishshell.org/files/%{version}/%{name}-%{version}.tar.bz2
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: doxygen ncurses-devel
BuildRequires: %{xinclude}/X11/StringDefs.h, %{xinclude}/X11/Xlib.h
BuildRequires: %{xinclude}/X11/Intrinsic.h, %{xinclude}/X11/Xatom.h
BuildRequires: ncurses-devel gettext groff
# Locate correct build time-dependencies for providing X headers
%if "%fedora" >= "5"
# Modern Fedora version, has modular X.org
BuildRequires: xorg-x11-proto-devel libX11-devel libXt-devel libXext-devel
%endif
%if "%fedora" < "5"
%if "%fedora" >= "3"
# Semi-old Fedora version, has non-modular X.org
BuildRequires: xorg-x11-devel
%endif
%endif
%if 0%{?fedora}
%if "%fedora" < "3"
# Ancient Fedora version, has XFree86
BuildRequires: XFree86-devel
%endif
%else
# The %fedora variable has not been correctly defined, or this is is
# not a Fedora system, try guessing BuildRequires by looking at the
# directory structure
%define xinclude /usr%(if [ -d /usr/X11R6/include ]; then echo /X11R6; fi)/include
BuildRequires: %{xinclude}/X11/StringDefs.h, %{xinclude}/X11/Xlib.h
BuildRequires: %{xinclude}/X11/Intrinsic.h, %{xinclude}/X11/Xatom.h
%endif
%description
fish is a shell geared towards interactive use. It's features are
focused on user friendlieness and discoverability. The language syntax
fish is a shell geared towards interactive use. Its features are
focused on user friendliness and discoverability. The language syntax
is simple but incompatible with other shell languages.
%prep
%setup -q
@@ -34,6 +64,9 @@ is simple but incompatible with other shell languages.
%build
# The docdir argument is to make the name of the cosumantation
# directory 'fish-VERSION', instead of the default, which is simply
# 'fish'.
%configure docdir=%_datadir/doc/%{name}-%{version}
make %{?_smp_mflags}
@@ -44,6 +77,8 @@ make %{?_smp_mflags}
rm -rf $RPM_BUILD_ROOT
make install DESTDIR="$RPM_BUILD_ROOT"
# Find translation files
%find_lang %{name}.\*
@@ -54,6 +89,7 @@ rm -rf $RPM_BUILD_ROOT
%post
# Add fish to the list of allowed shells in /etc/shells
if ! grep %_bindir/fish %_sysconfdir/shells >/dev/null; then
echo %_bindir/fish >>%_sysconfdir/shells
fi
@@ -62,6 +98,7 @@ fi
%postun
# Remove fish from the list of allowed shells in /etc/shells
if [ "$1" = 0 ]; then
grep -v %_bindir/fish %_sysconfdir/shells >%_sysconfdir/fish.tmp
mv %_sysconfdir/fish.tmp %_sysconfdir/shells
@@ -70,11 +107,14 @@ fi
%files
%files -f %{name}.\*.lang
%defattr(-,root,root,-)
# The documentation directory
%doc %_datadir/doc/%{name}-%{version}
# man files
%_mandir/man1/fish.1*
%_mandir/man1/xsel.1x*
%_mandir/man1/mimedb.1*
@@ -83,6 +123,7 @@ fi
%_mandir/man1/fishd.1*
%_mandir/man1/fish_pager.1*
# The program binaries
%attr(0755,root,root) %_bindir/fish
%attr(0755,root,root) %_bindir/fishd
%attr(0755,root,root) %_bindir/fish_pager
@@ -91,26 +132,44 @@ fi
%attr(0755,root,root) %_bindir/mimedb
%attr(0755,root,root) %_bindir/count
%config %_sysconfdir/fish
%config %_sysconfdir/fish_inputrc
%dir %_sysconfdir/fish.d
%config %_sysconfdir/fish.d/fish_*.fish
# Configuration files
%config %_sysconfdir/fish/config.fish
%config %_sysconfdir/fish/fish_inputrc
%dir %_sysconfdir/fish
# Non-configuration initialization files
%dir %_datadir/fish
%_datadir/fish/fish
%_datadir/fish/config.fish
%_datadir/fish/config_interactive.fish
# Program specific tab-completions
%dir %_datadir/fish/completions
%_datadir/fish/completions/*.fish
# Dynamically loaded shellscript functions
%dir %_datadir/fish/functions
%_datadir/fish/functions/*.fish
%_datadir/locale/*/LC_MESSAGES/fish.mo
%changelog
* Sat Oct 14 2006 Axel Liljencrantz<axel@liljencrantz.se> 1.22.0-0
- Update names of various configuration files
* Fri Aug 4 2006 Axel Liljencrantz<axel@liljencrantz.se> 1.21.10-4
- Add better translation finding code from fedora spec to main spec. Thank you to Michael Schwendt.
- Add missing dependency libXext-devel.
- Remove one nesting level from dependency checking code.
* Tue Aug 1 2006 Axel Liljencrantz<axel@liljencrantz.se> 1.21.10-1
- Improved the dependency check for X headers. Thank you to Michael Schwendt for pointers on how to do this
* Mon Jul 31 2006 Axel Liljencrantz<axel@liljencrantz.se> 1.21.10-1
- Fixed spelling and punctuation as a per patch from Paul Howarth
- Fixed dependencies as per patch from Paul Howarth
* Tue Nov 29 2005 Axel Liljencrantz <axel@liljencrantz.se> 1.17.0-0
- 1.17.0

View File

@@ -9,7 +9,14 @@
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_SYS_TERMIOS_H
#include <sys/termios.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include <sys/time.h>
#include <sys/wait.h>
#include <dirent.h>
@@ -67,6 +74,33 @@ enum
}
;
enum
{
/*
Returnd by the pager if no more displaying is needed
*/
PAGER_DONE,
/*
Returned by the pager if the completions would not fit in the specified number of columns
*/
PAGER_RETRY,
/*
Returned by the pager if the terminal changes size
*/
PAGER_RESIZE
}
;
/**
The minimum number of columns the terminal may have for fish_pager to not refuse showing the completions
*/
#define PAGER_MIN_WIDTH 16
/**
The maximum number of columns of completion to attempt to fit onto the screen
*/
#define PAGER_MAX_COLS 6
/**
This struct should be continually updated by signals as the term
resizes, and as such always contain the correct current size.
@@ -74,11 +108,23 @@ enum
static struct winsize termsize;
/**
The termios modes the terminal had when the program started. These
should be restored on exit
*/
static struct termios saved_modes;
static struct termios pager_modes;
/**
This flag is set to 1 of we have sent the enter_ca_mode terminfo
sequence to save the previous terminal contents.
*/
static int is_ca_mode = 0;
/**
This buffer_t is used to buffer the output of the pager to improve
screen redraw performance bu cutting down the number of write()
calls to only one.
*/
static buffer_t *pager_buffer;
/**
@@ -94,30 +140,68 @@ static wchar_t *hightlight_var[] =
}
;
/**
This string_buffer_t contains the text that should be sent back to the calling program
*/
static string_buffer_t out_buff;
/**
This is the file to which the output text should be sent. It is really a pipe.
*/
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;
/**
This function translates from a highlight code to a specific color
by check invironement variables
*/
static int get_color( int highlight )
{
wchar_t *val;
if( highlight < 0 )
return FISH_COLOR_NORMAL;
if( highlight >= (4) )
return FISH_COLOR_NORMAL;
wchar_t *val = env_universal_get( hightlight_var[highlight]);
val = wgetenv( hightlight_var[highlight]);
if( !val )
{
val = env_universal_get( hightlight_var[highlight]);
}
if( val == 0 )
if( !val )
{
return FISH_COLOR_NORMAL;
}
@@ -125,6 +209,12 @@ static int get_color( int highlight )
return output_color_code( val );
}
/**
This function calculates the minimum width for each completion
entry in the specified array_list. This width depends on the
terminal size, so this function should be called when the terminal
changes size.
*/
static void recalc_width( array_list_t *l, const wchar_t *prefix )
{
int i;
@@ -138,6 +228,10 @@ static void recalc_width( array_list_t *l, const wchar_t *prefix )
}
/**
Test if the specified character sequence has been entered on the
keyboard
*/
static int try_sequence( char *seq )
{
int j, k;
@@ -161,6 +255,9 @@ static int try_sequence( char *seq )
return 0;
}
/**
Read a character from keyboard
*/
static wint_t readch()
{
struct mapping
@@ -220,26 +317,39 @@ static wint_t readch()
return input_common_readch(0);
}
/**
Write specified character to the output buffer \c pager_buffer
*/
static int pager_buffered_writer( char c)
{
b_append( pager_buffer, &c, 1 );
return 0;
}
/**
Flush \c pager_buffer to stdout
*/
static void pager_flush()
{
write( 1, pager_buffer->buff, pager_buffer->used );
pager_buffer->used = 0;
}
/**
Print the specified string, but use at most the specified amount of
space. If the whole string can't be fitted, ellipsize it.
\param str the string to print
\param max the maximum space that may be used for printing
\param has_more if this flag is true, this is not the entire string, and the string should be ellisiszed even if the string fits but takes up the whole space.
*/
static int print_max( const wchar_t *str, int max, int has_more )
{
int i;
int written = 0;
for( i=0; str[i]; i++ )
{
if( written + wcwidth(str[i]) > max )
break;
if( ( written + wcwidth(str[i]) == max) && (has_more || str[i+1]) )
@@ -255,6 +365,9 @@ static int print_max( const wchar_t *str, int max, int has_more )
return written;
}
/**
Print the specified item using at the specified amount of space
*/
static void completion_print_item( const wchar_t *prefix, comp_t *c, int width )
{
int comp_width=0, desc_width=0;
@@ -388,7 +501,7 @@ static void completion_print( int cols,
\param is_quoted whether the completions should be quoted
\param l the list of completions
\return zero if the specified number of columns do not fit, no-zero otherwise
\return one of PAGER_RETRY, PAGER_DONE and PAGER_RESIZE
*/
static int completion_try_print( int cols,
@@ -399,11 +512,11 @@ static int completion_try_print( int cols,
/*
The calculated preferred width of each column
*/
int pref_width[32];
int pref_width[PAGER_MAX_COLS];
/*
The calculated minimum width of each column
*/
int min_width[32];
int min_width[PAGER_MAX_COLS];
/*
If the list can be printed with this width, width will contain the width of each column
*/
@@ -419,13 +532,13 @@ static int completion_try_print( int cols,
int pref_tot_width=0;
int min_tot_width = 0;
int res=0;
int res=PAGER_RETRY;
/*
Skip completions on tiny terminals
*/
if( termsize.ws_col < 16 )
return 1;
if( termsize.ws_col < PAGER_MIN_WIDTH )
return PAGER_DONE;
memset( pref_width, 0, sizeof(pref_width) );
memset( min_width, 0, sizeof(min_width) );
@@ -510,11 +623,9 @@ static int completion_try_print( int cols,
}
}
// return cols==1;
if( print )
{
res=1;
res=PAGER_DONE;
if( rows < termsize.ws_row )
{
/* List fits on screen. Print it and leave */
@@ -548,15 +659,19 @@ static int completion_try_print( int cols,
*/
while(do_loop)
{
wchar_t msg[10];
int percent = 100*pos/(rows-termsize.ws_row+1);
string_buffer_t msg;
sb_init( &msg );
set_color( FISH_COLOR_BLACK,
get_color(HIGHLIGHT_PAGER_PROGRESS) );
swprintf( msg, 12,
L" %ls(%d%%) \r",
percent==100?L"":(percent >=10?L" ": L" "),
percent );
writestr(msg);
sb_printf( &msg,
_(L" %d to %d of %d \r"),
pos,
pos+termsize.ws_row-1,
rows );
writestr((wchar_t *)msg.buff);
sb_destroy( &msg );
set_color( FISH_COLOR_NORMAL, FISH_COLOR_NORMAL );
pager_flush();
int c = readch();
@@ -654,7 +769,7 @@ static int completion_try_print( int cols,
case R_NULL:
{
do_loop=0;
res=2;
res=PAGER_RESIZE;
break;
}
@@ -719,7 +834,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 +876,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 ) );
}
}
@@ -844,15 +958,28 @@ static void handle_winch( int sig )
}
}
/**
The callback function that the keyboard reading function calls when
an interrupt occurs. This makes sure that R_NULL is returned at
once when an interrupt has occured.
*/
static int interrupt_handler()
{
return R_NULL;
}
/**
Initialize various subsystems. This also closes stdin and replaces
it with a copy of stderr, so the reading of completion strings must
be done before init is called.
*/
static void init()
{
struct sigaction act;
static struct termios pager_modes;
program_name = L"fish_pager";
wsetlocale( LC_ALL, L"" );
@@ -861,14 +988,28 @@ static void init()
the resulting output back to the caller
*/
int out = dup( 1 );
int in = dup( 0 );
close(1);
if( open( ttyname(0), O_WRONLY ) != 1 )
close(0);
if( (in = open( ttyname(2), O_RDWR )) != -1 )
{
if( dup2( 2, 1 ) == -1 )
{
debug( 0, L"Could not set up file descriptors for pager" );
debug( 0, _(L"Could not set up output file descriptors for pager") );
exit( 1 );
}
if( dup2( in, 0 ) == -1 )
{
debug( 0, _(L"Could not set up input file descriptors for pager %d"), in );
exit( 1 );
}
}
else
{
debug( 0, _(L"Could not open tty for pager") );
exit( 1 );
}
out_file = fdopen( out, "w" );
@@ -877,13 +1018,12 @@ static void init()
*/
sb_init( &out_buff );
halloc_util_init();
env_universal_init( 0, 0, 0, 0);
input_common_init( &interrupt_handler );
output_set_writer( &pager_buffered_writer );
pager_buffer = halloc( global_context, sizeof( buffer_t ) );
halloc_register_function( global_context, (void (*)(void *))&b_destroy, pager_buffer );
sigemptyset( & act.sa_mask );
act.sa_flags=0;
act.sa_handler=SIG_DFL;
@@ -896,7 +1036,7 @@ static void init()
}
handle_winch( 0 ); /* Set handler for window change events */
tcgetattr(0,&pager_modes); /* get the current terminal modes */
memcpy( &saved_modes,
&pager_modes,
@@ -918,81 +1058,177 @@ static void init()
if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
{
debug( 0, L"Could not set up terminal" );
debug( 0, _(L"Could not set up terminal") );
exit(1);
}
}
void destroy()
/**
Free memory used by various subsystems.
*/
static void destroy()
{
env_universal_destroy();
input_common_destroy();
halloc_util_destroy();
del_curterm( cur_term );
wutil_destroy();
if( del_curterm( cur_term ) == ERR )
{
debug( 0, _(L"Error while closing terminfo") );
}
sb_destroy( &out_buff );
fclose( out_file );
}
/**
Read lines of input from the specified file, unescape them and
insert them into the specified list.
*/
static void read_array( FILE* file, array_list_t *comp )
{
buffer_t buffer;
int c;
char cc;
wchar_t *wcs, *unescaped;
b_init( &buffer );
while( !feof( file ) )
{
buffer.used=0;
while( 1 )
{
c = getc( file );
if( c == EOF )
{
break;
}
if( c == '\n' )
{
break;
}
cc=c;
b_append( &buffer, &cc, 1 );
}
if( buffer.used )
{
cc=0;
b_append( &buffer, &cc, 1 );
wcs = str2wcs( buffer.buff );
if( wcs )
{
unescaped = unescape( wcs, 0 );
al_push( comp, unescaped );
free( wcs );
}
}
}
b_destroy( &buffer );
}
int main( int argc, char **argv )
{
int i;
int is_quoted=0;
array_list_t *comp;
wchar_t *prefix;
init();
/*
This initialization is made early, so that the other init code
can use global_context for memory managment
*/
halloc_util_init();
if( argc < 3 )
{
debug( 0, L"Insufficient arguments" );
debug( 0, _(L"Insufficient arguments") );
}
else
{
comp = al_halloc( global_context );
prefix = str2wcs( argv[2] );
is_quoted = strcmp( "1", argv[1] )==0;
is_quoted = 0;
debug( 3, L"prefix is '%ls'", prefix );
// debug( 3, L"prefix is '%ls'", prefix );
for( i=3; i<argc; i++ )
if( argc > 3 )
{
wchar_t *wcs = str2wcs( argv[i] );
if( wcs )
for( i=3; i<argc; i++ )
{
al_push( comp, wcs );
wchar_t *wcs = str2wcs( argv[i] );
if( wcs )
{
al_push( comp, wcs );
}
}
}
mangle_descriptions( comp );
if( wcscmp( prefix, L"-" ) == 0 )
else
{
read_array( stdin, comp );
}
init();
mangle_descriptions( comp );
if( wcscmp( prefix, L"-" ) == 0 )
join_completions( comp );
mangle_completions( comp, prefix );
for( i = 6; i>0; i-- )
mangle_completions( comp, prefix );
/**
Try to print the completions. Start by trying to print the
list in PAGER_MAX_COLS columns, if the completions won't
fit, reduce the number of columns by one. Printing a single
column never fails.
*/
for( i = PAGER_MAX_COLS; i>0; i-- )
{
switch( completion_try_print( i, prefix, is_quoted, comp ) )
{
case 0:
case PAGER_RETRY:
break;
case 1:
case PAGER_DONE:
i=0;
break;
case 2:
i=7;
case PAGER_RESIZE:
/*
This means we got a resize event, so we start
over from the beginning. Since it the screen got
bigger, we might be able to fit all completions
on-screen.
*/
i=PAGER_MAX_COLS+1;
break;
}
}
}
free(prefix );
fwprintf( out_file, L"%ls", (wchar_t *)out_buff.buff );
if( is_ca_mode )
{
writembs(exit_ca_mode);
pager_flush();
}
}
destroy();
}

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
*/
@@ -83,14 +88,6 @@ static void err( wchar_t *blah, ... )
wprintf( L"\n" );
}
/**
Print ok message
*/
static void ok()
{
wprintf( L"OK\n" );
}
/**
Compare two pointers
*/
@@ -115,7 +112,7 @@ static void pq_test( int elements )
for( i=0; i<elements; i++ )
{
int foo = rand() % 100;
long foo = rand() % 100;
// printf( "Adding %d\n", foo );
pq_put( &q, (void *)foo );
count[foo]++;
@@ -125,7 +122,7 @@ static void pq_test( int elements )
for( i=0; i<elements; i++ )
{
int pos = (int)pq_get( &q );
long pos = (long)pq_get( &q );
count[ pos ]--;
if( pos > prev )
err( L"Wrong order of elements in priority_queue_t" );
@@ -147,7 +144,7 @@ static void pq_test( int elements )
*/
static int stack_test( int elements )
{
int i;
long i;
int res=1;
@@ -157,12 +154,12 @@ static int stack_test( int elements )
for( i=0; i<elements; i++ )
{
int foo;
long foo;
al_push( &s, (void*)i);
al_push( &s, (void*)i);
al_push_long( &s, i);
al_push_long( &s, i);
if( (foo=(int)al_pop( &s )) != i )
if( (foo=al_pop_long( &s )) != i )
{
err( L"Unexpected data" );
res = 0;
@@ -172,16 +169,14 @@ static int stack_test( int elements )
for( i=0; i<elements; i++ )
{
int foo;
long foo;
if( (foo=(int)al_pop( &s )) != (elements-i-1) )
if( (foo=al_pop_long( &s )) != (elements-i-1) )
{
err( L"Unexpected data" );
res = 0;
break;
}
}
}
@@ -193,19 +188,19 @@ 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();
*/
int foo = (int)data;
int foo = (int)(long)data;
return 127*((foo^0xefc7e214)) ^(foo<<11);
}
/**
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;
}
@@ -214,9 +209,9 @@ static int compare_func( const void *key1, const void *key2 )
/**
Hashtable test
*/
static int hash_test( int elements )
static int hash_test( long elements )
{
int i;
long i;
int res=1;
hash_table_t h;
@@ -225,17 +220,17 @@ static int hash_test( int elements )
for( i=1; i< elements+1; i++ )
{
hash_put( &h, (void*)i, (void*)100-i );
hash_put( &h, (void*)i, (void*)100l-i );
}
for( i=1; i< elements+1; i++ )
{
if( (int)hash_get( &h, (void*)i ) != (100-i) )
if( (long)hash_get( &h, (void*)i ) != (100l-i) )
{
err( L"Key %d gave data %d, expected data %d",
i,
(int)hash_get( &h, (void*)i ),
100-i );
(long)hash_get( &h, (void*)i ),
100l-i );
res = 0;
break;
@@ -268,7 +263,7 @@ static int hash_test( int elements )
for( i=1; i<elements+1; i++ )
{
if( hash_contains( &h, (void*)i) != (i+1)%2 )
if( hash_contains( &h, (void*)i) != (i+1l)%2l )
{
if( i%2 )
err( L"Key %d remains, should be deleted",
@@ -292,22 +287,22 @@ static int hash_test( int elements )
*/
static void al_test( int sz)
{
int i;
long i;
array_list_t l;
al_init( &l );
al_set( &l, 1, (void *)7 );
al_set( &l, sz, (void *)7 );
al_set_long( &l, 1, 7L );
al_set_long( &l, sz, 7L );
if( al_get_count( &l ) != maxf( sz+1, 2 ) )
if( al_get_count( &l ) != maxi( sz+1, 2 ) )
err( L"Wrong number of elements in array list" );
for( i=0; i<al_get_count( &l ); i++ )
{
int val = (int)((long) al_get( &l, i ));
long val = al_get_long( &l, i );
if( (i == 1) || (i==sz))
{
if( val != 7 )
@@ -345,8 +340,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 +476,43 @@ static void test_parser()
say( L"Testing null input to parser" );
if( !parser_test( 0, 0 ) )
if( !parser_test( 0, 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, 0 ) )
{
err( L"Incomplete if statement undetected" );
}
if( !parser_test( L"if test; echo", 0 ) )
if( !parser_test( L"if test; echo", 0, 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, 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, 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, 0 ) )
{
err( L"'case' command outside of switch block context undetected" );
}
if( !parser_test( L"else", 0 ) )
if( !parser_test( L"else", 0, 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, 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, 0 ) || !parser_test( L"echo|return", 0, 0, 0 ))
{
err( L"Invalid pipe command undetected" );
}
@@ -552,7 +545,11 @@ static int expand_test( const wchar_t *in, int flags, ... )
wchar_t *arg;
al_init( &out );
expand_string( 0, wcsdup(in), &out, flags);
if( expand_string( 0, wcsdup(in), &out, flags) )
{
}
va_start( va, flags );
@@ -574,7 +571,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 +636,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 +658,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 +690,6 @@ int main( int argc, char **argv )
parser_init();
function_init();
builtin_init();
complete_init();
reader_init();
env_init();
@@ -715,7 +711,6 @@ int main( int argc, char **argv )
parser_destroy();
function_destroy();
builtin_destroy();
complete_destroy();
wutil_destroy();
event_destroy();
proc_destroy();

188
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:
@@ -17,10 +17,12 @@ set_export KEY:VALUE
These commands update the value of a variable. The only difference
between the two is that <tt>set_export</tt>-variables should be
exported to children of the process using them. The variable value may
be escaped using C-style backslash escapes. In fact, this is required
for newline characters, which would otherwise be interpreted as end of
command.
exported to children of the process using them. When sending messages,
all values below 32 or above 127 must be escaped using C-style
backslash escapes. This means that the over the wire protocol is
ASCII. However, any conforming reader must also accept non-ascii
characters and interpret them as UTF-8. Lines containing invalid UTF-8
escape sequences must be ignored entirely.
<pre>erase KEY
</pre>
@@ -68,6 +70,9 @@ time the original barrier request was sent have been received.
#include "common.h"
#include "wutil.h"
#include "env_universal_common.h"
#include "halloc.h"
#include "halloc_util.h"
#include "path.h"
/**
Maximum length of socket filename
@@ -88,12 +93,17 @@ 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.
*/
#define FILE ".fishd."
#define FILE "fishd."
/**
Maximum length of hostname. Longer hostnames are truncated
@@ -110,6 +120,11 @@ time the original barrier request was sent have been received.
*/
#define LOCKTIMEOUT 1
/**
Getopt short switches for fishd
*/
#define GETOPT_STRING "hv"
/**
The list of connections to clients
*/
@@ -225,7 +240,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 );
@@ -273,7 +288,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
*/
@@ -376,23 +391,108 @@ static void daemonize()
}
/**
Get environment variable value. The resulting string needs to be free'd.
*/
static wchar_t *fishd_env_get( wchar_t *key )
{
char *nres, *nkey;
wchar_t *res;
nkey = wcs2str( key );
nres = getenv( nkey );
free( nkey );
if( nres )
{
return str2wcs( nres );
}
else
{
res = env_universal_common_get( key );
if( res )
res = wcsdup( res );
return env_universal_common_get( key );
}
}
/**
Get the configuration directory. The resulting string needs to be
free'd. This is mostly the same code as path_get_config(), but had
to be rewritten to avoid dragging in additional library
dependencies.
*/
static wchar_t *fishd_get_config()
{
wchar_t *xdg_dir, *home;
int done = 0;
wchar_t *res = 0;
xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" );
if( xdg_dir )
{
res = wcsdupcat( xdg_dir, L"/fish" );
if( !create_directory( res ) )
{
done = 1;
}
else
{
free( res );
}
free( xdg_dir );
}
else
{
home = fishd_env_get( L"HOME" );
if( home )
{
res = wcsdupcat( home, L"/.config/fish" );
if( !create_directory( res ) )
{
done = 1;
}
else
{
free( res );
}
free( home );
}
}
if( done )
{
return res;
}
else
{
debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
return 0;
}
}
/**
Load or save all variables
*/
void load_or_save( int save)
static void load_or_save( int save)
{
struct passwd *pw;
char *name;
char *dir = getenv( "HOME" );
wchar_t *wdir = fishd_get_config();
char *dir;
char hostname[HOSTNAME_LEN];
connection_t c;
int fd;
if( !dir )
if( !wdir )
{
pw = getpwuid( getuid() );
dir = pw->pw_dir;
return;
}
dir = wcs2str( wdir );
free( wdir );
gethostname( hostname, HOSTNAME_LEN );
name = malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 );
@@ -400,34 +500,38 @@ void load_or_save( int save)
strcat( name, "/" );
strcat( name, FILE );
strcat( name, hostname );
free( dir );
debug( 1, L"Open file for %s: '%s'",
debug( 4, L"Open file for %s: '%s'",
save?"saving":"loading",
name );
c.fd = open( name, save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
fd = open( name, save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
free( name );
if( c.fd == -1 )
if( fd == -1 )
{
debug( 1, L"Could not open load/save file. No previous saves?" );
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 );
connection_init( &c, fd );
if( save )
{
write( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
enqueue_all( &c );
}
else
read_message( &c );
q_destroy( &c.unsent );
sb_destroy( &c.input );
close( c.fd );
connection_destroy( &c );
}
/**
@@ -471,6 +575,8 @@ int main( int argc, char ** argv )
int update_count=0;
fd_set read_fd, write_fd;
halloc_util_init();
program_name=L"fishd";
wsetlocale( LC_ALL, L"" );
@@ -480,7 +586,6 @@ int main( int argc, char ** argv )
*/
while( 1 )
{
#ifdef HAVE_GETOPT_LONG
static struct option
long_options[] =
{
@@ -502,15 +607,10 @@ int main( int argc, char ** argv )
int opt = getopt_long( argc,
argv,
"hv",
GETOPT_STRING,
long_options,
&opt_index );
#else
int opt = getopt( argc,
argv,
"hv" );
#endif
if( opt == -1 )
break;
@@ -539,7 +639,7 @@ int main( int argc, char ** argv )
connection_t *c;
int res;
t=sizeof( remote );
t = sizeof( remote );
FD_ZERO( &read_fd );
FD_ZERO( &write_fd );
@@ -587,7 +687,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 )
{
@@ -597,12 +697,8 @@ int main( int argc, char ** argv )
else
{
connection_t *new = malloc( sizeof(connection_t));
new->fd = child_socket;
connection_init( new, child_socket );
new->next = conn;
q_init( &new->unsent );
new->killme=0;
sb_init( &new->input );
memset (&new->wstate, '\0', sizeof (mbstate_t));
send( new->fd, GREETING, strlen(GREETING), MSG_DONTWAIT );
enqueue_all( new );
conn=new;
@@ -644,10 +740,7 @@ int main( int argc, char ** argv )
{
if( c->killme )
{
debug( 1, L"Close connection %d", c->fd );
close(c->fd );
sb_destroy( &c->input );
debug( 4, L"Close connection %d", c->fd );
while( !q_empty( &c->unsent ) )
{
@@ -657,7 +750,7 @@ int main( int argc, char ** argv )
free( msg );
}
q_destroy( &c->unsent );
connection_destroy( c );
if( prev )
{
prev->next=c->next;
@@ -678,13 +771,16 @@ int main( int argc, char ** argv )
c=c->next;
}
}
if( !conn )
{
debug( 0, L"No more clients. Quitting" );
save();
env_universal_common_destroy();
exit(0);
c=c->next;
break;
}
}
halloc_util_destroy();
}

View File

@@ -1,6 +1,9 @@
/** \file function.c
Functions for storing and retrieving function information.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
@@ -8,15 +11,12 @@
#include <termios.h>
#include <signal.h>
#include "config.h"
#include "wutil.h"
#include "fallback.h"
#include "util.h"
#include "function.h"
#include "proc.h"
#include "translate.h"
#include "parser.h"
#include "common.h"
#include "intern.h"
@@ -36,9 +36,18 @@ 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;
int is_binding;
/**
Flag for specifying that this function was automatically loaded
*/
int is_autoload;
}
function_data_t;
@@ -47,6 +56,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;
/**
@@ -87,7 +102,7 @@ static void autoload_names( array_list_t *out, int get_hidden )
al_init( &path_list );
expand_variable_array( path_var, &path_list );
tokenize_variable_array( path_var, &path_list );
for( i=0; i<al_get_count( &path_list ); i++ )
{
wchar_t *ndir = (wchar_t *)al_get( &path_list, i );
@@ -110,13 +125,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 +139,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 );
@@ -150,27 +165,24 @@ void function_destroy()
void function_add( const wchar_t *name,
const wchar_t *val,
const wchar_t *desc,
array_list_t *events,
int is_binding )
array_list_t *events )
{
int i;
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;
while( (cmd_end>d->cmd) && wcschr( L"\n\r\t ", *cmd_end ) )
{
*cmd_end-- = 0;
}
d->desc = desc?wcsdup( desc ):0;
d->is_binding = is_binding;
d->definition_file = intern(reader_current_filename());
d->is_autoload = is_autoload;
@@ -185,6 +197,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 +210,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 +231,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 +259,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 +273,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 +285,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,14 +304,12 @@ 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;
function_data_t *f = (function_data_t *)val;
if( name[0] != L'_' && !f->is_binding && !al_contains_str( (array_list_t *)aux, name ) )
if( name[0] != L'_' && !al_contains_str( (array_list_t *)aux, name ) )
{
al_push( (array_list_t *)aux, name );
}
@@ -280,9 +318,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 +332,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,7 +350,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;
load( argv );
CHECK( argv, 0 );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return 0;
@@ -322,7 +364,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;
load( argv );
CHECK( argv, -1 );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return -1;

View File

@@ -27,8 +27,7 @@ void function_destroy();
void function_add( const wchar_t *name,
const wchar_t *val,
const wchar_t *desc,
array_list_t *events,
int is_binding );
array_list_t *events );
/**
Remove the function with the specified name.

101
halloc.c
View File

@@ -18,38 +18,104 @@
#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
#define HALLOC_SCRAP_SIZE 16
/**
Maximum size of trailing halloc space to refuse to discard. This is
set to be larger on 64-bit platforms, since we don't want to get
'stuck' with an unusably small slice of memory, and what is
unusably small often depends on pointer size.
*/
#define HALLOC_SCRAP_SIZE (4*sizeof(void *))
#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;
size_t scratch_free;
long long data[0];
/**
Amount of free space in the scratch area
*/
ssize_t scratch_free;
}
halloc_t;
static halloc_t *halloc_from_data( void *data )
static void *align_ptr( void *in )
{
return (halloc_t *)(((char *)data) - sizeof( halloc_t ) );
unsigned long step = maxi(sizeof(double),sizeof(void *));
unsigned long inc = step-1;
unsigned long long_in = (long)in;
unsigned long long_out = ((long_in+inc)/step)*step;
return (void *)long_out;
}
static size_t align_sz( size_t in )
{
size_t step = maxi(sizeof(double),sizeof(void *));
size_t inc = step-1;
return ((in+inc)/step)*step;
}
/**
Get the offset of the halloc structure before a data block
*/
static halloc_t *halloc_from_data( void *data )
{
return (halloc_t *)(((char *)data) - align_sz(sizeof( halloc_t ) ));
}
/**
A function that does nothing
*/
static void late_free( void *data)
{
}
#ifdef HALLOC_DEBUG
static void woot()
/**
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 halloc_report()
{
if( getpid() == pid )
{
@@ -60,25 +126,40 @@ static void woot()
}
#endif
void *halloc( void *context, size_t size )
{
halloc_t *me, *parent;
if( context )
{
void *res;
void *aligned;
#ifdef HALLOC_DEBUG
if( !child_count )
{
pid = getpid();
atexit( woot );
atexit( &halloc_report );
}
child_count++;
child_size += size;
#endif
parent = halloc_from_data( context );
/*
Align memory address
*/
aligned = align_ptr( parent->scratch );
parent->scratch_free -= (aligned-parent->scratch);
if( parent->scratch_free < 0 )
parent->scratch_free=0;
parent->scratch = aligned;
if( size <= parent->scratch_free )
{
res = parent->scratch;
@@ -114,18 +195,18 @@ void *halloc( void *context, size_t size )
}
else
{
me = (halloc_t *)calloc( 1, sizeof(halloc_t) + size + HALLOC_BLOCK_SIZE );
me = (halloc_t *)calloc( 1, align_sz(sizeof(halloc_t)) + align_sz(size) + HALLOC_BLOCK_SIZE );
if( !me )
return 0;
#ifdef HALLOC_DEBUG
parent_count++;
#endif
me->scratch = ((char *)me) + sizeof(halloc_t) + size;
me->scratch = ((char *)me) + align_sz(sizeof(halloc_t)) + align_sz(size);
me->scratch_free = HALLOC_BLOCK_SIZE;
al_init( &me->children );
return &me->data;
return ((char *)me) + align_sz(sizeof(halloc_t));
}
}

View File

@@ -11,7 +11,8 @@
/**
Allocate new memory using specified parent memory context. Context
_must_ be either 0 or the result of a previous call to halloc.
_must_ be either 0 or the result of a previous call to halloc. The
resulting memory is set to zero.
If \c context is null, the resulting block is a root block, and
must be freed with a call to halloc_free().

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

@@ -1,6 +1,8 @@
/** \file highlight.c
Functions for syntax highlighting
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
@@ -11,8 +13,6 @@
#include <termios.h>
#include <signal.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -30,6 +30,15 @@
#include "common.h"
#include "complete.h"
#include "output.h"
#include "halloc.h"
#include "halloc_util.h"
#include "wildcard.h"
#include "path.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,
@@ -40,43 +49,480 @@ static void highlight_universal_internal( wchar_t * buff,
/**
The environment variables used to specify the color of different tokens.
*/
static wchar_t *hightlight_var[] =
static wchar_t *highlight_var[] =
{
L"fish_color_normal",
L"fish_color_command",
L"fish_color_subshell",
L"fish_color_redirection",
L"fish_color_end",
L"fish_color_error",
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_pager_prefix",
L"fish_color_pager_completion",
L"fish_color_pager_description",
L"fish_color_pager_progress"
L"fish_color_operator",
L"fish_color_escape",
L"fish_color_quote",
L"fish_color_redirection",
L"fish_color_valid_path"
}
;
/**
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;
if( 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 >= (12) )
if( highlight >= (1<<VAR_COUNT) )
return FISH_COLOR_NORMAL;
wchar_t *val = env_get( hightlight_var[highlight]);
if( val == 0 )
val = env_get( hightlight_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 );
return output_color_code( 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;
}
/**
Highligt operators (such as $, ~, %, as well as escaped characters.
*/
static void highlight_param( const wchar_t * buff,
int *color,
int pos,
array_list_t *error )
{
int mode = 0;
int in_pos, len = wcslen( buff );
int bracket_count=0;
wchar_t c;
int normal_status = *color;
for( in_pos=0;
in_pos<len;
in_pos++ )
{
c = buff[in_pos];
switch( mode )
{
/*
Mode 0 means unquoted string
*/
case 0:
{
if( c == L'\\' )
{
int start_pos = in_pos;
in_pos++;
if( wcschr( L"~%", buff[in_pos] ) )
{
if( in_pos == 1 )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = normal_status;
}
}
else if( buff[in_pos]==L',' )
{
if( bracket_count )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = normal_status;
}
}
else if( wcschr( L"nrtbe*?$(){}'\"<>^ \\#;|&", buff[in_pos] ) )
{
color[start_pos]=HIGHLIGHT_ESCAPE;
color[in_pos+1]=normal_status;
}
else if( wcschr( L"uUxX01234567", buff[in_pos] ) )
{
int i;
long long res=0;
int chars=2;
int base=16;
int byte = 0;
wchar_t max_val = ASCII_MAX;
switch( buff[in_pos] )
{
case L'u':
{
chars=4;
max_val = UCS2_MAX;
break;
}
case L'U':
{
chars=8;
max_val = WCHAR_MAX;
break;
}
case L'x':
{
break;
}
case L'X':
{
byte=1;
max_val = BYTE_MAX;
break;
}
default:
{
base=8;
chars=3;
in_pos--;
break;
}
}
for( i=0; i<chars; i++ )
{
int d = convert_digit( buff[++in_pos],base);
if( d < 0 )
{
in_pos--;
break;
}
res=(res*base)|d;
}
if( (res <= max_val) )
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = normal_status;
}
else
{
color[start_pos] = HIGHLIGHT_ERROR;
color[in_pos+1] = normal_status;
}
}
}
else
{
switch( buff[in_pos]){
case L'~':
case L'%':
{
if( in_pos == 0 )
{
color[in_pos] = HIGHLIGHT_OPERATOR;
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')':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = normal_status;
break;
}
case L'{':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = normal_status;
bracket_count++;
break;
}
case L'}':
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = normal_status;
bracket_count--;
break;
}
case L',':
{
if( bracket_count )
{
color[in_pos] = HIGHLIGHT_OPERATOR;
color[in_pos+1] = normal_status;
}
break;
}
case L'\'':
{
color[in_pos] = HIGHLIGHT_QUOTE;
mode = 1;
break;
}
case L'\"':
{
color[in_pos] = HIGHLIGHT_QUOTE;
mode = 2;
break;
}
}
}
break;
}
/*
Mode 1 means single quoted string, i.e 'foo'
*/
case 1:
{
if( c == L'\\' )
{
int start_pos = in_pos;
switch( buff[++in_pos] )
{
case '\\':
case L'\'':
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_QUOTE;
break;
}
case 0:
{
return;
}
}
}
if( c == L'\'' )
{
mode = 0;
color[in_pos+1] = normal_status;
}
break;
}
/*
Mode 2 means double quoted string, i.e. "foo"
*/
case 2:
{
switch( c )
{
case '"':
{
mode = 0;
color[in_pos+1] = normal_status;
break;
}
case '\\':
{
int start_pos = in_pos;
switch( buff[++in_pos] )
{
case L'\0':
{
return;
}
case '\\':
case L'$':
case '"':
{
color[start_pos] = HIGHLIGHT_ESCAPE;
color[in_pos+1] = HIGHLIGHT_QUOTE;
break;
}
}
break;
}
case '$':
{
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;
}
}
break;
}
}
}
}
@@ -90,11 +536,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;
@@ -104,7 +560,7 @@ void highlight_shell( wchar_t * buff,
{
int last_type = tok_last_type( &tok );
int prev_argc=0;
switch( last_type )
{
case TOK_STRING:
@@ -125,6 +581,27 @@ 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_CMDSUBST );
if( dir )
{
if( !path_get_cdpath( context, dir ) )
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
}
}
}
highlight_param( param,
&color[tok_get_pos( &tok )],
pos-tok_get_pos( &tok ),
error );
}
else
{
@@ -133,9 +610,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_CMDSUBST | EXPAND_SKIP_VARIABLES);
if( cmd == 0 )
{
@@ -143,17 +620,17 @@ void highlight_shell( wchar_t * buff,
}
else
{
wchar_t *tmp;
int is_cmd = 0;
int is_subcommand = 0;
int mark = tok_get_pos( &tok );
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_COMMAND;
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
@@ -172,31 +649,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=path_get_path( 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=path_get_cdpath( context, cmd ));
if( is_cmd )
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_COMMAND;
@@ -204,20 +687,16 @@ void highlight_shell( wchar_t * buff,
else
{
if( error )
al_push( error, wcsdupcat2 ( L"Unknown command \'", cmd, L"\'", 0 ));
al_push( error, wcsdupcat2 ( L"Unknown command \'", cmd, L"\'", (void *)0 ));
color[ tok_get_pos( &tok ) ] = (HIGHLIGHT_ERROR);
}
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 ) );
}
}
}
@@ -250,9 +729,9 @@ 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_CMDSUBST);
/*
Redirect filename may contain a subshell.
Redirect filename may contain a cmdsubst.
If so, it will be ignored/not flagged.
*/
}
@@ -268,7 +747,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;
/*
@@ -282,11 +761,10 @@ void highlight_shell( wchar_t * buff,
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
if( error )
al_push( error, wcsdupcat2( L"Directory \'", dir, L"\' does not exist", 0 ) );
al_push( error, wcsdupcat2( L"Directory \'", dir, L"\' does not exist", (void *)0 ) );
}
}
}
free( dir );
/*
If the file is read from or appended to, check
@@ -299,10 +777,9 @@ void highlight_shell( wchar_t * buff,
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
if( error )
al_push( error, wcsdupcat2( L"File \'", target, L"\' does not exist", 0 ) );
al_push( error, wcsdupcat2( L"File \'", target, L"\' does not exist", (void *)0 ) );
}
}
free( target );
}
break;
}
@@ -352,16 +829,13 @@ void highlight_shell( wchar_t * buff,
}
}
if( last_cmd )
free( last_cmd );
tok_destroy( &tok );
/*
Locate and syntax highlight subshells recursively
Locate and syntax highlight cmdsubsts recursively
*/
wchar_t *buffcpy = wcsdup( buff );
wchar_t *buffcpy = halloc_wcsdup( context, buff );
wchar_t *subpos=buffcpy;
int done=0;
@@ -370,8 +844,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;
@@ -383,7 +857,7 @@ void highlight_shell( wchar_t * buff,
*end=0;
highlight_shell( begin+1, color +(begin-buffcpy)+1, -1, error );
color[end-buffcpy]=HIGHLIGHT_PARAM;
color[end-buffcpy]=HIGHLIGHT_OPERATOR;
if( done )
break;
@@ -391,9 +865,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++ )
{
@@ -403,6 +879,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 );
@@ -416,6 +918,9 @@ void highlight_shell( wchar_t * buff,
color[i]=0;
}
}
halloc_free( context );
}
/**
@@ -458,22 +963,22 @@ static void highlight_universal_internal( wchar_t * buff,
if( level == 0 )
{
level++;
al_push( &l, (void *)(str-buff) );
al_push_long( &l, (long)(str-buff) );
prev_q = *str;
}
else
{
if( prev_q == *str )
{
int pos1, pos2;
long pos1, pos2;
level--;
pos1 = (int)al_pop( &l );
pos1 = al_pop_long( &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;
}
@@ -482,7 +987,7 @@ static void highlight_universal_internal( wchar_t * buff,
else
{
level++;
al_push( &l, (void *)(str-buff) );
al_push_long( &l, (long)(str-buff) );
prev_q = *str;
}
}
@@ -498,7 +1003,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;
}
/*
@@ -511,8 +1016,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)
{
@@ -523,8 +1027,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;
}
@@ -532,7 +1036,7 @@ static void highlight_universal_internal( wchar_t * buff,
}
if( !match_found )
color[pos] = HIGHLIGHT_ERROR<<8;
color[pos] = HIGHLIGHT_ERROR<<16;
}
}
}
@@ -544,7 +1048,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

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