Compare commits

..

348 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
186 changed files with 23238 additions and 8198 deletions

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

327
builtin.c
View File

@@ -13,7 +13,7 @@
3). Create a file doc_src/NAME.txt, containing the manual for the builtin in Doxygen-format. Check the other builtin manuals for proper syntax.
4). Add an entry to the BUILTIN_DOC_SRC variable of Makefile.in. Note that the entries should be sorted alphabetically!
4). Add an entry to the BUILTIN_DOC_SRC variable of Makefile.in.
5). Add an entry to the manual at the builtin-overview subsection of doc_src/doc.hdr. Note that the entries should be sorted alphabetically!
@@ -21,6 +21,8 @@
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>
@@ -37,8 +39,6 @@
#include <sys/time.h>
#include <time.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -60,11 +60,12 @@
#include "intern.h"
#include "event.h"
#include "signal.h"
#include "translate.h"
#include "halloc.h"
#include "halloc_util.h"
#include "parse_util.h"
#include "expand.h"
#include "path.h"
@@ -214,15 +215,17 @@ static void builtin_print_help( wchar_t *cmd, string_buffer_t *b )
if( is_interactive && !builtin_out_redirect && b==sb_err)
{
/* Interactive mode help to screen - only print synopsis if the rest won't fit */
int screen_height, lines;
screen_height = common_get_height();
lines = count_char( str, L'\n' );
if( lines > 2*screen_height/3 )
{
wchar_t *pos;
int cut=0;
/* Find first empty line */
for( pos=str; *pos; pos++ )
@@ -246,9 +249,16 @@ static void builtin_print_help( wchar_t *cmd, string_buffer_t *b )
if( is_empty )
{
*(pos+1)=L'\0';
cut = 1;
break;
}
}
}
if( !cut )
{
*str = 0;
}
}
}
@@ -335,7 +345,7 @@ static int builtin_bind( wchar_t **argv )
long_options[opt_index].name );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
case 'M':
input_set_mode( woptarg );
@@ -348,7 +358,7 @@ static int builtin_bind( wchar_t **argv )
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
@@ -430,7 +440,7 @@ static int builtin_block( wchar_t **argv )
long_options[opt_index].name );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
@@ -450,7 +460,7 @@ static int builtin_block( wchar_t **argv )
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
@@ -461,13 +471,13 @@ static int builtin_block( wchar_t **argv )
if( scope != UNSET )
{
sb_printf( sb_err, _( L"%ls: Can not specify scope when removing block\n" ), argv[0] );
return 1;
return STATUS_BUILTIN_ERROR;
}
if( !global_event_block )
{
sb_printf( sb_err, _( L"%ls: No blocks defined\n" ), argv[0] );
return 1;
return STATUS_BUILTIN_ERROR;
}
event_block_t *eb = global_event_block;
@@ -571,7 +581,7 @@ static int builtin_builtin( wchar_t **argv )
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
case 'h':
builtin_print_help( argv[0], sb_out );
return 0;
@@ -583,7 +593,7 @@ static int builtin_builtin( wchar_t **argv )
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
@@ -660,7 +670,7 @@ static int builtin_generic( wchar_t **argv )
argv[0],
long_options[opt_index].name );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
case 'h':
builtin_print_help( argv[0], sb_out );
@@ -669,19 +679,19 @@ static int builtin_generic( wchar_t **argv )
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
}
return 1;
return STATUS_BUILTIN_ERROR;
}
/**
Output a definition of the specified function to the sb_out
Output a definition of the specified function to the specified
stringbuffer. Used by the functions builtin.
*/
static void functions_def( wchar_t *name )
static void functions_def( wchar_t *name, string_buffer_t *out )
{
const wchar_t *desc = function_get_desc( name );
const wchar_t *def = function_get_definition(name);
@@ -697,7 +707,7 @@ static void functions_def( wchar_t *name )
al_init( &ev );
event_get( &search, &ev );
sb_append2( sb_out,
sb_append2( out,
L"function ",
name,
(void *)0);
@@ -706,7 +716,7 @@ static void functions_def( wchar_t *name )
{
wchar_t *esc_desc = escape( desc, 1 );
sb_append2( sb_out, L" --description ", esc_desc, (void *)0 );
sb_append2( out, L" --description ", esc_desc, (void *)0 );
free( esc_desc );
}
@@ -717,22 +727,22 @@ static void functions_def( wchar_t *name )
{
case EVENT_SIGNAL:
{
sb_printf( sb_out, L" --on-signal %ls", sig2wcs( next->param1.signal ) );
sb_printf( out, L" --on-signal %ls", sig2wcs( next->param1.signal ) );
break;
}
case EVENT_VARIABLE:
{
sb_printf( sb_out, L" --on-variable %ls", next->param1.variable );
sb_printf( out, L" --on-variable %ls", next->param1.variable );
break;
}
case EVENT_EXIT:
{
if( next->param1.pid > 0 )
sb_printf( sb_out, L" --on-process-exit %d", next->param1.pid );
sb_printf( out, L" --on-process-exit %d", next->param1.pid );
else
sb_printf( sb_out, L" --on-job-exit %d", -next->param1.pid );
sb_printf( out, L" --on-job-exit %d", -next->param1.pid );
break;
}
@@ -740,7 +750,7 @@ static void functions_def( wchar_t *name )
{
job_t *j = job_get( next->param1.job_id );
if( j )
sb_printf( sb_out, L" --on-job-exit %d", j->pgid );
sb_printf( out, L" --on-job-exit %d", j->pgid );
break;
}
@@ -750,7 +760,7 @@ static void functions_def( wchar_t *name )
al_destroy( &ev );
sb_append2( sb_out,
sb_append2( out,
L"\n\t",
def,
L"\nend\n\n",
@@ -835,7 +845,7 @@ static int builtin_functions( wchar_t **argv )
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
case 'e':
erase=1;
@@ -864,7 +874,7 @@ static int builtin_functions( wchar_t **argv )
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
@@ -882,7 +892,7 @@ static int builtin_functions( wchar_t **argv )
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
if( erase )
@@ -903,7 +913,7 @@ static int builtin_functions( wchar_t **argv )
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
func = argv[woptind];
if( !function_exists( func ) )
@@ -915,7 +925,7 @@ static int builtin_functions( wchar_t **argv )
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
function_set_desc( func, desc );
@@ -973,7 +983,7 @@ static int builtin_functions( wchar_t **argv )
for( i=0; i<al_get_count( &names ); i++ )
{
functions_def( (wchar_t *)al_get( &names, i ) );
functions_def( (wchar_t *)al_get( &names, i ), sb_out );
}
al_destroy( &names );
@@ -992,7 +1002,7 @@ static int builtin_functions( wchar_t **argv )
{
if( !query )
{
functions_def( argv[i] );
functions_def( argv[i], sb_out );
}
}
}
@@ -1004,21 +1014,14 @@ static int builtin_functions( wchar_t **argv )
}
/**
Test whether the specified string is a valid name for a keybinding
*/
static int wcsbindingname( wchar_t *str )
typedef struct function_data
{
while( *str )
{
if( (!iswalnum(*str)) && (*str != L'-' ) )
{
return 0;
}
str++;
}
return 1;
wchar_t *name;
wchar_t *description;
array_list_t *events;
}
function_data_t;
/**
@@ -1030,7 +1033,6 @@ static int builtin_function( wchar_t **argv )
int argc = builtin_count_args( argv );
int res=0;
wchar_t *desc=0;
int is_binding=0;
array_list_t *events;
int i;
@@ -1046,10 +1048,6 @@ static int builtin_function( wchar_t **argv )
L"description", required_argument, 0, 'd'
}
,
{
L"key-binding", no_argument, 0, 'b'
}
,
{
L"on-signal", required_argument, 0, 's'
}
@@ -1082,7 +1080,7 @@ static int builtin_function( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"bd:s:j:p:v:h",
L"d:s:j:p:v:h",
long_options,
&opt_index );
if( opt == -1 )
@@ -1097,7 +1095,6 @@ static int builtin_function( wchar_t **argv )
BUILTIN_ERR_UNKNOWN,
argv[0],
long_options[opt_index].name );
builtin_print_help( argv[0], sb_err );
res = 1;
break;
@@ -1106,10 +1103,6 @@ static int builtin_function( wchar_t **argv )
desc=woptarg;
break;
case 'b':
is_binding=1;
break;
case 's':
{
int sig = wcs2sig( woptarg );
@@ -1241,7 +1234,7 @@ static int builtin_function( wchar_t **argv )
return 0;
case '?':
builtin_print_help( argv[0], sb_err );
res = 1;
break;
@@ -1259,7 +1252,7 @@ static int builtin_function( wchar_t **argv )
argc-woptind );
res=1;
}
else if( !(is_binding?wcsbindingname( argv[woptind] ) : !wcsvarname( argv[woptind] ) ))
else if( wcsfuncname( argv[woptind] ) )
{
sb_printf( sb_err,
_( L"%ls: Illegal function name '%ls'\n" ),
@@ -1316,16 +1309,20 @@ static int builtin_function( wchar_t **argv )
}
else
{
current_block->param1.function_name=halloc_wcsdup( current_block, argv[woptind]);
current_block->param2.function_description=desc?halloc_wcsdup( current_block, desc):0;
current_block->param3.function_is_binding = is_binding;
current_block->param4.function_events = events;
function_data_t * d = halloc( current_block, sizeof( function_data_t ));
d->name=halloc_wcsdup( current_block, argv[woptind]);
d->description=desc?halloc_wcsdup( current_block, desc):0;
d->events = events;
for( i=0; i<al_get_count( events ); i++ )
{
event_t *e = (event_t *)al_get( events, i );
e->function_name = current_block->param1.function_name;
e->function_name = d->name;
}
current_block->data = d;
}
current_block->tok_pos = parser_get_pos();
@@ -1383,7 +1380,7 @@ static int builtin_random( wchar_t **argv )
long_options[opt_index].name );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
case 'h':
builtin_print_help( argv[0], sb_out );
@@ -1392,7 +1389,7 @@ static int builtin_random( wchar_t **argv )
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
@@ -1412,7 +1409,7 @@ static int builtin_random( wchar_t **argv )
}
lrand48_r( &seed_buffer, &res );
sb_printf( sb_out, L"%d\n", res%32767 );
sb_printf( sb_out, L"%d\n", abs(res%32767) );
break;
}
@@ -1430,7 +1427,7 @@ static int builtin_random( wchar_t **argv )
argv[0],
argv[woptind] );
return 1;
return STATUS_BUILTIN_ERROR;
}
seeded=1;
srand48_r( foo, &seed_buffer);
@@ -1444,7 +1441,7 @@ static int builtin_random( wchar_t **argv )
argv[0],
argc-woptind );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
}
return 0;
@@ -1531,7 +1528,7 @@ static int builtin_read( wchar_t **argv )
long_options[opt_index].name );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
case L'x':
place |= ENV_EXPORT;
@@ -1562,7 +1559,7 @@ static int builtin_read( wchar_t **argv )
case L'?':
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
}
@@ -1576,7 +1573,7 @@ static int builtin_read( wchar_t **argv )
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
if( (place&ENV_LOCAL?1:0) + (place & ENV_GLOBAL?1:0) + (place & ENV_UNIVERSAL?1:0) > 1)
@@ -1587,7 +1584,7 @@ static int builtin_read( wchar_t **argv )
parser_current_line() );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
/*
@@ -1600,7 +1597,7 @@ static int builtin_read( wchar_t **argv )
if( !wcslen( argv[i] ) )
{
sb_printf( sb_err, BUILTIN_ERR_VARNAME_ZERO, argv[0] );
return 1;
return STATUS_BUILTIN_ERROR;
}
for( src=argv[i]; *src; src++ )
@@ -1609,7 +1606,7 @@ static int builtin_read( wchar_t **argv )
{
sb_printf( sb_err, BUILTIN_ERR_VARCHAR, argv[0], *src );
sb_append2(sb_err, parser_current_line(), L"\n", (void *)0 );
return 1;
return STATUS_BUILTIN_ERROR;
}
}
@@ -1815,7 +1812,7 @@ static int builtin_status( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"hjt",
L"hj:t",
long_options,
&opt_index );
if( opt == -1 )
@@ -1832,7 +1829,7 @@ static int builtin_status( wchar_t **argv )
long_options[opt_index].name );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
case 'h':
builtin_print_help( argv[0], sb_out );
@@ -1858,7 +1855,7 @@ static int builtin_status( wchar_t **argv )
case '?':
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
@@ -1986,7 +1983,7 @@ static int builtin_exit( wchar_t **argv )
argv[0],
argv[1] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
break;
}
@@ -1998,7 +1995,7 @@ static int builtin_exit( wchar_t **argv )
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
}
@@ -2049,7 +2046,7 @@ static int builtin_cd( wchar_t **argv )
else
dir_in = argv[1];
dir = parser_cdpath_get( context, dir_in );
dir = path_get_cdpath( context, dir_in );
if( !dir )
{
@@ -2110,13 +2107,13 @@ static int builtin_source( wchar_t ** argv )
{
sb_printf( sb_err, _( L"%ls: Expected at least one argument, got %d\n" ), argv[0], argc );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
if( wstat(argv[1], &buf) == -1 )
{
builtin_wperror( L"stat" );
return 1;
return STATUS_BUILTIN_ERROR;
}
if( !S_ISREG(buf.st_mode) )
@@ -2124,7 +2121,7 @@ static int builtin_source( wchar_t ** argv )
sb_printf( sb_err, _( L"%ls: '%ls' is not a file\n" ), argv[0], argv[1] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
if( ( fd = wopen( argv[1], O_RDONLY ) ) == -1 )
{
@@ -2219,8 +2216,8 @@ static int builtin_fg( wchar_t **argv )
*/
for( j=first_job; j; j=j->next )
{
if( j->constructed && (!job_is_completed(j)) &&
( (job_is_stopped(j) || !j->fg) && (j->job_control) ) )
if( job_get_flag( j, JOB_CONSTRUCTED ) && (!job_is_completed(j)) &&
( (job_is_stopped(j) || (!job_get_flag(j, JOB_FOREGROUND)) ) && job_get_flag( j, JOB_CONTROL) ) )
{
break;
}
@@ -2241,9 +2238,20 @@ static int builtin_fg( wchar_t **argv )
since we want to know if this is an ambigous job
specification or if this is an malformed job id
*/
int pid = wcstol( argv[1], 0, 10 );
j = job_get_from_pid( pid );
if( j != 0 )
wchar_t *endptr;
int pid;
int found_job = 0;
errno = 0;
pid = wcstol( argv[1], &endptr, 10 );
if( !( *endptr || errno ) )
{
j = job_get_from_pid( pid );
if( j )
found_job = 1;
}
if( found_job )
{
sb_printf( sb_err,
_( L"%ls: Ambiguous job\n" ),
@@ -2256,6 +2264,7 @@ static int builtin_fg( wchar_t **argv )
argv[0],
argv[1] );
}
builtin_print_help( argv[0], sb_err );
j=0;
@@ -2264,12 +2273,14 @@ static int builtin_fg( wchar_t **argv )
else
{
wchar_t *end;
int pid = abs(wcstol( argv[1], &end, 10 ));
int pid;
errno = 0;
pid = abs(wcstol( argv[1], &end, 10 ));
if( *end )
if( *end || errno )
{
sb_printf( sb_err,
_( L"%ls: Argument '%ls' is not a number\n" ),
BUILTIN_ERR_NOT_NUMBER,
argv[0],
argv[1] );
builtin_print_help( argv[0], sb_err );
@@ -2277,7 +2288,7 @@ static int builtin_fg( wchar_t **argv )
else
{
j = job_get_from_pid( pid );
if( !j || !j->constructed || job_is_completed( j ))
if( !j || !job_get_flag( j, JOB_CONSTRUCTED ) || job_is_completed( j ))
{
sb_printf( sb_err,
_( L"%ls: No suitable job: %d\n" ),
@@ -2286,7 +2297,7 @@ static int builtin_fg( wchar_t **argv )
builtin_print_help( argv[0], sb_err );
j=0;
}
else if( !j->job_control )
else if( !job_get_flag( j, JOB_CONTROL) )
{
sb_printf( sb_err,
_( L"%ls: Can't put job %d, '%ls' to foreground because it is not under job control\n" ),
@@ -2328,7 +2339,7 @@ static int builtin_fg( wchar_t **argv )
reader_write_title();
make_first( j );
j->fg=1;
job_set_flag( j, JOB_FOREGROUND, 1 );
job_continue( j, job_is_stopped(j) );
}
@@ -2347,9 +2358,9 @@ static int send_to_bg( job_t *j, const wchar_t *name )
L"bg",
name );
builtin_print_help( L"bg", sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
else if( !j->job_control )
else if( !job_get_flag( j, JOB_CONTROL ) )
{
sb_printf( sb_err,
_( L"%ls: Can't put job %d, '%ls' to background because it is not under job control\n" ),
@@ -2357,7 +2368,7 @@ static int send_to_bg( job_t *j, const wchar_t *name )
j->job_id,
j->command );
builtin_print_help( L"bg", sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
else
{
@@ -2367,7 +2378,7 @@ static int send_to_bg( job_t *j, const wchar_t *name )
j->command );
}
make_first( j );
j->fg=0;
job_set_flag( j, JOB_FOREGROUND, 0 );
job_continue( j, job_is_stopped(j) );
return 0;
}
@@ -2385,7 +2396,7 @@ static int builtin_bg( wchar_t **argv )
job_t *j;
for( j=first_job; j; j=j->next )
{
if( job_is_stopped(j) && j->job_control && (!job_is_completed(j)) )
if( job_is_stopped(j) && job_get_flag( j, JOB_CONTROL ) && (!job_is_completed(j)) )
{
break;
}
@@ -2427,15 +2438,15 @@ static int builtin_for( wchar_t **argv )
if( argc < 3)
{
sb_printf( sb_err,
_( L"%ls: Expected at least two arguments, got %d\n"),
argc ,
argv[0] );
BUILTIN_FOR_ERR_COUNT,
argv[0] ,
argc );
builtin_print_help( argv[0], sb_err );
}
else if ( wcsvarname(argv[1]) )
{
sb_printf( sb_err,
_( L"%ls: '%ls' is not a valid variable name\n" ),
BUILTIN_FOR_ERR_NAME,
argv[0],
argv[1] );
builtin_print_help( argv[0], sb_err );
@@ -2494,6 +2505,30 @@ static int builtin_begin( wchar_t **argv )
return proc_get_last_status();
}
/**
Define the function specified by the function_data_t structure.
*/
static void builtin_end_add_function_def( function_data_t *d )
{
/**
Copy the text from the beginning of the function
until the end command and use as the new definition
for the specified function
*/
wchar_t *def = wcsndup( parser_get_buffer()+current_block->tok_pos,
parser_get_job_pos()-current_block->tok_pos );
function_add( d->name,
def,
d->description,
d->events );
free( def );
}
/**
Builtin for ending a block of code, such as a for-loop or an if statement.
@@ -2509,7 +2544,7 @@ static int builtin_end( wchar_t **argv )
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
else
{
@@ -2574,21 +2609,21 @@ static int builtin_end( wchar_t **argv )
case FUNCTION_DEF:
{
/**
Copy the text from the beginning of the function
until the end command and use as the new definition
for the specified function
*/
wchar_t *def = wcsndup( parser_get_buffer()+current_block->tok_pos,
parser_get_job_pos()-current_block->tok_pos );
function_add( current_block->param1.function_name,
def,
current_block->param2.function_description,
current_block->param4.function_events,
current_block->param3.function_is_binding );
function_data_t *d = (function_data_t *)current_block->data;
if( d )
{
builtin_end_add_function_def( d );
}
else
{
debug(0,
_(L"%ls: Missing function definition information. This is a fish bug. If you can reproduce it, please file a bug report to %s."),
argv[0],
PACKAGE_BUGREPORT);
}
free(def);
}
break;
@@ -2619,7 +2654,7 @@ static int builtin_else( wchar_t **argv )
_( L"%ls: Not inside of 'if' block\n" ),
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
else
{
@@ -2654,7 +2689,7 @@ static int builtin_break_continue( wchar_t **argv )
argv[1] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
@@ -2671,7 +2706,7 @@ static int builtin_break_continue( wchar_t **argv )
_( L"%ls: Not inside of loop\n" ),
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
b = current_block;
@@ -2712,7 +2747,7 @@ static int builtin_return( wchar_t **argv )
argv[0],
argv[1] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
break;
}
@@ -2721,7 +2756,7 @@ static int builtin_return( wchar_t **argv )
_( L"%ls: Too many arguments\n" ),
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
@@ -2737,23 +2772,24 @@ static int builtin_return( wchar_t **argv )
_( L"%ls: Not inside of function\n" ),
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
b = current_block;
while( ( b->type != FUNCTION_CALL))
{
b->type = FAKE;
b->skip=1;
b = b->outer;
}
b->skip=1;
// proc_set_last_status( status );
return status;
}
/**
Builtin for executing one of several blocks of commands depending on the value of an argument.
Builtin for executing one of several blocks of commands depending
on the value of an argument.
*/
static int builtin_switch( wchar_t **argv )
{
@@ -2778,51 +2814,52 @@ static int builtin_switch( wchar_t **argv )
current_block->skip=1;
current_block->param2.switch_taken=0;
}
return res;
}
/**
Builtin used together with the switch builtin for conditional execution
Builtin used together with the switch builtin for conditional
execution
*/
static int builtin_case( wchar_t **argv )
{
int argc = builtin_count_args( argv );
int i;
wchar_t *unescaped=0;
if( current_block->type != SWITCH )
{
sb_printf( sb_err,
_( L"%ls: 'case' command while not in switch block\n" ),
argv[0] );
builtin_print_help( argv[0], sb_err );
return 1;
return STATUS_BUILTIN_ERROR;
}
current_block->skip = 1;
if( current_block->param2.switch_taken )
{
return 0;
}
for( i=1; i<argc; i++ )
{
free( unescaped );
int match;
unescaped = parse_util_unescape_wildcards( argv[i] );
match = wildcard_match( current_block->param1.switch_value, unescaped );
free( unescaped );
if( wildcard_match( current_block->param1.switch_value, unescaped ) )
if( match )
{
current_block->skip = 0;
current_block->param2.switch_taken = 1;
break;
}
}
free( unescaped );
return 0;
}
@@ -2838,15 +2875,15 @@ static int builtin_case( wchar_t **argv )
const static builtin_data_t builtin_data[]=
{
{
L"exit", &builtin_exit, N_( L"Exit the shell" )
L"exit", &builtin_exit, N_( L"Exit the shell" )
}
,
{
L"block", &builtin_block, N_( L"Temporarily block delivery of events" )
L"block", &builtin_block, N_( L"Temporarily block delivery of events" )
}
,
{
L"builtin", &builtin_builtin, N_( L"Run a builtin command instead of a function" )
L"builtin", &builtin_builtin, N_( L"Run a builtin command instead of a function" )
}
,
{
@@ -3048,6 +3085,8 @@ int builtin_exists( wchar_t *cmd )
*/
static int internal_help( wchar_t *cmd )
{
CHECK( cmd, 0 );
if( wcscmp( cmd, L"for" ) == 0 ||
wcscmp( cmd, L"while" ) == 0 ||
wcscmp( cmd, L"function" ) == 0 ||
@@ -3126,7 +3165,7 @@ void builtin_push_io( int in )
{
if( builtin_stdin != -1 )
{
al_push( &io_stack, (void *)(long)builtin_stdin );
al_push_long( &io_stack, (long)builtin_stdin );
al_push( &io_stack, sb_out );
al_push( &io_stack, sb_err );
}
@@ -3149,7 +3188,7 @@ void builtin_pop_io()
{
sb_err = (string_buffer_t *)al_pop( &io_stack );
sb_out = (string_buffer_t *)al_pop( &io_stack );
builtin_stdin = (int)(long)al_pop( &io_stack );
builtin_stdin = (int)al_pop_long( &io_stack );
}
else
{

View File

@@ -62,11 +62,29 @@ enum
*/
#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
*/

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,15 +52,15 @@ 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;
}
/**
@@ -68,11 +68,7 @@ static const wchar_t *get_buffer()
*/
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;
}
@@ -210,6 +206,20 @@ static 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() )
{
@@ -272,6 +282,14 @@ static int builtin_commandline( wchar_t **argv )
L"help", no_argument, 0, 'h'
}
,
{
L"input", required_argument, 0, 'I'
}
,
{
L"cursor", no_argument, 0, 'C'
}
,
{
0, 0, 0, 0
}
@@ -282,7 +300,7 @@ static int builtin_commandline( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"aijpctwforh",
L"aijpctwforhI:C",
long_options,
&opt_index );
if( opt == -1 )
@@ -337,6 +355,15 @@ static 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;
@@ -354,16 +381,13 @@ static 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;
}
@@ -374,10 +398,6 @@ static 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;
}
@@ -386,7 +406,6 @@ static 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
@@ -396,15 +415,10 @@ static 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;
}
@@ -416,7 +430,7 @@ static 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,
@@ -427,9 +441,19 @@ static 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],
@@ -463,14 +487,44 @@ static 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;
}
wchar_t *begin, *end;
}
switch( buffer_part )
{
case STRING_MODE:
{
begin = (wchar_t *)get_buffer();
begin = get_buffer();
end = begin+wcslen(begin);
break;
}
@@ -516,7 +570,28 @@ static 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,7 +23,7 @@ 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.
@@ -364,7 +364,7 @@ static int builtin_complete( wchar_t **argv )
}
,
{
L"do-complete", required_argument, 0, 'C'
L"do-complete", optional_argument, 0, 'C'
}
,
{
@@ -489,14 +489,14 @@ static int builtin_complete( wchar_t **argv )
{
if( condition && wcslen( condition ) )
{
if( parser_test( condition, 0, 0 ) )
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, sb_err, argv[0] );
parser_test( condition, 0, sb_err, argv[0] );
res = 1;
}

View File

@@ -5,13 +5,14 @@
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 "halloc_util.h"

View File

@@ -1,6 +1,7 @@
/** \file builtin_jobs.c
Functions for executing the jobs builtin.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
@@ -13,8 +14,6 @@
#include <string.h>
#include <wctype.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -24,7 +23,7 @@
#include "parser.h"
#include "common.h"
#include "wgetopt.h"
#include "translate.h"
/**
Print modes for the jobs builtin
@@ -277,7 +276,7 @@ static int builtin_jobs( wchar_t **argv )
*/
for( j=first_job; j; j=j->next )
{
if( j->constructed && !job_is_completed(j) )
if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
return 0;
@@ -331,7 +330,7 @@ static int builtin_jobs( wchar_t **argv )
/*
Ignore unconstructed jobs, i.e. ourself.
*/
if( j->constructed && !job_is_completed(j) )
if( (j->flags & JOB_CONSTRUCTED) && !job_is_completed(j) )
{
builtin_jobs_print( j, mode, !found );
found = 1;

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;
@@ -233,7 +233,6 @@ static int parse_index( array_list_t *indexes,
{
wchar_t *end;
long l_ind = wcstol(src, &end, 10);
int *ind;
if (end == src)
{
@@ -246,9 +245,7 @@ static int parse_index( array_list_t *indexes,
l_ind = var_count+l_ind+1;
}
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++;
@@ -275,7 +272,11 @@ 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 )
{
@@ -291,18 +292,18 @@ static int update_values( array_list_t *list,
/**
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;
}
@@ -317,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));
}
}
@@ -357,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);
@@ -365,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");
@@ -454,6 +478,8 @@ static 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;
@@ -598,6 +624,13 @@ static 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 )
{
/*
@@ -622,13 +655,6 @@ static 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();
@@ -647,7 +673,15 @@ static int builtin_set( wchar_t **argv )
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 );
@@ -675,9 +709,9 @@ static int builtin_set( wchar_t **argv )
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, al_get_count( &result ) ) )
@@ -749,7 +783,6 @@ static int builtin_set( wchar_t **argv )
al_foreach( &result, &free );
al_destroy( &result );
al_foreach( &indexes, &free );
al_destroy(&indexes);
al_destroy(&values);

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

242
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>
@@ -278,7 +296,10 @@ char *wcs2str_internal( const wchar_t *in, char *out )
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;
@@ -289,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
@@ -387,19 +408,25 @@ 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'_' ));
@@ -722,7 +749,6 @@ wchar_t *escape( const wchar_t *in,
case L'*':
case L'|':
case L';':
case L':':
case L'\'':
case L'"':
case L'%':
@@ -795,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':
@@ -843,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;
@@ -915,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;
}
@@ -924,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) )
@@ -1040,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;
}
@@ -1072,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;
@@ -1093,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
@@ -1114,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;
}
@@ -1131,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;
@@ -1402,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()
@@ -1445,3 +1562,42 @@ void tokenize_variable_array( const wchar_t *val, array_list_t *out )
}
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;
}

View File

@@ -52,7 +52,8 @@ extern struct termios shell_modes;
extern wchar_t ellipsis_char;
/**
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;
@@ -71,31 +72,71 @@ extern wchar_t *program_name;
This macro is used to check that an input argument is not null. It
is a bit lika a non-fatal form of assert. Instead of exit-ing on
failiure, the current function is ended at once. The second
parameter is the exit status of the current function on failiure.
parameter is the return value of the current function on failiure.
*/
#define CHECK( arg, retval ) \
#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.", \
_( 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
Exit program at once, leaving an error message about running out of memory.
*/
#define DIE_MEM() \
#define DIE_MEM() \
{ \
fwprintf( stderr, L"fish: Out of memory on line %d of file %s, shutting down fish\n", __LINE__, __FILE__ ); \
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
@@ -183,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
@@ -196,7 +237,16 @@ 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
@@ -246,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
@@ -348,5 +398,12 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff );
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

View File

@@ -3,6 +3,8 @@
These functions are used for storing and retrieving tab-completion data, as well as for performing tab-completion.
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
@@ -20,7 +22,6 @@
#include <signal.h>
#include <wchar.h>
#include "config.h"
#include "fallback.h"
#include "util.h"
@@ -39,11 +40,12 @@
#include "reader.h"
#include "history.h"
#include "intern.h"
#include "translate.h"
#include "parse_util.h"
#include "halloc.h"
#include "halloc_util.h"
#include "wutil.h"
#include "path.h"
/*
@@ -193,7 +195,7 @@ typedef struct complete_entry_opt
/** Next option in the linked list */
struct complete_entry_opt *next;
}
complete_entry_opt;
complete_entry_opt_t;
/**
Struct describing a command completion
@@ -208,16 +210,16 @@ typedef struct complete_entry
/** String containing all short option characters */
wchar_t *short_opt_str;
/** Linked list of all options */
complete_entry_opt *first_option;
complete_entry_opt_t *first_option;
/** Next command completion in the linked list */
struct complete_entry *next;
/** True if no other options than the ones supplied are possible */
int authorative;
}
complete_entry;
complete_entry_t;
/** First node in the linked list of all completion entries */
static complete_entry *first_entry=0;
static complete_entry_t *first_entry=0;
/** Hashtable containing all descriptions that describe an executable */
static hash_table_t *suffix_hash=0;
@@ -233,6 +235,51 @@ static hash_table_t *condition_cache=0;
*/
static string_buffer_t *get_desc_buff=0;
static void complete_free_entry( complete_entry_t *c );
static void clear_hash_entry( void *key, void *data );
/**
Destroys various structures used for tab-completion and free()s the memory used by them.
*/
static void complete_destroy()
{
complete_entry_t *i=first_entry, *prev;
while( i )
{
prev = i;
i=i->next;
complete_free_entry( prev );
}
first_entry = 0;
if( suffix_hash )
{
hash_foreach( suffix_hash, &clear_hash_entry );
hash_destroy( suffix_hash );
free( suffix_hash );
suffix_hash=0;
}
parse_util_load_reset( L"fish_complete_path", 0 );
}
/**
Make sure complete_destroy is called on exit
*/
static void complete_init()
{
static int is_init = 0;
if( !is_init )
{
is_init = 1;
halloc_register_function_void( global_context, &complete_destroy );
}
}
/**
This command clears the cache of condition tests created by \c condition_test().
*/
@@ -300,9 +347,9 @@ static int condition_test( const wchar_t *condition )
/**
Recursively free all complete_entry_opt structs and their contents
Recursively free all complete_entry_opt_t structs and their contents
*/
static void complete_free_opt_recursive( complete_entry_opt *o )
static void complete_free_opt_recursive( complete_entry_opt_t *o )
{
if( o->next != 0 )
complete_free_opt_recursive( o->next );
@@ -310,9 +357,9 @@ static void complete_free_opt_recursive( complete_entry_opt *o )
}
/**
Free a complete_entry and its contents
Free a complete_entry_t and its contents
*/
static void complete_free_entry( complete_entry *c )
static void complete_free_entry( complete_entry_t *c )
{
// free( c->cmd );
free( c->short_opt_str );
@@ -329,41 +376,13 @@ static void clear_hash_entry( void *key, void *data )
free( (void *)data );
}
void complete_init()
{
}
void complete_destroy()
{
complete_entry *i=first_entry, *prev;
while( i )
{
prev = i;
i=i->next;
complete_free_entry( prev );
}
first_entry = 0;
if( suffix_hash )
{
hash_foreach( suffix_hash, &clear_hash_entry );
hash_destroy( suffix_hash );
free( suffix_hash );
suffix_hash=0;
}
parse_util_load_reset( L"fish_complete_path", 0 );
}
/**
Search for an exactly matching completion entry
*/
static complete_entry *complete_find_exact_entry( const wchar_t *cmd,
static complete_entry_t *complete_find_exact_entry( const wchar_t *cmd,
const int cmd_type )
{
complete_entry *i;
complete_entry_t *i;
for( i=first_entry; i; i=i->next )
{
if( ( wcscmp(cmd, i->cmd)==0) && ( cmd_type == i->cmd_type ))
@@ -385,16 +404,18 @@ void complete_add( const wchar_t *cmd,
const wchar_t *comp,
const wchar_t *desc )
{
complete_entry *c;
complete_entry_opt *opt;
complete_entry_t *c;
complete_entry_opt_t *opt;
CHECK( cmd, );
complete_init();
c = complete_find_exact_entry( cmd, cmd_type );
if( c == 0 )
{
if( !(c = malloc( sizeof(complete_entry) )))
if( !(c = malloc( sizeof(complete_entry_t) )))
{
DIE_MEM();
}
@@ -409,7 +430,7 @@ void complete_add( const wchar_t *cmd,
c->short_opt_str = wcsdup(L"");
}
if( !(opt = malloc( sizeof( complete_entry_opt ) )))
if( !(opt = malloc( sizeof( complete_entry_opt_t ) )))
{
DIE_MEM();
}
@@ -454,7 +475,7 @@ void complete_remove( const wchar_t *cmd,
wchar_t short_opt,
const wchar_t *long_opt )
{
complete_entry *e, *eprev=0, *enext=0;
complete_entry_t *e, *eprev=0, *enext=0;
CHECK( cmd, );
@@ -465,7 +486,7 @@ void complete_remove( const wchar_t *cmd,
if( (cmd_type == e->cmd_type ) &&
( wcscmp( cmd, e->cmd) == 0 ) )
{
complete_entry_opt *o, *oprev=0, *onext=0;
complete_entry_opt_t *o, *oprev=0, *onext=0;
if(( short_opt == 0 ) && (long_opt == 0 ) )
{
@@ -561,14 +582,14 @@ static void parse_cmd_string( void *context,
wchar_t *cmd, *path;
/* Get the path of the command */
path = parser_get_filename( context, str );
path = path_get_path( context, str );
if( path == 0 )
{
/**
Use the empty string as the 'path' for commands that can
not be found.
*/
path = wcsdup(L"");
path = halloc_wcsdup( context, L"");
}
/* Make sure the path is not included in the command */
@@ -590,8 +611,8 @@ int complete_is_valid_option( const wchar_t *str,
const wchar_t *opt,
array_list_t *errors )
{
complete_entry *i;
complete_entry_opt *o;
complete_entry_t *i;
complete_entry_opt_t *o;
wchar_t *cmd, *path;
int found_match = 0;
int authorative = 1;
@@ -795,7 +816,7 @@ int complete_is_valid_option( const wchar_t *str,
str[0] = opt[j];
str[1]=0;
al_push( errors,
wcsdupcat2(_( L"Unknown option: " ), L"'", str, L"'", 0) );
wcsdupcat2(_( L"Unknown option: " ), L"'", str, L"'", (void *)0) );
}
opt_found = 0;
@@ -813,12 +834,12 @@ int complete_is_valid_option( const wchar_t *str,
if( hash_get_count( &gnu_match_hash )==0)
{
al_push( errors,
wcsdupcat2( _(L"Unknown option: "), L"'", opt, L"\'", 0) );
wcsdupcat2( _(L"Unknown option: "), L"'", opt, L"\'", (void *)0) );
}
else
{
al_push( errors,
wcsdupcat2( _(L"Multiple matches for option: "), L"'", opt, L"\'", 0) );
wcsdupcat2( _(L"Multiple matches for option: "), L"'", opt, L"\'", (void *)0) );
}
}
}
@@ -888,24 +909,26 @@ static const wchar_t *complete_get_desc_suffix( const wchar_t *suff_orig )
array_list_t l;
al_init( &l );
exec_subshell( cmd, &l );
free(cmd);
if( al_get_count( &l )>0 )
if( exec_subshell( cmd, &l ) != -1 )
{
wchar_t *ln = (wchar_t *)al_get(&l, 0 );
if( wcscmp( ln, L"unknown" ) != 0 )
if( al_get_count( &l )>0 )
{
desc = wcsdup( ln);
/*
I have decided I prefer to have the description
begin in uppercase and the whole universe will just
have to accept it. Hah!
*/
desc[0]=towupper(desc[0]);
wchar_t *ln = (wchar_t *)al_get(&l, 0 );
if( wcscmp( ln, L"unknown" ) != 0 )
{
desc = wcsdup( ln);
/*
I have decided I prefer to have the description
begin in uppercase and the whole universe will just
have to accept it. Hah!
*/
desc[0]=towupper(desc[0]);
}
}
}
free(cmd);
al_foreach( &l, &free );
al_destroy( &l );
}
@@ -934,6 +957,7 @@ const wchar_t *complete_get_desc( const wchar_t *filename )
if( !get_desc_buff )
{
complete_init();
get_desc_buff = sb_halloc( global_context);
}
else
@@ -1060,7 +1084,7 @@ static void copy_strings_with_prefix( array_list_t *comp_out,
wchar_t *wc, *tmp;
tmp = expand_one( 0,
wcsdup(wc_escaped), EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_WILDCARDS);
wcsdup(wc_escaped), EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_WILDCARDS);
if(!tmp)
return;
@@ -1133,78 +1157,82 @@ static void complete_cmd_desc( const wchar_t *cmd, array_list_t *comp )
systems with a large set of manuals, but it should be ok
since apropos is only called once.
*/
exec_subshell( lookup_cmd, &list );
if( exec_subshell( lookup_cmd, &list ) != -1 )
{
/*
Then discard anything that is not a possible completion and put
the result into a hashtable with the completion as key and the
description as value.
Should be reasonably fast, since no memory allocations are needed.
*/
for( i=0; i<al_get_count( &list); i++ )
{
wchar_t *el = (wchar_t *)al_get( &list, i );
wchar_t *key, *key_end, *val_begin;
key = el+wcslen(cmd);
if( !el )
continue;
key_end = wcschr( el, L'\t' );
if( !key_end )
continue;
*key_end = 0;
val_begin = key_end+1;
/*
And once again I make sure the first character is uppercased
because I like it that way, and I get to decide these
things.
Then discard anything that is not a possible completion and put
the result into a hashtable with the completion as key and the
description as value.
Should be reasonably fast, since no memory allocations are needed.
*/
val_begin[0]=towupper(val_begin[0]);
for( i=0; i<al_get_count( &list); i++ )
{
wchar_t *el = (wchar_t *)al_get( &list, i );
wchar_t *key, *key_end, *val_begin;
hash_put( &lookup, key, val_begin );
}
if( !el )
continue;
/*
Then do a lookup on every completion and if a match is found,
change to the new description.
key = el+wcslen(cmd_start);
key_end = wcschr( el, L'\t' );
This needs to do a reallocation for every description added, but
there shouldn't be that many completions, so it should be ok.
*/
for( i=0; i<al_get_count(comp); i++ )
{
wchar_t *el = (wchar_t *)al_get( comp, i );
wchar_t *cmd_end = wcschr( el,
COMPLETE_SEP );
wchar_t *new_desc;
if( cmd_end )
*cmd_end = 0;
new_desc = (wchar_t *)hash_get( &lookup,
el );
if( new_desc )
{
wchar_t *new_el = wcsdupcat2( el,
COMPLETE_SEP_STR,
new_desc,
0 );
al_set( comp, i, new_el );
free( el );
if( !key_end )
continue;
*key_end = 0;
val_begin = key_end+1;
/*
And once again I make sure the first character is uppercased
because I like it that way, and I get to decide these
things.
*/
val_begin[0]=towupper(val_begin[0]);
hash_put( &lookup, key, val_begin );
}
else
/*
Then do a lookup on every completion and if a match is found,
change to the new description.
This needs to do a reallocation for every description added, but
there shouldn't be that many completions, so it should be ok.
*/
for( i=0; i<al_get_count(comp); i++ )
{
wchar_t *el = (wchar_t *)al_get( comp, i );
wchar_t *cmd_end = wcschr( el,
COMPLETE_SEP );
wchar_t *new_desc;
if( cmd_end )
*cmd_end = COMPLETE_SEP;
*cmd_end = 0;
new_desc = (wchar_t *)hash_get( &lookup,
el );
if( new_desc )
{
wchar_t *new_el = wcsdupcat2( el,
COMPLETE_SEP_STR,
new_desc,
(void *)0 );
al_set( comp, i, new_el );
free( el );
}
else
{
if( cmd_end )
*cmd_end = COMPLETE_SEP;
}
}
}
hash_destroy( &lookup );
al_foreach( &list,
&free );
@@ -1249,9 +1277,11 @@ static void complete_cmd( const wchar_t *cmd,
wchar_t *cdpath = env_get(L"CDPATH");
wchar_t *cdpath_cpy = wcsdup( cdpath?cdpath:L"." );
int prev_count = al_get_count( comp );
if( (wcschr( cmd, L'/') != 0) || (cmd[0] == L'~' ) )
{
array_list_t tmp;
al_init( &tmp );
@@ -1260,47 +1290,57 @@ static void complete_cmd( const wchar_t *cmd,
comp,
ACCEPT_INCOMPLETE | EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
complete_cmd_desc( cmd, comp );
if( al_get_count( comp ) > prev_count )
{
complete_cmd_desc( cmd, comp );
}
}
al_destroy( &tmp );
}
else
{
path = env_get(L"PATH");
path_cpy = wcsdup( path );
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
if( path )
{
nxt_completion = wcsdupcat2( nxt_path,
(nxt_path[wcslen(nxt_path)-1]==L'/'?L"":L"/"),
cmd,
0 );
if( ! nxt_completion )
continue;
al_init( &tmp );
if( expand_string( 0,
nxt_completion,
&tmp,
ACCEPT_INCOMPLETE |
EXECUTABLES_ONLY ) != EXPAND_ERROR )
path_cpy = wcsdup( path );
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
nxt_path != 0;
nxt_path = wcstok( 0, ARRAY_SEP_STR, &state) )
{
for( i=0; i<al_get_count(&tmp); i++ )
nxt_completion = wcsdupcat2( nxt_path,
(nxt_path[wcslen(nxt_path)-1]==L'/'?L"":L"/"),
cmd,
(void *)0 );
if( ! nxt_completion )
continue;
al_init( &tmp );
if( expand_string( 0,
nxt_completion,
&tmp,
ACCEPT_INCOMPLETE |
EXECUTABLES_ONLY ) != EXPAND_ERROR )
{
al_push( comp, al_get( &tmp, i ) );
for( i=0; i<al_get_count(&tmp); i++ )
{
al_push( comp, al_get( &tmp, i ) );
}
}
al_destroy( &tmp );
}
free( path_cpy );
if( al_get_count( comp ) > prev_count )
{
complete_cmd_desc( cmd, comp );
}
al_destroy( &tmp );
}
free( path_cpy );
complete_cmd_desc( cmd, comp );
/*
These return the original strings - don't free them
*/
@@ -1314,7 +1354,6 @@ static void complete_cmd( const wchar_t *cmd,
copy_strings_with_prefix( comp, cmd, COMPLETE_BUILTIN_DESC, &builtin_get_desc, &possible_comp );
al_destroy( &possible_comp );
}
/*
@@ -1333,7 +1372,7 @@ static void complete_cmd( const wchar_t *cmd,
wcsdupcat2( nxt_path,
(nxt_path[wcslen(nxt_path)-1]==L'/'?L"":L"/"),
cmd,
0 );
(void *)0 );
if( ! nxt_completion )
{
continue;
@@ -1414,29 +1453,29 @@ static void complete_from_args( const wchar_t *str,
strings should be escaped!
*/
/*
for( i=0; i< al_get_count( &possible_comp ); i++ )
{
wchar_t *next = (wchar_t *)al_get( &possible_comp, i );
wchar_t *next_unescaped;
if( next )
{
next_unescaped = unescape( next, 0 );
if( next_unescaped )
{
al_set( &possible_comp , i, next_unescaped );
}
else
{
al_set( &possible_comp , i, 0 );
debug( 2, L"Could not expand string %ls on line %d of file %s", next, __LINE__, __FILE__ );
}
free( next );
}
else
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
}
}
for( i=0; i< al_get_count( &possible_comp ); i++ )
{
wchar_t *next = (wchar_t *)al_get( &possible_comp, i );
wchar_t *next_unescaped;
if( next )
{
next_unescaped = unescape( next, 0 );
if( next_unescaped )
{
al_set( &possible_comp , i, next_unescaped );
}
else
{
al_set( &possible_comp , i, 0 );
debug( 2, L"Could not expand string %ls on line %d of file %s", next, __LINE__, __FILE__ );
}
free( next );
}
else
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
}
}
*/
copy_strings_with_prefix( comp_out, str, desc, 0, &possible_comp );
@@ -1448,7 +1487,7 @@ static void complete_from_args( const wchar_t *str,
/**
Match against an old style long option
*/
static int param_match_old( complete_entry_opt *e,
static int param_match_old( complete_entry_opt_t *e,
wchar_t *optstr )
{
return (optstr[0] == L'-') && (wcscmp( e->long_opt, &optstr[1] ) == 0);
@@ -1457,7 +1496,7 @@ static int param_match_old( complete_entry_opt *e,
/**
Match a parameter
*/
static int param_match( complete_entry_opt *e,
static int param_match( complete_entry_opt_t *e,
wchar_t *optstr )
{
if( e->short_opt != L'\0' &&
@@ -1478,7 +1517,7 @@ static int param_match( complete_entry_opt *e,
/**
Test if a string is an option with an argument, like --color=auto or -I/usr/include
*/
static wchar_t *param_match2( complete_entry_opt *e,
static wchar_t *param_match2( complete_entry_opt_t *e,
wchar_t *optstr )
{
if( e->short_opt != L'\0' && e->short_opt == optstr[1] )
@@ -1550,6 +1589,7 @@ static void complete_load_handler( const wchar_t *cmd )
void complete_load( const wchar_t *name, int reload )
{
CHECK( name, );
parse_util_load( name,
L"fish_complete_path",
&complete_load_handler,
@@ -1566,8 +1606,8 @@ static int complete_param( wchar_t *cmd_orig,
wchar_t *str,
array_list_t *comp_out )
{
complete_entry *i;
complete_entry_opt *o;
complete_entry_t *i;
complete_entry_opt_t *o;
array_list_t matches;
wchar_t *cmd, *path;
@@ -1708,24 +1748,22 @@ static int complete_param( wchar_t *cmd_orig,
if( wcsncmp( str, (wchar_t *)whole_opt->buff, wcslen(str) )==0)
{
int has_arg=0;
int req_arg=0;
/*
If the option requires arguments, add
option with an appended '=' . If the
option does not accept arguments, add
option. If option accepts but does not
require arguments, add both.
If the switch has an _optional_
argument, it needs to be specified using
'=', otherwise we complete without the
'=' since quite a few programs don't
support it.
*/
if( o->old_mode || !(o->result_mode & NO_COMMON ) )
{
al_push( comp_out,
wcsdupcat2( &((wchar_t *)whole_opt->buff)[wcslen(str)],
COMPLETE_SEP_STR,
C_(o->desc),
(void *)0) );
}
has_arg = !!wcslen( o->comp );
req_arg = (o->result_mode & NO_COMMON );
if( !o->old_mode && ( wcslen(o->comp) || (o->result_mode & NO_COMMON ) ) )
if( !o->old_mode && ( has_arg && !req_arg ) )
{
al_push( comp_out,
wcsdupcat2( &((wchar_t *)whole_opt->buff)[wcslen(str)],
@@ -1734,6 +1772,12 @@ static int complete_param( wchar_t *cmd_orig,
C_(o->desc),
(void *)0) );
}
al_push( comp_out,
wcsdupcat2( &((wchar_t *)whole_opt->buff)[wcslen(str)],
COMPLETE_SEP_STR,
C_(o->desc),
(void *)0) );
}
}
}
@@ -1754,7 +1798,7 @@ static void complete_param_expand( wchar_t *str,
int do_file )
{
wchar_t *comp_str;
if( (wcsncmp( str, L"--", 2 )) == 0 && (comp_str = wcschr(str, L'=' ) ) )
{
comp_str++;
@@ -1763,16 +1807,16 @@ static void complete_param_expand( wchar_t *str,
{
comp_str = str;
}
/*
debug( 3,
L"expand_string( \"%ls\", comp_out, EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | %ls );",
comp_str,
do_file?L"0":L"EXPAND_SKIP_WILDCARDS" );
*/
expand_string( 0,
wcsdup(comp_str),
comp_out,
EXPAND_SKIP_SUBSHELL | ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) );
if( expand_string( 0,
wcsdup(comp_str),
comp_out,
EXPAND_SKIP_CMDSUBST | ACCEPT_INCOMPLETE | (do_file?0:EXPAND_SKIP_WILDCARDS) ) == EXPAND_ERROR )
{
debug( 3, L"Error while expanding string '%ls'", comp_str );
}
}
/**
@@ -1799,20 +1843,27 @@ static int complete_variable( const wchar_t *var,
if( wcsncmp( var, name, varlen) == 0 )
{
wchar_t *value = expand_escape_variable( env_get( name ));
wchar_t *blarg;
/*
Variable description is 'Variable: VALUE
*/
blarg = wcsdupcat2( &name[varlen], COMPLETE_SEP_STR, COMPLETE_VAR_DESC_VAL, value, 0 );
wchar_t *value_unescaped, *value;
if( blarg )
value_unescaped = env_get( name );
if( value_unescaped )
{
res =1;
al_push( comp, blarg );
}
free( value );
wchar_t *desc;
value = expand_escape_variable( value_unescaped );
/*
Variable description is 'Variable: VALUE
*/
desc = wcsdupcat2( &name[varlen], COMPLETE_SEP_STR, COMPLETE_VAR_DESC_VAL, value, (void *)0 );
if( desc )
{
res =1;
al_push( comp, desc );
}
free( value );
}
}
}
@@ -1932,7 +1983,7 @@ static int try_complete_user( const wchar_t *cmd,
L"/",
COMPLETE_SEP_STR,
COMPLETE_USER_DESC,
0 );
(void *)0 );
if( blarg != 0 )
{
al_push( comp, blarg );
@@ -1965,6 +2016,8 @@ void complete( const wchar_t *cmd,
CHECK( cmd, );
CHECK( comp, );
complete_init();
// debug( 1, L"Complete '%ls'", cmd );
cursor_pos = wcslen(cmd );
@@ -2107,6 +2160,14 @@ void complete( const wchar_t *cmd,
int do_file;
do_file = complete_param( current_command, prev_token, current_token, comp );
/*
If we have found no command specific completions at
all, fall back to using file completions.
*/
if( !al_get_count( comp ) )
do_file = 1;
complete_param_expand( current_token, comp, do_file );
}
}
@@ -2142,11 +2203,13 @@ static void append_switch( string_buffer_t *out,
void complete_print( string_buffer_t *out )
{
complete_entry *e;
complete_entry_t *e;
CHECK( out, );
for( e = first_entry; e; e=e->next )
{
complete_entry_opt *o;
complete_entry_opt_t *o;
for( o= e->first_option; o; o=o->next )
{
wchar_t *modestr[] =

View File

@@ -66,16 +66,6 @@
*/
#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.9,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,140 +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 lrand48_r)
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 _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)
@@ -357,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 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,5 +1,4 @@
\section and and - Conditionally execute a command
\section and and - conditionally execute a command
\subsection and-synopsis Synopsis
<tt>COMMAND1; and COMMAND2</tt>
@@ -7,10 +6,14 @@
\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
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, if the

View File

@@ -1,17 +1,17 @@
\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.
@@ -30,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,5 +1,4 @@
\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>

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,16 +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>

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,13 +17,14 @@ 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. Do NOT edit this file manually!
\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!
/tmp/fishd.socket.USERNAME the socket which fishd uses to communicate
\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

@@ -5,14 +5,13 @@
\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.
- <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
@@ -25,11 +24,12 @@ end
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

@@ -11,7 +11,7 @@ This builtin command is used to print or erase functions.
- <code>-d DESCRIPTION</code> or <code>--description=DESCRIPTION</code> change the description of this function
- <code>-e</code> or <code>--erase</code> causes the specified functions to be erased.
- <code>-h</code> or <code>--help</code> display a help message and exit
- <code>-n</code> or <code>--names</code> list only the names of all defined functions
- <code>-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.
The default behavior of \c functions when called with no arguments,

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.

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>

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,15 +1,19 @@
\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, if the

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,8 +1,7 @@
\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...] return [STATUS]; [COMMANDS...] end</tt>
<tt>function NAME; [COMMANDS...;] return [STATUS]; [COMMANDS...;] end</tt>
\subsection return-description Description
@@ -17,9 +16,11 @@ function.
\subsection return-example Example
The following code is an implementation of the false command as a fish function
<p>
<pre>function false
return 1
end</pre>
</p>
<pre>
function false
return 1
end
</pre>

View File

@@ -1,12 +1,14 @@
\section set set - Handle environment variables.
\section set set - handle environment variables.
\subsection set-synopsis Synopsis
<pre>set [SCOPE_OPTIONS]
<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>
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>.
@@ -15,7 +17,7 @@ The <code>set</code> builtin causes fish to assign the variable <code>VARIABLE_N
- <code>-l</code> or <code>--local</code> forces the specified environment variable to be given a scope that is local to the current block, even if a variable with the given name exists and is non-local
- <code>-g</code> or <code>--global</code> causes the specified environment variable to be given a global scope. Non-global variables disappear when the block they belong to ends
- <code>-U</code> or <code>--universal</code> causes the specified environment variable to be given a universal scope. If this option is supplied, the variable will be shared between all the current users fish instances on the current computer, and will be preserved across restarts of the shell.
- <code>-n</code> or <code>--names</code> List only the names of all defined variables
- <code>-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>-x</code> or <code>--export</code> causes the specified environment variable to be exported to child processes

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>

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>

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.

78
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.log.%s; end"
#define FISHD_CMD L"fishd ^/tmp/fishd.log.%s"
/**
Value denoting a null string
@@ -305,16 +309,17 @@ 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 )
{
debug( 0, _(L"Changing language to English") );
@@ -447,11 +452,34 @@ static void setup_path()
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 );
@@ -463,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"" );
@@ -550,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()
@@ -678,7 +718,7 @@ int env_set( const wchar_t *key,
env_universal_set( key, val, export );
is_universal = 1;
}
else
{
@@ -706,6 +746,7 @@ int env_set( const wchar_t *key,
(var_mode & ENV_GLOBAL) )
{
node = ( var_mode & ENV_GLOBAL )?global_env:top;
}
else
{
@@ -931,7 +972,7 @@ wchar_t *env_get( const wchar_t *key )
wchar_t *item;
CHECK( key, 0 );
if( wcscmp( key, L"history" ) == 0 )
{
wchar_t *current;
@@ -946,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;
}
@@ -962,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 )

7
env.h
View File

@@ -80,8 +80,8 @@ void env_destroy();
*/
int env_set( const wchar_t *key,
const wchar_t *val,
int mode );
const wchar_t *val,
int mode );
/**
@@ -94,7 +94,7 @@ 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
@@ -129,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
@@ -190,7 +193,7 @@ static void check_connection()
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();
}
}
@@ -208,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 )
@@ -222,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()
@@ -255,17 +254,11 @@ void env_universal_destroy()
{
wperror( L"fcntl" );
}
try_send_all( &env_universal_server );
try_send_all( &env_universal_server );
}
if( close( env_universal_server.fd ) )
{
wperror( L"close" );
}
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;
}
@@ -279,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();
@@ -308,7 +299,6 @@ wchar_t *env_universal_get( const wchar_t *name )
CHECK( name, 0 );
debug( 3, L"env_universal_get( \"%ls\" )", name );
return env_universal_common_get( name );
}
@@ -319,7 +309,6 @@ int env_universal_get_export( const wchar_t *name )
CHECK( name, 0 );
debug( 3, L"env_universal_get_export()" );
return env_universal_common_get_export( name );
}
@@ -363,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
*/

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 );
}
@@ -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 );
}
}
}
@@ -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;
@@ -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,11 +690,11 @@ 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;
@@ -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;
}
@@ -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,110 +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 red
set_default fish_color_error red --bold
set_default fish_color_escape cyan
set_default fish_color_operator cyan
set_default fish_color_quote brown
set_default fish_color_valid_path --underline
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

30
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"
/**
@@ -391,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 )
{
@@ -444,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
*/
@@ -473,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 )
@@ -510,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;
@@ -533,7 +543,7 @@ static void event_fire_delayed()
free( blocked );
blocked = new_blocked;
}
while( sig_list[active_list].count > 0 )
{
signal_list_t *lst;
@@ -594,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 )

255
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;
@@ -94,13 +101,12 @@ void exec_close( int fd )
{
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;
@@ -130,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;
}
@@ -176,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 );
@@ -270,7 +276,7 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
case IO_FILE:
{
if( (tmp=wopen( io->param1.filename,
io->param2.flags, 0777 ) )==-1 )
io->param2.flags, BASE_MASK ) )==-1 )
{
debug( 1,
FILE_ERROR,
@@ -439,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 );
@@ -523,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,
@@ -574,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;
}
@@ -605,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" );
@@ -634,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 )
{
@@ -669,8 +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;
@@ -679,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 )
{
/*
@@ -699,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;
@@ -716,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
@@ -742,7 +822,7 @@ void exec( job_t *j )
{
mypipe[1]=-1;
skip_fork=0;
pipe_write.fd = p->pipe_fd;
/*
@@ -792,18 +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] )));
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 );
@@ -811,7 +900,7 @@ void exec( job_t *j )
if( p->next )
{
io_buffer = io_buffer_create();
io_buffer = io_buffer_create( 0 );
j->io = io_add( j->io, io_buffer );
}
@@ -827,7 +916,7 @@ void exec( job_t *j )
{
if( p->next )
{
io_buffer = io_buffer_create();
io_buffer = io_buffer_create( 0 );
j->io = io_add( j->io, io_buffer );
}
@@ -835,7 +924,7 @@ void exec( job_t *j )
break;
}
case INTERNAL_BUILTIN:
{
int builtin_stdin=0;
@@ -865,7 +954,7 @@ void exec( job_t *j )
case IO_FILE:
{
builtin_stdin=wopen( in->param1.filename,
in->param2.flags, 0777 );
in->param2.flags, BASE_MASK );
if( builtin_stdin == -1 )
{
debug( 1,
@@ -915,8 +1004,8 @@ void exec( job_t *j )
builtin_out_redirect = has_fd( j->io, 1 );
builtin_err_redirect = has_fd( j->io, 2 );
fg = j->fg;
j->fg = 0;
fg = job_get_flag( j, JOB_FOREGROUND );
job_set_flag( j, JOB_FOREGROUND, 0 );
signal_unblock();
@@ -929,7 +1018,7 @@ void exec( job_t *j )
false during builtin execution so as not to confuse
some job-handling builtins.
*/
j->fg = fg;
job_set_flag( j, JOB_FOREGROUND, fg );
}
if( close_stdin )
@@ -945,6 +1034,7 @@ void exec( job_t *j )
switch( p->type )
{
case INTERNAL_BLOCK:
case INTERNAL_FUNCTION:
{
@@ -964,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;
@@ -1014,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;
}
@@ -1025,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:
{
@@ -1065,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;
@@ -1125,7 +1255,7 @@ void exec( job_t *j )
p->pid = getpid();
setup_child_process( j, p );
launch_process( p );
/*
launch_process _never_ returns...
*/
@@ -1181,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" );
@@ -1190,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;
}
@@ -1218,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 );
/**

411
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
*/
@@ -575,12 +596,9 @@ static int expand_pid( wchar_t *in,
array_list_t *out )
{
if( !in || !out)
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
CHECK( in, 0 );
CHECK( out, 0 );
if( *in != PROCESS_EXPAND )
{
al_push( out, in );
@@ -637,8 +655,8 @@ static int expand_pid( wchar_t *in,
free( in );
else
{
*in = L'%';
al_push( out, in );
free(in);
return 0;
}
}
else
@@ -649,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.
@@ -674,12 +818,9 @@ 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;
if( !in || !out)
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
CHECK( in, 0 );
CHECK( out, 0 );
if( !var_tmp )
{
var_tmp = sb_halloc( global_context );
@@ -735,43 +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 );
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;
}
@@ -785,44 +891,22 @@ 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 ) )
{
long 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 )
{
tokenize_variable_array( var_val, &var_item_list );
@@ -831,12 +915,17 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
int j;
for( j=0; j<al_get_count( var_idx_list ); j++)
{
long tmp = (long)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,
@@ -848,12 +937,11 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
}
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 */
/* 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 */
@@ -1002,13 +1090,10 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
wchar_t *item_begin;
int len1, len2, tot_len;
if( !in || !out)
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
CHECK( in, 0 );
CHECK( out, 0 );
for( pos=in;
(*pos) && !syntax_error;
pos++ )
@@ -1127,23 +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 )
{
wchar_t *paran_begin=0, *paran_end=0;
int len1, len2;
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;
CHECK( in, 0 );
CHECK( out, 0 );
if( !in || !out)
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
switch( parse_util_locate_cmdsubst(in,
&paran_begin,
@@ -1163,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, &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 );
@@ -1217,12 +1356,8 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
}
free(in);
al_destroy( &sub_res );
al_foreach( &tail_expand, &free );
al_destroy( &tail_expand );
free( subcmd );
al_foreach( tail_expand, &free );
halloc_free( context );
return 1;
}
@@ -1246,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;
@@ -1332,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 )
{
@@ -1376,7 +1515,7 @@ 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 );
@@ -1393,7 +1532,7 @@ int expand_string( void *context,
al_init( &list1 );
al_init( &list2 );
if( EXPAND_SKIP_SUBSHELL & flags )
if( EXPAND_SKIP_CMDSUBST & flags )
{
wchar_t *begin, *end;
@@ -1402,7 +1541,7 @@ int expand_string( void *context,
&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 );
@@ -1412,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;

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,26 +112,6 @@ enum
/** String containing the character for separating two array elements */
#define ARRAY_SEP_STR L"\x1e"
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_DESC _( L"The '$' character begins a variable name. The character '%lc', which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_NULL_DESC _( L"The '$' begins a variable name. It was given at the end of an argument. Variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'.")
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_BRACKET_DESC _( L"Did you mean {$VARIABLE}? The '$' character begins a variable name. A bracket, which directly followed a '$', is not allowed as a part of a variable name, and variable names may not be zero characters long. To learn more about variable expansion in fish, type 'help expand-variable'." )
/**
Error issued on invalid variable name
*/
#define COMPLETE_VAR_PARAN_DESC _( L"Did you mean (COMMAND)? In fish, the '$' character is only used for accessing variables. To learn more about command substitution in fish, type 'help expand-command-substitution'.")
/**
Error issued on array out of bounds
*/
@@ -142,7 +122,7 @@ enum
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
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
@@ -155,11 +135,11 @@ enum
\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. 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
@@ -171,7 +151,7 @@ int expand_string( void *context, wchar_t *in, array_list_t *out, int flag );
\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 );
@@ -207,4 +187,17 @@ wchar_t *expand_tilde(wchar_t *in);
*/
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,14 +1006,6 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
#endif
#ifdef HAVE_BROKEN_DEL_CURTERM
int del_curterm(TERMINAL *oterm)
{
}
#endif
#ifndef HAVE_LRAND48_R
int lrand48_r(struct drand48_data *buffer, long int *result)
@@ -1029,6 +1030,64 @@ int futimes(int fd, const struct timeval *times)
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

@@ -9,6 +9,8 @@
#include <wchar.h>
#include <limits.h>
#include <sys/time.h>
#include <sys/types.h>
#include <signal.h>
#ifndef WCHAR_MAX
/**
@@ -43,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
/**
@@ -290,7 +310,7 @@ 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
@@ -310,18 +330,96 @@ struct drand48_data
/**
Fallback implementation of lrand48_r. Internally uses rand_r, so it is pretty weak.
*/
int lrand48_r(struct drand48_data *buffer, long int *result);
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);
int srand48_r( long int seedval, struct drand48_data *buffer );
#endif
#ifndef HAVE_FUTIMES
int futimes(int fd, const struct timeval *times);
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

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: 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,7 +140,13 @@ 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;
/**
@@ -129,16 +181,27 @@ typedef struct
}
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;
}
@@ -146,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;
@@ -159,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;
@@ -182,6 +255,9 @@ static int try_sequence( char *seq )
return 0;
}
/**
Read a character from keyboard
*/
static wint_t readch()
{
struct mapping
@@ -241,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]) )
@@ -276,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;
@@ -409,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,
@@ -420,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
*/
@@ -440,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) );
@@ -531,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 */
@@ -569,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();
@@ -675,7 +769,7 @@ static int completion_try_print( int cols,
case R_NULL:
{
do_loop=0;
res=2;
res=PAGER_RESIZE;
break;
}
@@ -864,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"" );
@@ -881,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" );
@@ -897,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;
@@ -916,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,
@@ -938,72 +1058,165 @@ 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 );

View File

@@ -88,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
*/
@@ -120,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]++;
@@ -130,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" );
@@ -152,7 +144,7 @@ static void pq_test( int elements )
*/
static int stack_test( int elements )
{
int i;
long i;
int res=1;
@@ -162,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;
@@ -177,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;
}
}
}
@@ -198,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;
}
@@ -219,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;
@@ -230,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;
@@ -273,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",
@@ -297,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 )
@@ -486,43 +476,43 @@ static void test_parser()
say( L"Testing null input to parser" );
if( !parser_test( 0, 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, 0 ) )
if( !parser_test( L"if; end", 0, 0, 0 ) )
{
err( L"Incomplete if statement undetected" );
}
if( !parser_test( L"if test; echo", 0, 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, 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, 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, 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, 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, 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, 0 ) || !parser_test( L"echo|return", 0, 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" );
}
@@ -555,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 );
@@ -577,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;
}
@@ -642,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();
@@ -664,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();
@@ -696,7 +690,6 @@ int main( int argc, char **argv )
parser_init();
function_init();
builtin_init();
complete_init();
reader_init();
env_init();
@@ -718,7 +711,6 @@ int main( int argc, char **argv )
parser_destroy();
function_destroy();
builtin_destroy();
complete_destroy();
wutil_destroy();
event_destroy();
proc_destroy();

156
fishd.c
View File

@@ -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
@@ -98,7 +103,7 @@ time the original barrier request was sent have been received.
/**
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
@@ -386,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 );
@@ -410,15 +500,19 @@ void load_or_save( int save)
strcat( name, "/" );
strcat( name, FILE );
strcat( name, hostname );
free( dir );
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" );
@@ -426,9 +520,7 @@ void load_or_save( int save)
}
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 )
{
@@ -439,9 +531,7 @@ void load_or_save( int save)
else
read_message( &c );
q_destroy( &c.unsent );
sb_destroy( &c.input );
close( c.fd );
connection_destroy( &c );
}
/**
@@ -485,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"" );
@@ -494,7 +586,6 @@ int main( int argc, char ** argv )
*/
while( 1 )
{
#ifdef HAVE_GETOPT_LONG
static struct option
long_options[] =
{
@@ -520,11 +611,6 @@ int main( int argc, char ** argv )
long_options,
&opt_index );
#else
int opt = getopt( argc,
argv,
GETOPT_STRING );
#endif
if( opt == -1 )
break;
@@ -553,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 );
@@ -611,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;
@@ -660,9 +742,6 @@ int main( int argc, char ** argv )
{
debug( 4, L"Close connection %d", c->fd );
close(c->fd );
sb_destroy( &c->input );
while( !q_empty( &c->unsent ) )
{
message_t *msg = (message_t *)q_get( &c->unsent );
@@ -671,7 +750,7 @@ int main( int argc, char ** argv )
free( msg );
}
q_destroy( &c->unsent );
connection_destroy( c );
if( prev )
{
prev->next=c->next;
@@ -692,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"
@@ -44,10 +44,6 @@ typedef struct
Line where definition started
*/
int definition_offset;
/**
Flag for specifying functions which are actually key bindings
*/
int is_binding;
/**
Flag for specifying that this function was automatically loaded
@@ -169,8 +165,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 )
{
int i;
wchar_t *cmd_end;
@@ -186,13 +181,8 @@ void function_add( const wchar_t *name,
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;
@@ -319,9 +309,7 @@ static void get_names_internal( void *key,
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 );
}
@@ -365,7 +353,6 @@ const wchar_t *function_get_definition_file( const wchar_t *argv )
CHECK( argv, 0 );
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return 0;
@@ -380,7 +367,6 @@ int function_get_definition_offset( const wchar_t *argv )
CHECK( argv, -1 );
load( argv );
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.

View File

@@ -24,9 +24,12 @@
#define HALLOC_BLOCK_SIZE 128
/**
Maximum size of trailing halloc space to refuse to discard
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 16
#define HALLOC_SCRAP_SIZE (4*sizeof(void *))
#ifdef HALLOC_DEBUG
/**
@@ -71,24 +74,32 @@ typedef struct halloc
/**
Amount of free space in the scratch area
*/
size_t scratch_free;
#if __STDC_VERSION__ < 199901L
/**
The actual data. MAde to be of type long long to make sure memory alignment is in order.
*/
long long data[1]; // Waste one byte on non-C99 compilers... :-(
#else
long long data[];
#endif
ssize_t scratch_free;
}
halloc_t;
static void *align_ptr( void *in )
{
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) - sizeof( halloc_t ) );
return (halloc_t *)(((char *)data) - align_sz(sizeof( halloc_t ) ));
}
/**
@@ -104,7 +115,7 @@ static void late_free( void *data)
statistics, like number of allocations and number of internal calls
to malloc.
*/
static void woot()
static void halloc_report()
{
if( getpid() == pid )
{
@@ -115,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;
@@ -169,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,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"
@@ -32,6 +32,8 @@
#include "output.h"
#include "halloc.h"
#include "halloc_util.h"
#include "wildcard.h"
#include "path.h"
/**
Number of elements in the highlight_var array
@@ -102,6 +104,9 @@ static int is_potential_path( const wchar_t *path )
case BRACKET_BEGIN:
case BRACKET_END:
case BRACKET_SEP:
case ANY_CHAR:
case ANY_STRING:
case ANY_STRING_RECURSIVE:
{
has_magic = 1;
break;
@@ -132,7 +137,10 @@ static int is_potential_path( const wchar_t *path )
{
dir = wopendir( unescaped );
res = !!dir;
closedir( dir );
if( dir )
{
closedir( dir );
}
}
else
{
@@ -552,8 +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:
@@ -579,10 +586,10 @@ void highlight_shell( wchar_t * buff,
{
wchar_t *dir = expand_one( context,
wcsdup(tok_last( &tok )),
EXPAND_SKIP_SUBSHELL );
EXPAND_SKIP_CMDSUBST );
if( dir )
{
if( !parser_cdpath_get( context, dir ) )
if( !path_get_cdpath( context, dir ) )
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
}
@@ -605,7 +612,7 @@ void highlight_shell( wchar_t * buff,
*/
cmd = expand_one( context,
wcsdup(tok_last( &tok )),
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
if( cmd == 0 )
{
@@ -617,7 +624,7 @@ void highlight_shell( wchar_t * buff,
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 );
@@ -665,13 +672,13 @@ void highlight_shell( wchar_t * buff,
/*
Check if this is a regular command
*/
is_cmd |= !!(tmp=parser_get_filename( context, cmd ));
is_cmd |= !!(tmp=path_get_path( context, cmd ));
/*
Could not find the command. Maybe it is
a path for a implicit cd command.
*/
is_cmd |= !!(tmp=parser_cdpath_get( context, cmd ));
is_cmd |= !!(tmp=path_get_cdpath( context, cmd ));
if( is_cmd )
{
@@ -680,7 +687,7 @@ 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;
@@ -722,9 +729,9 @@ void highlight_shell( wchar_t * buff,
{
case TOK_STRING:
{
target = expand_one( context, 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.
*/
}
@@ -754,7 +761,7 @@ 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 ) );
}
}
@@ -770,7 +777,7 @@ 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 ) );
}
}
}
@@ -825,7 +832,7 @@ void highlight_shell( wchar_t * buff,
tok_destroy( &tok );
/*
Locate and syntax highlight subshells recursively
Locate and syntax highlight cmdsubsts recursively
*/
wchar_t *buffcpy = halloc_wcsdup( context, buff );
@@ -956,7 +963,7 @@ 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
@@ -966,7 +973,7 @@ static void highlight_universal_internal( wchar_t * buff,
long pos1, pos2;
level--;
pos1 = (long)al_pop( &l );
pos1 = al_pop_long( &l );
pos2 = str-buff;
if( pos1==pos || pos2==pos )
{
@@ -980,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;
}
}

1399
history.c

File diff suppressed because it is too large Load Diff

View File

@@ -43,7 +43,7 @@ wchar_t *history_get( int idx );
void history_first();
/**
Make current point to last history item
Make current point to last history item
*/
void history_reset();
@@ -61,7 +61,7 @@ const wchar_t *history_next_match( const wchar_t *str);
of the history.
*/
void history_set_mode( wchar_t *name );
void history_set_mode( const wchar_t *name );
/**

166
input.c
View File

@@ -17,7 +17,15 @@ implementation in fish is as of yet incomplete.
#include <termios.h>
#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 <unistd.h>
#include <wchar.h>
@@ -59,7 +67,7 @@ implementation in fish is as of yet incomplete.
#include "expand.h"
#include "event.h"
#include "signal.h"
#include "translate.h"
#include "output.h"
#include "intern.h"
@@ -115,13 +123,17 @@ static const wchar_t *name_arr[] =
L"kill-word",
L"backward-kill-word",
L"dump-functions",
L"clear-screen",
L"winch",
L"exit",
L"history-token-search-backward",
L"history-token-search-forward",
L"self-insert",
L"null",
L"eof"
L"eof",
L"vi-arg-digit",
L"execute",
L"beginning-of-buffer",
L"end-of-buffer"
}
;
@@ -159,7 +171,8 @@ static const wchar_t *desc_arr[] =
L"Search forward through list of previous commands for matching token",
L"Insert the pressed key",
L"Do nothing",
L"End of file"
L"End of file",
L"Repeat command"
}
;
*/
@@ -190,13 +203,17 @@ static const wchar_t code_arr[] =
R_KILL_WORD,
R_BACKWARD_KILL_WORD,
R_DUMP_FUNCTIONS,
R_CLEAR_SCREEN,
R_WINCH,
R_EXIT,
R_HISTORY_TOKEN_SEARCH_BACKWARD,
R_HISTORY_TOKEN_SEARCH_FORWARD,
R_SELF_INSERT,
R_NULL,
R_EOF
R_EOF,
R_VI_ARG_DIGIT,
R_EXECUTE,
R_BEGINNING_OF_BUFFER,
R_END_OF_BUFFER,
}
;
@@ -238,6 +255,19 @@ static int inputrc_error = 0;
*/
static int is_init = 0;
/**
This is the variable telling us how many timew the next command
should bne repeated. Only actually used in vi-mode.
*/
static int repeat_count = 1;
/**
This is the type of the first command in a vi-mode two-part combo
like 'dw' or '3d3l'.
*/
static wint_t first_command = 0;
wchar_t input_get_code( const wchar_t *name )
{
@@ -998,7 +1028,7 @@ void input_parse_inputrc_line( wchar_t *cmd )
{
if( wcscmp( key, L"editing-mode" ) == 0 )
{
// current_mode_mappings = get_mapping( value );
current_mode_mappings = get_mapping( value );
}
}
@@ -1198,6 +1228,14 @@ static void add_common_bindings()
*/
for( i=0; i<3; i++ )
{
add_mapping( name[i], L"\n", L"Execute contents of commandline", L"execute" );
/*
This will make Meta-newline insert a newline, since
self-insert ignored the escape character unless it is the
only character of the sequence.
*/
add_mapping( name[i], L"\e\n", L"Meta-newline", L"self-insert" );
/*
We need alternative keybidnings for arrowkeys, since
terminfo sometimes specifies a different sequence than what
@@ -1263,6 +1301,7 @@ static void add_common_bindings()
add_escaped_mapping( name[i], (L"\\C-y"), L"Control-y", L"yank" );
add_mapping( name[i], L"", L"Any key", L"self-insert" );
}
}
/**
@@ -1286,6 +1325,8 @@ static void add_emacs_bindings()
add_escaped_mapping( L"emacs", (L"\ed"), L"Alt-d", L"forward-kill-word" );
add_terminfo_mapping( L"emacs", (key_ppage), L"Page Up", L"beginning-of-history" );
add_terminfo_mapping( L"emacs", (key_npage), L"Page Down", L"end-of-history" );
add_escaped_mapping( L"emacs", (L"\e<"), L"Alt-<", L"beginning-of-buffer" );
add_escaped_mapping( L"emacs", (L"\e>"), L"Alt->", L"end-of-buffer" );
}
/**
@@ -1305,12 +1346,29 @@ static void add_vi_bindings()
add_mapping( L"vi-command", L"$", L"$", L"end-of-line" );
add_mapping( L"vi-command", L"^", L"^", L"beginning-of-line" );
add_mapping( L"vi-command", L"0", L"0", L"beginning-of-line" );
add_mapping( L"vi-command", L"b", L"b", L"backward-word" );
add_mapping( L"vi-command", L"B", L"B", L"backward-word" );
add_mapping( L"vi-command", L"w", L"w", L"forward-word" );
add_mapping( L"vi-command", L"W", L"W", L"forward-word" );
add_mapping( L"vi-command", L"x", L"x", L"delete-char" );
add_mapping( L"vi-command", L"1", L"1", L"vi-arg-digit" );
add_mapping( L"vi-command", L"2", L"2", L"vi-arg-digit" );
add_mapping( L"vi-command", L"3", L"3", L"vi-arg-digit" );
add_mapping( L"vi-command", L"4", L"4", L"vi-arg-digit" );
add_mapping( L"vi-command", L"5", L"5", L"vi-arg-digit" );
add_mapping( L"vi-command", L"6", L"6", L"vi-arg-digit" );
add_mapping( L"vi-command", L"7", L"7", L"vi-arg-digit" );
add_mapping( L"vi-command", L"8", L"8", L"vi-arg-digit" );
add_mapping( L"vi-command", L"9", L"9", L"vi-arg-digit" );
add_mapping( L"vi-command", L"d", L"d", L"vi-delete-to" );
add_mapping( L"vi-command", L"D", L"D", L"vi-delete-to" );
/*
movement ("h", "l"), word movement
("b", "B", "w", "W", "e", "E"), moving to beginning and end of line
@@ -1349,7 +1407,7 @@ static int interrupt_handler()
/*
Tell the reader an event occured
*/
if( reader_interupted() )
if( reader_interrupted() )
{
/*
Return 3, i.e. the character read by a Control-C.
@@ -1357,7 +1415,7 @@ static int interrupt_handler()
return 3;
}
return 0;
return R_WINCH;
}
int input_init()
@@ -1370,7 +1428,7 @@ int input_init()
is_init = 1;
input_common_init( &interrupt_handler );
if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
{
debug( 0, _( L"Could not set up terminal" ) );
@@ -1448,7 +1506,11 @@ void input_destroy()
hash_foreach( &all_mappings, &destroy_mapping );
hash_destroy( &all_mappings );
del_curterm( cur_term );
if( del_curterm( cur_term ) == ERR )
{
debug( 0, _(L"Error while closing terminfo") );
}
}
/**
@@ -1456,23 +1518,81 @@ void input_destroy()
*/
static wint_t input_exec_binding( mapping *m, const wchar_t *seq )
{
int i;
// fwprintf( stderr, L"Binding %ls\n", m->command );
wchar_t code = input_get_code( m->command );
if( code != -1 )
{
switch( code )
{
case R_DUMP_FUNCTIONS:
{
dump_functions();
for( i=0; i<repeat_count; i++ )
dump_functions();
repeat_count = 1;
return R_NULL;
}
case R_SELF_INSERT:
{
return seq[0];
int idx = 0;
if( seq[0] == L'\e' && seq[1] )
{
idx = 1;
}
for( i=1; i<repeat_count; i++ )
input_unreadch( seq[idx] );
repeat_count = 1;
return seq[idx];
}
case R_VI_ARG_DIGIT:
{
int repeat = seq[0]-L'0';
if( repeat > 0 && repeat <= 9 )
repeat_count *= repeat;
return R_NULL;
}
case R_VI_DELETE_TO:
{
first_command = R_VI_DELETE_TO;
return R_NULL;
}
default:
{
if( first_command )
{
switch( first_command )
{
case R_VI_DELETE_TO:
{
break;
}
}
}
else
{
for( i=1; i<repeat_count; i++ )
{
input_unreadch( code );
}
}
repeat_count = 1;
first_command = 0;
return code;
}
}
}
else
@@ -1511,6 +1631,13 @@ static wint_t input_try_mapping( mapping *m)
{
int j, k;
wint_t c=0;
c = input_common_readch( 0 );
if( c == input_get_code( m->command ) )
{
return input_exec_binding( m, m->seq );
}
input_unreadch( c );
if( m->seq != 0 )
{
@@ -1524,9 +1651,14 @@ static wint_t input_try_mapping( mapping *m)
}
else
{
/*
Return the read characters
*/
input_unreadch(c);
for(k=j-1; k>=0; k--)
input_unreadch(m->seq[k]);
for( k=j-1; k>=0; k-- )
{
input_unreadch( m->seq[k] );
}
}
}
return 0;
@@ -1547,7 +1679,7 @@ wint_t input_readch()
/*
Clear the interrupted flag
*/
reader_interupted();
reader_interrupted();
/*
Search for sequence in various mapping tables

View File

@@ -39,11 +39,16 @@ enum
R_KILL_WORD,
R_BACKWARD_KILL_WORD,
R_DUMP_FUNCTIONS,
R_CLEAR_SCREEN,
R_WINCH,
R_EXIT,
R_HISTORY_TOKEN_SEARCH_BACKWARD,
R_HISTORY_TOKEN_SEARCH_FORWARD,
R_SELF_INSERT,
R_VI_ARG_DIGIT,
R_VI_DELETE_TO,
R_EXECUTE,
R_BEGINNING_OF_BUFFER,
R_END_OF_BUFFER
}
;

View File

@@ -14,7 +14,9 @@ Implementation file for the low level input library
#include <sys/types.h>
#include <unistd.h>
#include <wchar.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include "fallback.h"
#include "util.h"
@@ -34,7 +36,7 @@ Implementation file for the low level input library
/**
Characters that have been read and returned by the sequence matching code
*/
static wint_t lookahead_arr[32];
static wint_t lookahead_arr[1024];
/**
Number of entries in lookahead_arr
@@ -184,7 +186,7 @@ wchar_t input_common_readch( int timed )
int sz;
if( (b == R_NULL) || (b == R_EOF) )
if( (b >= R_NULL) && (b < R_NULL + 1000) )
return b;
bb=b;

View File

@@ -31,6 +31,8 @@ static hash_table_t *intern_static_table=0;
const wchar_t *intern( const wchar_t *in )
{
const wchar_t *res=0;
// debug( 0, L"intern %ls", in );
if( !in )
return 0;

34
io.c
View File

@@ -12,7 +12,15 @@ Utilities for io redirection.
#include <string.h>
#include <errno.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 <unistd.h>
#include <fcntl.h>
@@ -39,15 +47,14 @@ Utilities for io redirection.
#include "exec.h"
#include "common.h"
#include "io.h"
#include "translate.h"
#include "halloc.h"
void io_buffer_read( io_data_t *d )
{
exec_close(d->param1.pipe_fd[1] );
if( d->io_mode == IO_BUFFER )
{
/* if( fcntl( d->param1.pipe_fd[0], F_SETFL, 0 ) )
@@ -93,16 +100,17 @@ void io_buffer_read( io_data_t *d )
}
io_data_t *io_buffer_create()
io_data_t *io_buffer_create( int is_input )
{
io_data_t *buffer_redirect = malloc( sizeof( io_data_t ));
buffer_redirect->io_mode=IO_BUFFER;
buffer_redirect->next=0;
buffer_redirect->param2.out_buffer= malloc( sizeof(buffer_t));
buffer_redirect->is_input = is_input;
b_init( buffer_redirect->param2.out_buffer );
buffer_redirect->fd=1;
buffer_redirect->fd=is_input?0:1;
if( exec_pipe( buffer_redirect->param1.pipe_fd ) == -1 )
{
debug( 1, PIPE_ERROR );
@@ -126,7 +134,16 @@ io_data_t *io_buffer_create()
void io_buffer_destroy( io_data_t *io_buffer )
{
/**
If this is an input buffer, then io_read_buffer will not have
been called, and we need to close the output fd as well.
*/
if( io_buffer->is_input )
{
exec_close(io_buffer->param1.pipe_fd[1] );
}
exec_close( io_buffer->param1.pipe_fd[0] );
/*
@@ -221,8 +238,7 @@ void io_print( io_data_t *io )
return;
}
debug( 1, L"IO fd %d, type ",
io->fd );
debug( 1, L"IO fd %d, type ", io->fd );
switch( io->io_mode )
{
case IO_PIPE:

11
io.h
View File

@@ -44,6 +44,8 @@ typedef struct io_data
} param2
;
int is_input;
/** Pointer to the next IO redirection */
struct io_data *next;
@@ -80,9 +82,14 @@ void io_buffer_destroy( io_data_t *io_buffer );
/**
Create a IO_BUFFER type io redirection, complete with a pipe and a
buffer_t for output.
buffer_t for output. The default file descriptor used is 1 for
output buffering and 0 for input buffering.
\param is_input set this parameter to zero if the buffer should be
used to buffer the output of a command, or non-zero to buffer the
input to a command.
*/
io_data_t *io_buffer_create();
io_data_t *io_buffer_create( int is_input );
/**
Close output pipe, and read from input pipe until eof.

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