Compare commits

...

102 Commits

Author SHA1 Message Date
axel
6d0b6e5de5 Bump version number to 1.21.0
darcs-hash:20060225022220-ac50b-27a71eef149c0caa5336d425f24686ce152dcad1.gz
2006-02-25 12:22:20 +10:00
axel
fd6bf06f15 Various minor edits
darcs-hash:20060225022139-ac50b-9ef43f88e2266978e9b39038a6a5087ff1305509.gz
2006-02-25 12:21:39 +10:00
axel
d2e11ea61d Fix crash bug on invalid input to fish_pager
darcs-hash:20060224184050-ac50b-da122d893fa0e2aabbd48058c696e2815c4657ca.gz
2006-02-25 04:40:50 +10:00
axel
dad2b93d1e Add functiopn prototype completions for valgrind --alloc-fn
darcs-hash:20060224135618-ac50b-bcd2fa57593f6a5c9f41b9513ac25f859baf1659.gz
2006-02-24 23:56:18 +10:00
axel
1075ca69b0 Switch to standard syntax for octal escapes
darcs-hash:20060224121829-ac50b-8e19f27857378e6456ae08269721138bd60f3464.gz
2006-02-24 22:18:29 +10:00
axel
e29f5c5474 Add an FAQ section to the documentation, and remove a few seactions of the manual containing introductory material on fish which was no longer accurate
darcs-hash:20060224011446-ac50b-e9246e23dbf725a3e2488f7831b1c7420cdd42db.gz
2006-02-24 11:14:46 +10:00
axel
22bfa6638a Update of the makefile on how to handle the directory hierarchy transition
darcs-hash:20060223153556-ac50b-4af8c2376a37c28f056b7fef37db3fb371a3e899.gz
2006-02-24 01:35:56 +10:00
axel
1a48941f6b Protect against double-free of the process argument list
darcs-hash:20060222175107-ac50b-87c36439e2ec2f8be652db1595dad9a09e20f36c.gz
2006-02-23 03:51:07 +10:00
axel
68e0c94dbb Do not unescape strings from completion callouts. Why was this done before?
darcs-hash:20060222174716-ac50b-218c6896918e5cf8047ea6291a8cde44061d0b57.gz
2006-02-23 03:47:16 +10:00
axel
ca04fc745d Add some input validation code to various functions
darcs-hash:20060222154152-ac50b-608032284165f099beecd1cd4f7c6bb2b45df432.gz
2006-02-23 01:41:52 +10:00
axel
3afead1827 Documentation clarification for the cd builtin
darcs-hash:20060222142137-ac50b-cc9200ed23fa5796a56dc4ee3dde1ff7e8768fc3.gz
2006-02-23 00:21:37 +10:00
axel
0ea69dab7b Drop unuses error counter for string conversions
darcs-hash:20060222142042-ac50b-25f2e050c680071ccec6989e477f6db5904a2713.gz
2006-02-23 00:20:42 +10:00
axel
a4a025b786 Allow multiple slashes in a wildcard to be used as a single directory separator
darcs-hash:20060221154738-ac50b-e4b35d3604d8e39d3aff7b8da38617272bd6e89e.gz
2006-02-22 01:47:38 +10:00
axel
328c3a39a1 Move _ shellscript function to it's own file
darcs-hash:20060221153701-ac50b-05cecdac1221e0abc709d9e9c1799faa7986fa78.gz
2006-02-22 01:37:01 +10:00
axel
5aa019a0b5 Fix off-by-one error resulting in truncated output from wcsndup fallback and halloc_wcsndup
darcs-hash:20060221144642-ac50b-9dcd77238bc4bd740bbda6e15ded793fad44c363.gz
2006-02-22 00:46:42 +10:00
axel
92aa99104a Fix rare accidental ellipsisizing of strings that will actually fit in fish_pager
darcs-hash:20060221103435-ac50b-f46a08e29e7860886a357bc1c5d314b594793e68.gz
2006-02-21 20:34:35 +10:00
axel
6b544bc3c2 API documentation, code style cleanup, etc.
darcs-hash:20060220131146-ac50b-6ec3664e5e3eaefa2296a93d39014058df37fdf2.gz
2006-02-20 23:11:46 +10:00
axel
ea0005e16d Move code for setting ls and grep colors to function definition files
darcs-hash:20060220130203-ac50b-feb426f6450a0bbd17cb9dacdca94d4d5b72c113.gz
2006-02-20 23:02:03 +10:00
axel
6901ad361d Make fish continue parsing/executing a file if a command is not found
darcs-hash:20060220125524-ac50b-1f85e530cbbcb45988254c75cd45c11395c5cd27.gz
2006-02-20 22:55:24 +10:00
axel
b21cccf5f0 A flag got reversed, causing children to execute even if an IO redirection failed
darcs-hash:20060220014036-ac50b-43156940397e0535cfa9dd7e88d61e4ca4bab13b.gz
2006-02-20 11:40:36 +10:00
axel
7740035d14 Remove some ancient debug messages, drop two warnings, add some braces and other minor code tweaks
darcs-hash:20060219181932-ac50b-2d032e7a64257a6ca0db078ea9c81ae04a01120f.gz
2006-02-20 04:19:32 +10:00
axel
7dc3934997 Use variable name as index for tables when autoloading functions and completions in order to better handle changes on path variable values
darcs-hash:20060219170116-ac50b-8f617c6f8960660e6227827914dc910a78655c13.gz
2006-02-20 03:01:16 +10:00
axel
845e15876c Minor edits, additional comments, etc.
darcs-hash:20060219015438-ac50b-b6346876460912f3c27d1bb4287aeab962260ab6.gz
2006-02-19 11:54:38 +10:00
axel
c4e7a7992f Fix bug causing fish to occasionally reset line number for error reporting
darcs-hash:20060219011702-ac50b-c72b1f5ae56d3757c3fbfca002f1bc33c36a7660.gz
2006-02-19 11:17:02 +10:00
axel
43ab84397b Make sure that command specific completions can handle input strings with wildcards reasonably well
darcs-hash:20060219011432-ac50b-89a73a3d414f2dbd8a213b851fcb1c494e022eae.gz
2006-02-19 11:14:32 +10:00
axel
0840c9248f Give more detail in an error message
darcs-hash:20060218024346-ac50b-f26f6ef107fffa398b6ff61baff81914b998940a.gz
2006-02-18 12:43:46 +10:00
axel
dd79d75504 Move a few shellscript bits around
darcs-hash:20060218024145-ac50b-207ca782808ea8968cb38253c7bc2563350f38b2.gz
2006-02-18 12:41:45 +10:00
axel
7073f0b58b Change translation file offsets in swedish translation, needed to avoid darcs hang
darcs-hash:20060218023559-ac50b-bf6f5802b7ab810a3a8167f92358c085e3f02401.gz
2006-02-18 12:35:59 +10:00
axel
15916bfbdc Update build dependencies
darcs-hash:20060218023432-ac50b-9cfdc633f4b6834dea4324f429b1decca6d9e110.gz
2006-02-18 12:34:32 +10:00
axel
228fdbef5a Use the right sources for generating translation strings
darcs-hash:20060218023332-ac50b-5a2cec156ad5c49d052f17cf14fd14e72e0aa137.gz
2006-02-18 12:33:32 +10:00
axel
7f7f8fb156 Fix broken call to source /fish/fish on startup
darcs-hash:20060217223236-ac50b-384ea2549a2bbf445842700e693f5edc8bf72023.gz
2006-02-18 08:32:36 +10:00
axel
2ae9735858 Add the LGPL license to the license section of the documentation - xdgmime is released under this license. Also add a few rulers, and make some other minor edits to the license section.
darcs-hash:20060217222051-ac50b-8fc2e6d4e32d0f7f67cde8ff475ec0e16f72ffa1.gz
2006-02-18 08:20:51 +10:00
axel
8ac1688c89 Allow backslash-escaping of newlines
darcs-hash:20060217164119-ac50b-6efd2491fb7f504ad26ca35b2a7421d24c61ec63.gz
2006-02-18 02:41:19 +10:00
axel
9cd2dbc9e7 Remove note about problem with ancient fish version
darcs-hash:20060217125341-ac50b-8f4dc873c8b7146cfdae00b62a139c0643e4156e.gz
2006-02-17 22:53:41 +10:00
axel
a74055bc33 Proper ordering on paths for dynamic loading - user stuff should override sysadmin stuff should overrtide default stuff
darcs-hash:20060217125318-ac50b-f74103958cf01103b351227ae561703ac96ebe95.gz
2006-02-17 22:53:18 +10:00
axel
e1d0b9370e Minor edits in parse_util.c
darcs-hash:20060217125205-ac50b-f3cd1572eec966581730ee1983d06b64caac566f.gz
2006-02-17 22:52:05 +10:00
axel
5dfa28059e Remove dropped fish_function.fish from Makefile
darcs-hash:20060217103540-ac50b-5ea95b93bd93512100e652e2cd8146d4f2fdbf58.gz
2006-02-17 20:35:40 +10:00
axel
7ead45d899 More missing files
darcs-hash:20060217103214-ac50b-f0f65a28d574e6a7258148fd1162677be287e99c.gz
2006-02-17 20:32:14 +10:00
axel
5c9ac72c19 Add missing files
darcs-hash:20060217103018-ac50b-9097f60908d06d89f235d969719fe654117b423e.gz
2006-02-17 20:30:18 +10:00
axel
343cafef34 Redo installation file structure, move lots of things to $PREFIX/share/fish
darcs-hash:20060217101339-ac50b-d93d2c620a4b7f75f05ff461a6edbee001da7613.gz
2006-02-17 20:13:39 +10:00
axel
95a01f3c8f Use plgin support in output.c to make buffered pager output - noticably faster printing in many situations
darcs-hash:20060216142159-ac50b-2c31025be7d12fcc32f4ba352b59ea4cc3cc1387.gz
2006-02-17 00:21:59 +10:00
axel
cfa367f14c Finish support for plugging in a new output function for output.c
darcs-hash:20060216142100-ac50b-06db798debb56c7640f7ffec0bc32c8ca7b013e5.gz
2006-02-17 00:21:00 +10:00
axel
94cae410f3 Move the move_cursor and writeb functions to output.c, and make the output function used by output.c configurable
darcs-hash:20060216134025-ac50b-360d4816ee2c3f2ffdc8e5660502cb97b31d699e.gz
2006-02-16 23:40:25 +10:00
axel
cc69afc4fe Fix bug in fish causing occasionally incorrect signal handlers
darcs-hash:20060216133632-ac50b-f24c049830f9c6deca50aca640189ad3f87b630a.gz
2006-02-16 23:36:32 +10:00
axel
777a559e12 Use env to work around path issues on the shebang line for the seq fallback implementation
darcs-hash:20060216121617-ac50b-6c7e34329a5ca8f3cd6756f1860fa10693db21e4.gz
2006-02-16 22:16:17 +10:00
axel
0427ccbb55 Fix invalid destruction order on exit
darcs-hash:20060215222513-ac50b-f3b489568e4bad3532c36f9c66a3c0d61352cd5b.gz
2006-02-16 08:25:13 +10:00
axel
f9a4699147 Add swedish translation of function descriptions
darcs-hash:20060215180031-ac50b-f21e471c178610b7a2912f82b3d46b46f76d350c.gz
2006-02-16 04:00:31 +10:00
axel
e6e287ae1f Make function descriptions for dynamically loaded functions translatable
darcs-hash:20060215175925-ac50b-5dc52c615650779771a6c4a3c5d006b72dbca67d.gz
2006-02-16 03:59:25 +10:00
axel
143602e5f6 Minor edits
darcs-hash:20060215024900-ac50b-51863879c32660d9787db706c34fef10aa4c30c2.gz
2006-02-15 12:49:00 +10:00
axel
1c2d3583e7 Drop fuction from man completion file, already lives in it's own file
darcs-hash:20060215024822-ac50b-dbb1e3769f0b3101f634d4bf5f5e530aacc1dfda.gz
2006-02-15 12:48:22 +10:00
axel
e58110da2c Reset list of loaded completion files when running complete_destroy. Otherwise completions will not get propely loaded on language changes.
darcs-hash:20060215024644-ac50b-d259cdac14dccb55309a4702683f1b881636e9ac.gz
2006-02-15 12:46:44 +10:00
axel
0d1683edc8 Add missing function prototype in parse_util.h
darcs-hash:20060215022415-ac50b-a6510213a3559c7bd6b944bbe87c739faaef4792.gz
2006-02-15 12:24:15 +10:00
axel
c94b9e504d Remove the rather stupid -y option for complete, which loads another commands completions. Mostly the same results can be had with fewer bugs and corner cases vy using the new dynamically loaded functions.
darcs-hash:20060215022228-ac50b-85614ed684f73460d43543a579ff2c7e7914efeb.gz
2006-02-15 12:22:28 +10:00
axel
8be3bf3e5d Add support for checking current filename and current line nuber to status builtin
darcs-hash:20060214195747-ac50b-77b6aba42c99da4f79ea500c47cc00bba12ec663.gz
2006-02-15 05:57:47 +10:00
axel
3e165297ce Add support for sending arguments whenusing the source builtin
darcs-hash:20060214195636-ac50b-511c211368103df6923d63cef99ce20a88d31be3.gz
2006-02-15 05:56:36 +10:00
axel
7ac922def6 Fix timestap checking bug when autoloading scripts
darcs-hash:20060214195517-ac50b-3d084f351c5d1f4f11afb4fc1c706c843de98da1.gz
2006-02-15 05:55:17 +10:00
axel
f12127c775 Add missing translation string
darcs-hash:20060214114804-ac50b-1ce10e7613ebec38a283cd6f6f8ad08397cec529.gz
2006-02-14 21:48:04 +10:00
axel
73d84fe136 Escape semicolons and other chars that have syntactic meaning in various shell command situations
darcs-hash:20060214114739-ac50b-17616bf01a0504041c0d29ee9428abd8a9f9ad3a.gz
2006-02-14 21:47:39 +10:00
axel
c595448f9c Add missing #define, needed by new fish_pager code
darcs-hash:20060214114631-ac50b-39756b670fd0ab1f5a6bd067ba2ff3f9d6f82fc2.gz
2006-02-14 21:46:31 +10:00
axel
5a2aeb1511 Swedish translation checkin
darcs-hash:20060214113926-ac50b-86926878d127405be8a3acd8cf9ac36a56ea432e.gz
2006-02-14 21:39:26 +10:00
axel
5fb9d9aa38 Fix clash in usage of unicode private use area
darcs-hash:20060214113514-ac50b-5160e3b7ac9401a7ef198121d39e33225df4b766.gz
2006-02-14 21:35:14 +10:00
axel
8258961c29 Fix minor display bugs and a memory leak in fish_pager
darcs-hash:20060214113347-ac50b-302a7da47f9c07af3acc9a2dcc5c8007127fc3a2.gz
2006-02-14 21:33:47 +10:00
axel
0dab94a54c Group multiple switches with common description together when printing completions
darcs-hash:20060214000823-ac50b-2bde1ac964baf12a515d763a076434757ac9fd21.gz
2006-02-14 10:08:23 +10:00
axel
3097f71abd Initial checkin of german translation
darcs-hash:20060213215118-ac50b-7981b89adff210e5b53cc18cdc0ad6f1c865cd83.gz
2006-02-14 07:51:18 +10:00
axel
ea5e1b70db Fix memory leak and missing error check in dynamic function lookup
darcs-hash:20060213214416-ac50b-2bd8532aed600c06234e6fce500c737fcb415a5c.gz
2006-02-14 07:44:16 +10:00
axel
6b393d35a9 Spelling fixes from HJB
darcs-hash:20060213213659-ac50b-024e99d5c3a56d1c7308bf5cc291e032aa65bc0e.gz
2006-02-14 07:36:59 +10:00
axel
a5dde6021c Change a few chars to be long
darcs-hash:20060213111023-ac50b-5ad5ddf9beb72117fc1dc81c048a83e5480bc510.gz
2006-02-13 21:10:23 +10:00
axel
a015472739 Remova a few calls to free that are handled by halloc now
darcs-hash:20060213110929-ac50b-95bba1b70840ef16e45f3876c5d0521a51b90561.gz
2006-02-13 21:09:29 +10:00
axel
6affa4452b Check for translation strings in function files
darcs-hash:20060212222406-ac50b-10424c1daeb9e81054c87bbf8f7839da72cb05bb.gz
2006-02-13 08:24:06 +10:00
axel
7ebfa380dd Variable used for filenmae length was accidentally set to static
darcs-hash:20060212222313-ac50b-1893f4fbe52a8c72ebc8332b1e575c1b8a2b31d5.gz
2006-02-13 08:23:13 +10:00
axel
370336e7c7 Fix various minor misses in moving of shellscript functions
darcs-hash:20060212222205-ac50b-d7bccc4c1e1dd752ca40560e81309bb37bb4dca8.gz
2006-02-13 08:22:05 +10:00
axel
bad4269dc9 Remove trailing periods from descriptions
darcs-hash:20060212221918-ac50b-d2310f6a166b585b242a9b548b1d1f890cac2e03.gz
2006-02-13 08:19:18 +10:00
axel
effe6f47a3 Minor hallocifications
darcs-hash:20060212190301-ac50b-c15b9a8c6c2897189c4343946d9bd115eefb4972.gz
2006-02-13 05:03:01 +10:00
axel
7eb3a5a17d Allow backslash of quotes within quotes
darcs-hash:20060212161331-ac50b-c25affaa4b18e1654dab3d08debafa95017009ea.gz
2006-02-13 02:13:31 +10:00
axel
b6cd723eb7 Fix a few compiler warnings, add halloc debug output on exit if HALLOC_DEBUG is defined and other minor tweaks
darcs-hash:20060212131846-ac50b-128685d1c043697768be70631c736567544abf2c.gz
2006-02-12 23:18:46 +10:00
axel
a2cd8c8a8d Move a few more shellscript functions to their own files
darcs-hash:20060212131421-ac50b-861f8941af76cf9a1e6fb7da2ac7f33795fab272.gz
2006-02-12 23:14:21 +10:00
axel
3b03bd6a10 Check if curses-string 'flash_screen' is set before using it in fish_pager
darcs-hash:20060212131253-ac50b-39c03e4223e66230c9c76a59bc95eeadc38637c9.gz
2006-02-12 23:12:53 +10:00
Nicholas Pilon
6caff2d85d svn completions
Command-line completions for svn. This includes some tweaks to the cvs completions file, to move a common function out into fish_complete.fish.

darcs-hash:20060210004314-494f2-c12a77084499cbc4216e8c5603ae4fadfb6b384c.gz
2006-02-10 10:43:14 +10:00
axel
eeaa241be8 Optimizations of how variable expansion implementation
darcs-hash:20060212112930-ac50b-9b8bb640ef1a5bd14230ecd276167a80d6d986c9.gz
2006-02-12 21:29:30 +10:00
axel
8fdb4d2a17 Define fish_function_path at the top of the first init file to improve preformance (each non-existing variable causes a universal variable barrier)
darcs-hash:20060212112349-ac50b-51956f701d11ae897c560617e4b476fb51b576c7.gz
2006-02-12 21:23:49 +10:00
axel
7c7f744b4c Add %o, %x and %X formats to *wprintf fallback implemnentation
darcs-hash:20060212112030-ac50b-1e3153c25dca3d2e12a8eb0e65da29bf70fa0d2e.gz
2006-02-12 21:20:30 +10:00
axel
5718ea41df Add comment in manual about array base index
darcs-hash:20060211001546-ac50b-cebbcd5ca6709c8370433abf366c0aa318ec48ec.gz
2006-02-11 10:15:46 +10:00
axel
20c83ba605 Optimize the halloc implementation so that mutiple calls to halloc can be satisfied by a single malloc, also add wcsdup and wcsndup workalikes using halloc
darcs-hash:20060211001317-ac50b-c9cf234c334b4d697fe1251c21013c8ec7f7b0a1.gz
2006-02-11 10:13:17 +10:00
axel
e9e32f980b Re-add check for presense of ncurses.h header file
darcs-hash:20060211001050-ac50b-434f0d6ea015325f75f27aaebbc54d4b81f18a2c.gz
2006-02-11 10:10:50 +10:00
axel
4b2cc49aaa Registered wrong string with halloc in expand_one, causing potential crash.
darcs-hash:20060210003539-ac50b-523cbc848435b7f2b4239cc83da897cc65c00c1c.gz
2006-02-10 10:35:39 +10:00
axel
28f65c07b0 Use consistent quoting in wgetopt
darcs-hash:20060209215120-ac50b-4dda64a6791be33b6493899714485d55372ca8ea.gz
2006-02-10 07:51:20 +10:00
axel
18279c3867 make sure fish_tests is deleted on make clean
darcs-hash:20060209215101-ac50b-48d6e4ffa276e55e0ab896040a7070294061a4ce.gz
2006-02-10 07:51:01 +10:00
axel
d1c9bca2e9 Another halloc:ification of fish. Halloc has been extended to allow registering function calls, this has allowed the creation of halloc-handled arraylists, stringbuffers, etc. More job parsing halloc-ification has reduced the error handling code to only a shadow of it's former self
darcs-hash:20060209155020-ac50b-e119c5293ce2368e252cfc01b98ab7c629fdd678.gz
2006-02-10 01:50:20 +10:00
axel
49973b85da Add source documentation for functions in parse_util.h
darcs-hash:20060208184737-ac50b-e86de902a966621501eea1b706b181bcda91fb61.gz
2006-02-09 04:47:37 +10:00
axel
47373c4f68 Fix bug where recursive function loading crashed fish
darcs-hash:20060208184437-ac50b-c6b2001fbab07ac9561ba7aa941fbab0d93d7cd7.gz
2006-02-09 04:44:37 +10:00
axel
cbf1dbaa2e Add missing fish_tests file to make clean
darcs-hash:20060208180342-ac50b-a4cf2411534c8c1bd3db335152d4615f951529c8.gz
2006-02-09 04:03:42 +10:00
axel
fdaa79416a Make sure dynamically loaded functions are completable, even if they have not yet been loaded
darcs-hash:20060208173718-ac50b-40c93b82f3b8a717d220642e22c4b4005d8871d0.gz
2006-02-09 03:37:18 +10:00
axel
7c3700c190 Fix crash bug caused by trying to free halloc:ed memory
darcs-hash:20060208153904-ac50b-f8b3d2aadb12fa1e6aca0c4ca7a6046a09a0450d.gz
2006-02-09 01:39:04 +10:00
axel
a0e1f9113e Do not use CDPATH when completing arguments starting with a '.'
darcs-hash:20060208152909-ac50b-650092242a4d9454db6cf4d73858c137040db4c5.gz
2006-02-09 01:29:09 +10:00
axel
133b682793 New wreaddir function, wide character version of readdir
darcs-hash:20060208145847-ac50b-0e250edb67dd095e90054ed55f88a2638ba9b02a.gz
2006-02-09 00:58:47 +10:00
axel
824f4ee566 Make the __fish_describe_command function strip spaces and newlines
darcs-hash:20060208102236-ac50b-6df5b077a09eda9180a1405305e12fd15967eb31.gz
2006-02-08 20:22:36 +10:00
axel
1cb9b65744 Fis function signature for a few functions in parser.c
darcs-hash:20060208102203-ac50b-5e81c6580302ca3a1cee0d03f179b5d75ff61be3.gz
2006-02-08 20:22:03 +10:00
axel
35dde5de15 Move more functions to autoload
darcs-hash:20060208102043-ac50b-4e26615523a6b9528c2ea4768f41ad1b2e1c4a0f.gz
2006-02-08 20:20:43 +10:00
Nicholas Pilon
4d9bb19467 cvs completions
Better completions for cvs. Covers most flags in the manual, except for some for history that I couldn't write good descriptions for. Descriptions could probably use some tweaking, but the basic structure should be much better than what we had before.

darcs-hash:20060208023146-494f2-bea009421c161257f09c0f53c52ab1ee116fc3dc.gz
2006-02-08 12:31:46 +10:00
axel
2555353161 Make 'exit' work in even handlers
darcs-hash:20060208092429-ac50b-f88534a423dc194fdb6453d66b5d4cc7733e54fb.gz
2006-02-08 19:24:29 +10:00
axel
73a9c8bcb8 Autoloaded functions
darcs-hash:20060208092005-ac50b-8e784f79a4e158c8c15b553fad85002dccc7bd03.gz
2006-02-08 19:20:05 +10:00
Nicholas Pilon
47b652c76e Awk Indent Fix
Indented the awk script for command description.

darcs-hash:20060208004201-494f2-2f08b1b7999c690bd1815b6c1702529c932b364d.gz
2006-02-08 10:42:01 +10:00
263 changed files with 17862 additions and 6722 deletions

View File

@@ -48,25 +48,25 @@ datadir = @datadir@
bindir = @bindir@
mandir = @mandir@
sysconfdir = @sysconfdir@
fishdir = @fishdir@
fishfile = @fishfile@
fishinputfile = @fishinputfile@
docdir = @docdir@
#Init files to install
INIT_DIR_INSTALL = init/fish_interactive.fish init/fish_function.fish init/fish_complete.fish
#etc files to install
ETC_DIR_INSTALL = etc/fish_interactive.fish
# Set to 1 if we have gettext
HAVE_GETTEXT=@HAVE_GETTEXT@
CORE_OBJS := util.o common.o halloc.o halloc_util.o
# All objects used by fish, that are compiled from an ordinary .c file
# using an ordinary .h file.
COMMON_OBJS := function.o builtin.o common.o complete.o env.o exec.o \
COMMON_OBJS := function.o builtin.o complete.o env.o exec.o \
expand.o highlight.o history.o kill.o parser.o proc.o reader.o \
sanity.o tokenizer.o util.o wildcard.o wgetopt.o wutil.o input.o \
sanity.o tokenizer.o wildcard.o wgetopt.o wutil.o input.o \
output.o intern.o env_universal.o env_universal_common.o \
input_common.o event.o signal.o io.o translate.o parse_util.o \
halloc.o
$(CORE_OBJS)
# builtin_help.h exists, but builtin_help.c is autogenerated
COMMON_OBJS_WITH_HEADER := builtin_help.o
@@ -80,21 +80,21 @@ FISH_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \
$(COMMON_OBJS_WITH_HEADER) main.o
# All objects that the system needs to build fish_pager
FISH_PAGER_OBJS := fish_pager.o common.o output.o util.o wutil.o \
FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \
tokenizer.o input_common.o env_universal.o env_universal_common.o \
translate.o halloc.o
translate.o $(CORE_OBJS)
# All objects that the system needs to build fish_tests
FISH_TESTS_OBJS := $(COMMON_OBJS) $(COMMON_OBJS_WITH_CODE) \
$(COMMON_OBJS_WITH_HEADER) fish_tests.o
# All objects that the system needs to build fishd
FISHD_OBJS := fishd.o env_universal_common.o common.o util.o wutil.o \
doc_src/fishd.o halloc.o
FISHD_OBJS := fishd.o env_universal_common.o wutil.o \
doc_src/fishd.o $(CORE_OBJS)
# All objects needed to build mimedb
MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o halloc.o
MIME_OBJS := mimedb.o xdgmimealias.o xdgmime.o xdgmimeglob.o \
xdgmimeint.o xdgmimemagic.o xdgmimeparent.o wutil.o
#
# Files containing documentation for builtins. Should be listed
@@ -160,16 +160,20 @@ MAIN_DIR_FILES := Doxyfile Doxyfile.user Makefile.in configure \
user_doc.head.html xsel-0.9.6.tar ChangeLog config.sub \
config.guess fish_tests.c main.c fish_pager.c fishd.c seq.in
# Files in ./init/
INIT_DIR_FILES :=init/fish.in init/fish_complete.fish.in \
init/fish_function.fish init/fish_inputrc \
init/fish_interactive.fish.in
# Files in ./etc/
ETC_DIR_FILES :=etc/fish.in etc/fish_inputrc \
etc/fish_interactive.fish.in
# Files in ./share/
SHARE_DIR_FILES :=share/fish
# Files in ./tests/
TESTS_DIR_FILES := $(TEST_IN) $(TEST_IN:.in=.out) $(TEST_IN:.in=.err) \
$(TEST_IN:.in=.status) tests/test.fish tests/gen_output.fish
COMPLETIONS_DIR_FILES := $(wildcard init/completions/*.fish)
COMPLETIONS_DIR_FILES := $(wildcard share/completions/*.fish)
FUNCTIONS_DIR_FILES := $(wildcard share/functions/*.fish)
# Programs to build
PROGRAMS:=fish set_color @XSEL@ @SEQ_FALLBACK@ mimedb count fish_pager fishd
@@ -262,10 +266,10 @@ doc.h:$(BUILTIN_DOC_SRC) $(CMD_DOC_SRC) doc_src/doc.hdr
fi
# Create a template translation object
messages.pot: *.c *.h init/*.in init/*.fish init/completions/*.fish seq
messages.pot: *.c *.h etc/*.in share/fish share/completions/*.fish share/functions/*.fish seq
if test $(HAVE_GETTEXT) = 1;then \
xgettext -k_ -kN_ -kcomplete_desc *.c *.h -o messages.pot; \
if ! xgettext -j -k_ -LShell init/*.in init/*.fish init/completions/*.fish seq -o messages.pot; then \
if ! xgettext -j -k_ -LShell etc/*.in share/fish share/completions/*.fish share/functions/*.fish seq -o messages.pot; then \
echo "Your xgettext version is too old to build the messages.pot file"\
rm messages.pot\
false;\
@@ -336,24 +340,54 @@ builtin_help.c: $(BUILTIN_DOC_HDR) doc_src/count.doxygen gen_hdr2 gen_hdr.sh bui
#man -- doc_src/builtin_doc/man/man1/`basename $@ .c`.1 | cat -s | ./gen_hdr2 >>$@
#
# The build rules for installing/uninstalling
# The build rules for installing/uninstalling fish
#
install: all install-translations
# Check for an incompatible installed fish version, and fail with an
# error if found
check-uninstall:
if test -f $(DESTDIR)$(sysconfdir)/fish.d/fish_function.fish -o -f $(DESTDIR)$(sysconfdir)/fish.d/fish_complete.fish; then \
echo;\
echo ERROR;\
echo;\
echo An older fish installation using an incompatible filesystem hierarchy was detected;\
echo You must uninstall this fish version before installing proceeding;\
echo type \'make uninstall-legacy\' to uninstall these files,;\
echo or type \'make force-install\' to force installation.;\
echo The latter may result in a broken installation.;\
echo;\
false;\
fi;
.PHONY: check-uninstall
# Try to install after checking for incompatible installed versions
install: all check-uninstall install-force
.PHONY: install
# Force installation, even in presense of incompatible previous
# version
install-force: all install-translations
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
for i in $(PROGRAMS); do\
$(INSTALL) -m 755 $$i $(DESTDIR)$(bindir) ; \
done;
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)$(fishdir)
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)$(fishdir)/completions
$(INSTALL) -m 644 init/fish $(DESTDIR)$(sysconfdir)$(fishfile)
for i in $(INIT_DIR_INSTALL); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)$(fishdir); \
$(INSTALL) -m 755 -d $(DESTDIR)$(sysconfdir)/fish.d
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/completions
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/functions
$(INSTALL) -m 644 etc/fish $(DESTDIR)$(sysconfdir)/fish
$(INSTALL) -m 644 share/fish $(DESTDIR)$(datadir)/fish
for i in $(ETC_DIR_INSTALL); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)/fish.d; \
done;
for i in $(COMPLETIONS_DIR_FILES); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(sysconfdir)$(fishdir)/completions/; \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/completions/; \
done;
$(INSTALL) -m 644 init/fish_inputrc $(DESTDIR)$(sysconfdir)$(fishinputfile);
for i in $(FUNCTIONS_DIR_FILES); do \
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/functions/; \
done;
$(INSTALL) -m 644 etc/fish_inputrc $(DESTDIR)$(sysconfdir)/fish_inputrc;
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
for i in user_doc/html/* ChangeLog; do \
if test -f $$i; then \
@@ -372,22 +406,48 @@ install: all install-translations
@echo \* use the command \'chsh -s $(DESTDIR)$(bindir)/fish\'.
@echo
@echo Have fun!
.PHONY: install
.PHONY: force-install
# Uninstall this fish version
uninstall: uninstall-translations
for i in $(PROGRAMS); do \
rm -f $(DESTDIR)$(bindir)/$$i; \
done;
rm -f $(DESTDIR)$(bindir)/xsel
rm -f $(DESTDIR)$(sysconfdir)$(fishfile)
rm -f $(DESTDIR)$(sysconfdir)$(fishinputfile)
rm -r $(DESTDIR)$(sysconfdir)$(fishdir)
rm -r $(DESTDIR)$(docdir)
for i in fish.1* @XSEL_MAN@ mimedb.1* fishd.1* set_color.1* count.1*; do \
rm $(DESTDIR)$(mandir)/man1/$$i; \
rm -f $(DESTDIR)$(sysconfdir)/fish
rm -f $(DESTDIR)$(sysconfdir)/fish_inputrc
if test -d $(DESTDIR)$(datadir)/fish; then \
rm -r $(DESTDIR)$(datadir)/fish; \
fi
if test -d $(DESTDIR)$(docdir); then \
rm -r $(DESTDIR)$(docdir);\
fi
for i in fish.1 @XSEL_MAN@ mimedb.1 fishd.1 set_color.1 count.1; do \
rm -f $(DESTDIR)$(mandir)/man1/$$i*; \
done;
.PHONY: uninstall
# Uninstall older fish release. This is not the default uninstall
# since there is a slight chance that it removes a file put in place by
# the sysadmin.
uninstall-legacy: uninstall
rm -f $(DESTDIR)$(sysconfdir)/fish.d/fish_interactive.fish
rm -f $(DESTDIR)$(sysconfdir)/fish.d/fish_complete.fish
rm -f $(DESTDIR)$(sysconfdir)/fish.d/fish_function.fish
if test -d $(DESTDIR)$(sysconfdir)/fish.d/completions; then \
for i in $(COMPLETIONS_DIR_FILES); do \
basename=`basename $$i`; \
if test -f $(DESTDIR)$(sysconfdir)/fish.d/completions/$$basename; then \
rm $(DESTDIR)$(sysconfdir)/fish.d/completions/$$basename; \
fi; \
done; \
fi;
rmdir $(DESTDIR)$(sysconfdir)/fish.d/completions; true
rmdir $(DESTDIR)$(sysconfdir)/fish.d; true
install-translations: $(TRANSLATIONS)
if test $(HAVE_GETTEXT) = 1; then \
for i in $(TRANSLATIONS); do \
@@ -395,13 +455,13 @@ install-translations: $(TRANSLATIONS)
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/locale/`basename $$i .gmo`/LC_MESSAGES/fish.mo; \
echo $(DESTDIR)$(datadir)/locale/`basename $$i .gmo`/LC_MESSAGES/fish.mo;\
done; \
fi
fi;
.PHONY: install-translations
uninstall-translations:
if test $(HAVE_GETTEXT) = 1; then \
for i in $(TRANSLATIONS_SRC); do \
rm -f $(DESTDIR)$(datadir)/locale/`basename $$i .po`/LC_MESSAGES/fish.mo; \
rm -f $(DESTDIR)$(datadir)/locale/*/LC_MESSAGES/fish.mo; \
done; \
fi
.PHONY: uninstall-translations
@@ -450,18 +510,22 @@ depend:
#
# Uses install instead of mkdir so build won't fail if the directory
# exists
fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(INIT_DIR_FILES) $(TEST_DIR_FILES) $(COMPLETIONS_DIR_FILES) ChangeLog
fish-@PACKAGE_VERSION@.tar: $(DOC_SRC_DIR_FILES) $(MAIN_DIR_FILES) $(ETC_DIR_FILES) $(TEST_DIR_FILES) $(SHARE_DIR_FILES) $(FUNCTIONS_DIR_FILES) $(COMPLETIONS_DIR_FILES) ChangeLog
rm -rf fish-@PACKAGE_VERSION@
$(INSTALL) -d fish-@PACKAGE_VERSION@
$(INSTALL) -d fish-@PACKAGE_VERSION@/doc_src
$(INSTALL) -d fish-@PACKAGE_VERSION@/init
$(INSTALL) -d fish-@PACKAGE_VERSION@/init/completions
$(INSTALL) -d fish-@PACKAGE_VERSION@/etc
$(INSTALL) -d fish-@PACKAGE_VERSION@/share
$(INSTALL) -d fish-@PACKAGE_VERSION@/share/completions
$(INSTALL) -d fish-@PACKAGE_VERSION@/share/functions
$(INSTALL) -d fish-@PACKAGE_VERSION@/tests
$(INSTALL) -d fish-@PACKAGE_VERSION@/po
cp -f $(DOC_SRC_DIR_FILES) fish-@PACKAGE_VERSION@/doc_src
cp -f $(MAIN_DIR_FILES) fish-@PACKAGE_VERSION@/
cp -f $(INIT_DIR_FILES) fish-@PACKAGE_VERSION@/init/
cp -f $(COMPLETIONS_DIR_FILES) fish-@PACKAGE_VERSION@/init/completions/
cp -f $(ETC_DIR_FILES) fish-@PACKAGE_VERSION@/etc/
cp -f $(SHARE_DIR_FILES) fish-@PACKAGE_VERSION@/share/
cp -f $(COMPLETIONS_DIR_FILES) fish-@PACKAGE_VERSION@/share/completions/
cp -f $(FUNCTIONS_DIR_FILES) fish-@PACKAGE_VERSION@/share/functions/
cp -f $(TESTS_DIR_FILES) fish-@PACKAGE_VERSION@/tests/
cp -f $(TRANSLATIONS_SRC) fish-@PACKAGE_VERSION@/po/
tar -c fish-@PACKAGE_VERSION@ >fish-@PACKAGE_VERSION@.tar
@@ -489,7 +553,7 @@ rpm: fish-@PACKAGE_VERSION@.tar.bz2
distclean: clean
rm -f fish.spec doc_src/fish.1 doc_src/Doxyfile
rm -f init/fish init/fish_interactive.fish init/fish_complete.fish
rm -f etc/fish etc/fish_interactive.fish share/fish
rm -f config.status config.log config.h Makefile
.PHONY: distclean
@@ -512,83 +576,101 @@ clean:
# DO NOT DELETE THIS LINE -- make depend depends on it.
builtin.o: config.h util.h wutil.h builtin.h function.h complete.h proc.h
builtin.o: io.h parser.h reader.h env.h expand.h common.h wgetopt.h sanity.h
builtin.o: io.h parser.h event.h reader.h env.h common.h wgetopt.h sanity.h
builtin.o: tokenizer.h builtin_help.h wildcard.h input_common.h input.h
builtin.o: intern.h event.h signal.h translate.h
builtin_commandline.o: signal.h config.h util.h builtin.h common.h wgetopt.h
builtin_commandline.o: reader.h proc.h io.h parser.h tokenizer.h
builtin_commandline.o: input_common.h input.h translate.h
builtin.o: intern.h signal.h translate.h halloc.h halloc_util.h parse_util.h
builtin.o: expand.h
builtin_commandline.o: signal.h config.h util.h wutil.h builtin.h common.h
builtin_commandline.o: wgetopt.h reader.h proc.h io.h parser.h event.h
builtin_commandline.o: tokenizer.h input_common.h input.h translate.h
builtin_commandline.o: parse_util.h
builtin_complete.o: signal.h config.h util.h wutil.h builtin.h common.h
builtin_complete.o: complete.h wgetopt.h parser.h proc.h io.h event.h
builtin_complete.o: reader.h translate.h
builtin_help.o: config.h util.h common.h builtin_help.h
builtin_set.o: signal.h config.h util.h builtin.h env.h expand.h common.h
builtin_set.o: wgetopt.h proc.h io.h parser.h translate.h
builtin_set.o: signal.h config.h util.h wutil.h builtin.h env.h expand.h
builtin_set.o: common.h wgetopt.h proc.h io.h parser.h event.h translate.h
builtin_ulimit.o: config.h util.h builtin.h common.h wgetopt.h translate.h
common.o: config.h signal.h util.h wutil.h common.h expand.h proc.h io.h
common.o: wildcard.h parser.h
common.o: config.h util.h wutil.h common.h expand.h proc.h io.h wildcard.h
common.o: parser.h event.h
complete.o: signal.h config.h util.h tokenizer.h wildcard.h proc.h io.h
complete.o: parser.h function.h complete.h builtin.h env.h exec.h expand.h
complete.o: common.h reader.h history.h intern.h translate.h wutil.h
complete.o: parser.h event.h function.h complete.h builtin.h env.h exec.h
complete.o: expand.h common.h reader.h history.h intern.h translate.h
complete.o: parse_util.h halloc_util.h wutil.h
env.o: config.h signal.h util.h wutil.h proc.h io.h common.h env.h sanity.h
env.o: expand.h history.h reader.h parser.h env_universal.h
env.o: env_universal_common.h input_common.h event.h translate.h
env.o: expand.h history.h reader.h parser.h event.h env_universal.h
env.o: env_universal_common.h input_common.h translate.h complete.h
env_universal.o: config.h signal.h util.h common.h wutil.h
env_universal.o: env_universal_common.h env_universal.h
env_universal_common.o: signal.h util.h common.h wutil.h
env_universal_common.o: config.h signal.h util.h common.h wutil.h
env_universal_common.o: env_universal_common.h
event.o: signal.h config.h util.h function.h proc.h io.h parser.h common.h
event.o: event.h translate.h
event.o: signal.h config.h util.h wutil.h function.h proc.h io.h parser.h
event.o: event.h common.h translate.h halloc_util.h
exec.o: signal.h config.h util.h common.h wutil.h proc.h io.h exec.h parser.h
exec.o: builtin.h function.h env.h wildcard.h sanity.h expand.h
exec.o: env_universal.h env_universal_common.h translate.h
exec.o: event.h builtin.h function.h env.h wildcard.h sanity.h expand.h
exec.o: env_universal.h env_universal_common.h translate.h halloc.h
exec.o: halloc_util.h parse_util.h
expand.o: signal.h config.h util.h common.h wutil.h env.h proc.h io.h
expand.o: parser.h expand.h wildcard.h exec.h tokenizer.h complete.h
fishd.o: signal.h util.h common.h wutil.h env_universal_common.h
expand.o: parser.h event.h expand.h wildcard.h exec.h tokenizer.h complete.h
expand.o: translate.h parse_util.h halloc_util.h
fishd.o: config.h signal.h util.h common.h wutil.h env_universal_common.h
fish_pager.o: config.h signal.h util.h wutil.h common.h complete.h output.h
fish_pager.o: input_common.h env_universal.h env_universal_common.h
fish_pager.o: input_common.h env_universal.h env_universal_common.h halloc.h
fish_pager.o: halloc_util.h
fish_tests.o: config.h signal.h util.h common.h proc.h io.h reader.h
fish_tests.o: builtin.h function.h complete.h wutil.h env.h expand.h parser.h
fish_tests.o: tokenizer.h output.h exec.h event.h
function.o: signal.h config.h util.h function.h proc.h io.h parser.h common.h
function.o: intern.h event.h
fish_tests.o: event.h tokenizer.h output.h exec.h halloc_util.h
function.o: signal.h config.h wutil.h util.h function.h proc.h io.h parser.h
function.o: event.h common.h intern.h reader.h parse_util.h env.h expand.h
halloc.o: config.h util.h common.h halloc.h
halloc_util.o: config.h util.h common.h halloc.h
highlight.o: signal.h config.h util.h wutil.h highlight.h tokenizer.h proc.h
highlight.o: io.h parser.h builtin.h function.h env.h expand.h sanity.h
highlight.o: common.h complete.h output.h
highlight.o: io.h parser.h event.h parse_util.h builtin.h function.h env.h
highlight.o: expand.h sanity.h common.h complete.h output.h
history.o: config.h util.h wutil.h history.h common.h reader.h env.h sanity.h
history.o: signal.h
input.o: config.h signal.h util.h wutil.h reader.h proc.h io.h common.h
input.o: sanity.h input_common.h input.h parser.h env.h expand.h event.h
input.o: translate.h
input.o: sanity.h input_common.h input.h parser.h event.h env.h expand.h
input.o: translate.h output.h
input_common.o: config.h util.h common.h wutil.h input_common.h
input_common.o: env_universal.h env_universal_common.h
intern.o: config.h util.h common.h intern.h
intern.o: config.h util.h wutil.h common.h intern.h
io.o: config.h util.h wutil.h exec.h proc.h io.h common.h translate.h
io.o: halloc.h
key_reader.o: input_common.h
kill.o: signal.h config.h util.h wutil.h kill.h proc.h io.h sanity.h common.h
kill.o: env.h expand.h exec.h parser.h
kill.o: env.h exec.h parser.h event.h
main.o: config.h signal.h util.h common.h reader.h builtin.h function.h
main.o: complete.h wutil.h env.h sanity.h proc.h io.h parser.h expand.h
main.o: intern.h exec.h event.h output.h translate.h
main.o: complete.h wutil.h env.h sanity.h proc.h io.h parser.h event.h
main.o: expand.h intern.h exec.h output.h translate.h halloc_util.h
mimedb.o: config.h xdgmime.h util.h
output.o: config.h signal.h util.h wutil.h expand.h common.h output.h
output.o: highlight.h
output.o: halloc_util.h highlight.h
parser.o: signal.h config.h util.h common.h wutil.h proc.h io.h parser.h
parser.o: tokenizer.h exec.h wildcard.h function.h builtin.h builtin_help.h
parser.o: env.h expand.h reader.h sanity.h env_universal.h
parser.o: env_universal_common.h event.h translate.h
parser.o: event.h tokenizer.h exec.h wildcard.h function.h builtin.h
parser.o: builtin_help.h env.h expand.h reader.h sanity.h env_universal.h
parser.o: env_universal_common.h translate.h intern.h parse_util.h halloc.h
parser.o: halloc_util.h
parse_util.o: config.h util.h wutil.h common.h tokenizer.h parse_util.h
parse_util.o: expand.h intern.h exec.h proc.h io.h env.h halloc_util.h
proc.o: config.h signal.h util.h wutil.h proc.h io.h common.h reader.h
proc.o: sanity.h env.h parser.h event.h translate.h
proc.o: sanity.h env.h parser.h event.h translate.h halloc.h halloc_util.h
proc.o: output.h
reader.o: config.h signal.h util.h wutil.h highlight.h reader.h proc.h io.h
reader.o: parser.h complete.h history.h common.h sanity.h env.h exec.h
reader.o: expand.h tokenizer.h kill.h input_common.h input.h function.h
reader.o: output.h translate.h
reader.o: parser.h event.h complete.h history.h common.h sanity.h env.h
reader.o: exec.h expand.h tokenizer.h kill.h input_common.h input.h
reader.o: function.h output.h translate.h parse_util.h
refcount.o: config.h util.h wutil.h common.h refcount.h
sanity.o: signal.h config.h util.h common.h sanity.h proc.h io.h history.h
sanity.o: reader.h kill.h wutil.h
sanity.o: reader.h kill.h wutil.h translate.h
set_color.o: config.h
signal.o: config.h signal.h common.h util.h wutil.h event.h reader.h proc.h
signal.o: io.h translate.h
tokenizer.o: config.h util.h wutil.h tokenizer.h common.h wildcard.h
tokenizer.o: translate.h
translate.o: config.h common.h util.h
translate.o: config.h common.h util.h halloc_util.h
util.o: config.h util.h common.h wutil.h
wgetopt.o: config.h wgetopt.h wutil.h
wgetopt.o: config.h wgetopt.h wutil.h translate.h
wildcard.o: config.h util.h wutil.h complete.h common.h wildcard.h reader.h
wildcard.o: expand.h translate.h
wutil.o: config.h util.h common.h wutil.h

View File

@@ -60,6 +60,9 @@
#include "signal.h"
#include "translate.h"
#include "halloc.h"
#include "halloc_util.h"
#include "parse_util.h"
#include "expand.h"
/**
The default prompt for the read command
@@ -496,7 +499,7 @@ static int builtin_builtin( wchar_t **argv )
al_init( &names );
builtin_get_names( &names );
names_arr = list_to_char_arr( 0, &names );
names_arr = list_to_char_arr( &names );
qsort( names_arr,
al_get_count( &names ),
sizeof(wchar_t *),
@@ -511,7 +514,7 @@ static int builtin_builtin( wchar_t **argv )
L"\n",
(void *)0 );
}
halloc_free( names_arr );
free( names_arr );
al_destroy( &names );
}
return 0;
@@ -813,7 +816,7 @@ static int builtin_functions( wchar_t **argv )
al_init( &names );
function_get_names( &names, show_hidden );
names_arr = list_to_char_arr( 0, &names );
names_arr = list_to_char_arr( &names );
qsort( names_arr,
al_get_count( &names ),
sizeof(wchar_t *),
@@ -845,7 +848,7 @@ static int builtin_functions( wchar_t **argv )
}
}
halloc_free( names_arr );
free( names_arr );
al_destroy( &names );
return 0;
}
@@ -858,7 +861,7 @@ static int builtin_functions( wchar_t **argv )
sb_append( sb_out, _( L"Current function definitions are:\n\n" ) );
al_init( &names );
function_get_names( &names, show_hidden );
names_arr = list_to_char_arr( 0, &names );
names_arr = list_to_char_arr( &names );
qsort( names_arr,
al_get_count( &names ),
sizeof(wchar_t *),
@@ -867,7 +870,7 @@ static int builtin_functions( wchar_t **argv )
{
functions_def( names_arr[i] );
}
halloc_free( names_arr );
free( names_arr );
al_destroy( &names );
break;
}
@@ -924,8 +927,7 @@ static int builtin_function( wchar_t **argv )
woptind=0;
parser_push_block( FUNCTION_DEF );
events=halloc( current_block, sizeof(array_list_t ) );
al_init( events );
events=al_halloc( current_block );
const static struct woption
long_options[] =
@@ -1037,7 +1039,7 @@ static int builtin_function( wchar_t **argv )
if( !e )
die_mem();
e->type = EVENT_VARIABLE;
e->param1.variable = halloc_register( current_block, wcsdup( woptarg ));
e->param1.variable = halloc_wcsdup( current_block, woptarg );
e->function_name=0;
al_push( events, e );
break;
@@ -1160,8 +1162,6 @@ static int builtin_function( wchar_t **argv )
}
}
halloc_register( current_block, events->arr );
if( res )
{
int i;
@@ -1176,7 +1176,7 @@ static int builtin_function( wchar_t **argv )
al_init( &names );
function_get_names( &names, 0 );
names_arr = list_to_char_arr( 0, &names );
names_arr = list_to_char_arr( &names );
qsort( names_arr,
al_get_count( &names ),
sizeof(wchar_t *),
@@ -1194,7 +1194,7 @@ static int builtin_function( wchar_t **argv )
sb_append2( sb_err,
nxt, L" ", (void *)0 );
}
halloc_free( names_arr );
free( names_arr );
al_destroy( &names );
sb_append( sb_err, L"\n" );
@@ -1203,11 +1203,11 @@ static int builtin_function( wchar_t **argv )
}
else
{
current_block->param1.function_name=halloc_register( current_block, wcsdup(argv[woptind]));
current_block->param2.function_description=desc?halloc_register( current_block, wcsdup(desc)):0;
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;
for( i=0; i<al_get_count( events ); i++ )
{
event_t *e = (event_t *)al_get( events, i );
@@ -1613,6 +1613,8 @@ static int builtin_status( wchar_t **argv )
IS_NO_JOB_CONTROL,
STACK_TRACE,
DONE,
CURRENT_FILENAME,
CURRENT_LINE_NUMBER
}
;
@@ -1658,6 +1660,14 @@ static int builtin_status( wchar_t **argv )
L"is-no-job-control", no_argument, &mode, IS_NO_JOB_CONTROL
}
,
{
L"current-filename", no_argument, &mode, CURRENT_FILENAME
}
,
{
L"current-line-number", no_argument, &mode, CURRENT_LINE_NUMBER
}
,
{
L"job-control", required_argument, 0, 'j'
}
@@ -1732,6 +1742,24 @@ static int builtin_status( wchar_t **argv )
switch( mode )
{
case CURRENT_FILENAME:
{
const wchar_t *fn = parser_current_filename();
if( !fn )
fn = _(L"Standard input");
sb_printf( sb_out, L"%ls\n", fn );
break;
}
case CURRENT_LINE_NUMBER:
{
sb_printf( sb_out, L"%d\n", parser_get_lineno() );
break;
}
case IS_INTERACTIVE:
return !is_interactive_session;
@@ -1766,9 +1794,9 @@ static int builtin_status( wchar_t **argv )
else
sb_printf( sb_out, _( L"This is not a login shell\n" ) );
sb_printf( sb_out, _(L"Job control: %ls\n"),
job_control_mode==JOB_CONTROL_INTERACTIVE?_(L"Only on interactive jobs"):
(job_control_mode==JOB_CONTROL_NONE?_(L"Never"):_(L"Always")) );
sb_printf( sb_out, _( L"Job control: %ls\n" ),
job_control_mode==JOB_CONTROL_INTERACTIVE?_( L"Only on interactive jobs" ):
(job_control_mode==JOB_CONTROL_NONE ? _( L"Never" ) : _( L"Always" ) ) );
parser_stack_trace( current_block, sb_out );
break;
@@ -1943,9 +1971,9 @@ static int builtin_source( wchar_t ** argv )
argc = builtin_count_args( argv );
if( argc != 2 )
if( argc < 2 )
{
sb_printf( sb_err, _( L"%ls: Expected exactly one argument, got %d\n" ), argv[0], argc );
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;
}
@@ -1972,7 +2000,7 @@ static int builtin_source( wchar_t ** argv )
{
wchar_t *fn = wrealpath( argv[1], 0 );
const wchar_t *fn_intern;
if( !fn )
{
fn_intern = intern( argv[1] );
@@ -1985,10 +2013,13 @@ static int builtin_source( wchar_t ** argv )
parser_push_block( SOURCE );
reader_push_current_filename( fn_intern );
current_block->param1.source_dest = fn_intern;
parse_util_set_argv( argv+2);
res = reader_read( fd );
parser_pop_block();
if( res )
{
@@ -2010,7 +2041,6 @@ static int builtin_source( wchar_t ** argv )
return res;
}
/**
Make the specified job the first job of the job list. Moving jobs
around in the list makes the list reflect the order in which the
@@ -2545,7 +2575,8 @@ static int builtin_for( wchar_t **argv )
if( argc < 3)
{
sb_printf( sb_err,
_( L"%ls: Expected at least two arguments\n" ),
_( L"%ls: Expected at least two arguments, got %d\n"),
argc ,
argv[0] );
builtin_print_help( argv[0], sb_err );
}
@@ -2581,11 +2612,11 @@ static int builtin_for( wchar_t **argv )
int i;
current_block->tok_pos = parser_get_pos();
current_block->param1.for_variable = halloc_register( current_block, wcsdup( argv[1] ));
current_block->param1.for_variable = halloc_wcsdup( current_block, argv[1] );
for( i=argc-1; i>3; i-- )
{
al_push( &current_block->param2.for_vars, halloc_register( current_block, wcsdup(argv[ i ] ) ) );
al_push( &current_block->param2.for_vars, halloc_wcsdup( current_block, argv[ i ] ) );
}
halloc_register( current_block, current_block->param2.for_vars.arr );
@@ -2901,7 +2932,7 @@ static int builtin_switch( wchar_t **argv )
else
{
parser_push_block( SWITCH );
current_block->param1.switch_value = halloc_register( current_block, wcsdup( argv[1]));
current_block->param1.switch_value = halloc_wcsdup( current_block, argv[1]);
current_block->skip=1;
current_block->param2.switch_taken=0;
}
@@ -2937,8 +2968,10 @@ static int builtin_case( wchar_t **argv )
for( i=1; i<argc; i++ )
{
free( unescaped );
unescaped = unescape( argv[i], 1);
unescaped = parse_util_unescape_wildcards( argv[i] );
if( wildcard_match( current_block->param1.switch_value, unescaped ) )
{
current_block->skip = 0;
@@ -3145,6 +3178,7 @@ void builtin_destroy()
{
hash_destroy( desc );
free( desc );
desc=0;
}
al_destroy( &io_stack );

View File

@@ -27,7 +27,7 @@ const static wchar_t *temporary_buffer;
/*
builtin_complete_* are a set of rather silly looping functions that
make sure that all the proper combinations of complete_add or
complete_remove get called.
complete_remove get called.
*/
static void builtin_complete_add2( const wchar_t *cmd,
@@ -253,7 +253,7 @@ int builtin_complete( wchar_t **argv )
string_buffer_t short_opt;
array_list_t gnu_opt, old_opt;
wchar_t *comp=L"", *desc=L"", *condition=L"", *load=0;
wchar_t *comp=L"", *desc=L"", *condition=L"";
wchar_t *do_complete = 0;
@@ -307,7 +307,8 @@ int builtin_complete( wchar_t **argv )
}
,
{
L"long-option", required_argument, 0, 'l' }
L"long-option", required_argument, 0, 'l'
}
,
{
L"old-option", required_argument, 0, 'o'
@@ -333,10 +334,6 @@ int builtin_complete( wchar_t **argv )
L"condition", required_argument, 0, 'n'
}
,
{
L"load", required_argument, 0, 'y'
}
,
{
L"do-complete", required_argument, 0, 'C'
}
@@ -351,7 +348,7 @@ int builtin_complete( wchar_t **argv )
int opt = wgetopt_long( argc,
argv,
L"a:c:p:s:l:o:d:frxeun:y:C:",
L"a:c:p:s:l:o:d:frxeun:C:",
long_options,
&opt_index );
if( opt == -1 )
@@ -368,6 +365,7 @@ int builtin_complete( wchar_t **argv )
long_options[opt_index].name );
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
@@ -418,25 +416,21 @@ int builtin_complete( wchar_t **argv )
comp = woptarg;
break;
case 'e':
remove = 1;
break;
case 'n':
condition = woptarg;
break;
case 'y':
load = woptarg;
break;
case 'C':
do_complete = woptarg?woptarg:reader_get_buffer();
break;
case '?':
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
res = 1;
@@ -446,90 +440,85 @@ int builtin_complete( wchar_t **argv )
}
if( res != 0 )
if( !res )
{
}
else if( do_complete )
{
array_list_t comp;
int i;
const wchar_t *prev_temporary_buffer = temporary_buffer;
temporary_buffer = do_complete;
if( recursion_level < 1 )
if( do_complete )
{
recursion_level++;
array_list_t comp;
int i;
const wchar_t *prev_temporary_buffer = temporary_buffer;
temporary_buffer = do_complete;
if( recursion_level < 1 )
{
recursion_level++;
al_init( &comp );
complete( do_complete, &comp );
for( i=0; i<al_get_count( &comp ); i++ )
{
wchar_t *next = (wchar_t *)al_get( &comp, i );
wchar_t *sep = wcschr( next, COMPLETE_SEP );
if( sep )
*sep = L'\t';
sb_printf( sb_out, L"%ls\n", next );
}
al_foreach( &comp, (void (*)(const void *))&free );
al_destroy( &comp );
recursion_level--;
}
temporary_buffer = prev_temporary_buffer;
al_init( &comp );
complete( do_complete, &comp );
for( i=0; i<al_get_count( &comp ); i++ )
{
wchar_t *next = (wchar_t *)al_get( &comp, i );
wchar_t *sep = wcschr( next, COMPLETE_SEP );
if( sep )
*sep = L'\t';
sb_printf( sb_out, L"%ls\n", next );
}
al_foreach( &comp, (void (*)(const void *))&free );
al_destroy( &comp );
recursion_level--;
}
temporary_buffer = prev_temporary_buffer;
}
else if( woptind != argc )
{
sb_printf( sb_err,
_( L"%ls: Too many arguments\n" ),
argv[0] );
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
res = 1;
}
else if( load )
{
complete_load( load, 1 );
}
else if( (al_get_count( &cmd) == 0 ) && (al_get_count( &path) == 0 ) )
{
/* No arguments specified, meaning we print the definitions of
* all specified completions to stdout.*/
complete_print( sb_out );
}
else
{
if( remove )
else if( woptind != argc )
{
builtin_complete_remove( &cmd,
&path,
(wchar_t *)short_opt.buff,
&gnu_opt,
&old_opt );
sb_printf( sb_err,
_( L"%ls: Too many arguments\n" ),
argv[0] );
sb_append( sb_err,
parser_current_line() );
// builtin_print_help( argv[0], sb_err );
res = 1;
}
else if( (al_get_count( &cmd) == 0 ) && (al_get_count( &path) == 0 ) )
{
/* No arguments specified, meaning we print the definitions of
* all specified completions to stdout.*/
complete_print( sb_out );
}
else
{
builtin_complete_add( &cmd,
&path,
(wchar_t *)short_opt.buff,
&gnu_opt,
&old_opt,
result_mode,
authorative,
condition,
comp,
desc );
}
}
if( remove )
{
builtin_complete_remove( &cmd,
&path,
(wchar_t *)short_opt.buff,
&gnu_opt,
&old_opt );
}
else
{
builtin_complete_add( &cmd,
&path,
(wchar_t *)short_opt.buff,
&gnu_opt,
&old_opt,
result_mode,
authorative,
condition,
comp,
desc );
}
}
}
al_foreach( &cmd, (void (*)(const void *))&free );
al_foreach( &path, (void (*)(const void *))&free );

211
common.c
View File

@@ -20,7 +20,6 @@ parts of fish.
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <signal.h>
#include <locale.h>
#include <time.h>
#include <sys/time.h>
@@ -58,7 +57,6 @@ parts of fish.
#include "proc.h"
#include "wildcard.h"
#include "parser.h"
#include "halloc.h"
/**
The maximum number of minor errors to report. Further errors will be omitted.
@@ -73,13 +71,6 @@ parts of fish.
struct termios shell_modes;
/**
Number of error encountered. This is reset after each command, and
used to limit the number of error messages on commands with many
string convertion problems.
*/
static int error_count=0;
int error_max=1;
wchar_t ellipsis_char;
@@ -95,20 +86,14 @@ int debug_level=1;
*/
static struct winsize termsize;
/**
Number of nested calls to the block function. Unblock when this reaches 0.
*/
static int block_count=0;
/**
String buffer used by the wsetlocale function
*/
static string_buffer_t *setlocale_buff=0;
void common_destroy()
{
if( setlocale_buff )
{
sb_destroy( setlocale_buff );
@@ -116,9 +101,13 @@ void common_destroy()
}
}
wchar_t **list_to_char_arr( void *context, array_list_t *l )
void common_init()
{
wchar_t ** res = halloc( context, sizeof(wchar_t *)*(al_get_count( l )+1) );
}
wchar_t **list_to_char_arr( array_list_t *l )
{
wchar_t ** res = malloc( sizeof(wchar_t *)*(al_get_count( l )+1) );
int i;
if( res == 0 )
{
@@ -127,40 +116,11 @@ wchar_t **list_to_char_arr( void *context, array_list_t *l )
for( i=0; i<al_get_count( l ); i++ )
{
res[i] = (wchar_t *)al_get(l,i);
if( context )
halloc_register( context, res[i] );
}
res[i]='\0';
return res;
}
void block()
{
block_count++;
if( block_count == 1 )
{
sigset_t chldset;
sigemptyset( &chldset );
sigaddset( &chldset, SIGCHLD );
sigprocmask(SIG_BLOCK, &chldset, 0);
}
}
void unblock()
{
block_count--;
if( block_count == 0 )
{
sigset_t chldset;
sigemptyset( &chldset );
sigaddset( &chldset, SIGCHLD );
sigprocmask(SIG_UNBLOCK, &chldset, 0);
}
}
int fgetws2( wchar_t **b, int *len, FILE *f )
{
int i=0;
@@ -174,8 +134,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
watching for EINTR errors, bytes are lost.
*/
block();
while( 1 )
{
/* Reallocate the buffer if necessary */
@@ -214,8 +172,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
case L'\n':
case L'\0':
buff[i]=L'\0';
unblock();
return i;
/* Ignore carriage returns */
case L'\r':
@@ -228,7 +184,6 @@ int fgetws2( wchar_t **b, int *len, FILE *f )
}
unblock();
}
@@ -254,20 +209,28 @@ void sort_list( array_list_t *comp )
wchar_t *str2wcs( const char *in )
{
wchar_t *out;
size_t res=0;
int in_pos=0;
int out_pos = 0;
size_t len = strlen(in);
mbstate_t state;
out = malloc( sizeof(wchar_t)*(len+1) );
memset( &state, 0, sizeof(state) );
if( !out )
{
die_mem();
}
return str2wcs_internal( in, out );
}
wchar_t *str2wcs_internal( const char *in, wchar_t *out )
{
size_t res=0;
int in_pos=0;
int out_pos = 0;
mbstate_t state;
size_t len = strlen(in);
memset( &state, 0, sizeof(state) );
while( in[in_pos] )
{
res = mbrtowc( &out[out_pos], &in[in_pos], len-in_pos, &state );
@@ -287,6 +250,7 @@ wchar_t *str2wcs( const char *in )
{
return out;
}
default:
{
in_pos += res;
@@ -300,27 +264,28 @@ wchar_t *str2wcs( const char *in )
return out;
}
void error_reset()
{
error_count=0;
}
char *wcs2str( const wchar_t *in )
{
char *out;
size_t res=0;
int in_pos=0;
int out_pos = 0;
mbstate_t state;
out = malloc( MAX_UTF8_BYTES*wcslen(in)+1 );
memset( &state, 0, sizeof(state) );
if( !out )
{
die_mem();
}
return wcs2str_internal( in, out );
}
char *wcs2str_internal( const wchar_t *in, char *out )
{
size_t res=0;
int in_pos=0;
int out_pos = 0;
mbstate_t state;
memset( &state, 0, sizeof(state) );
while( in[in_pos] )
{
if( ( in[in_pos] >= ENCODE_DIRECT_BASE) &&
@@ -550,8 +515,6 @@ int wcsvarname( wchar_t *str )
str++;
}
return 1;
}
@@ -574,12 +537,34 @@ int my_wcswidth( const wchar_t *c )
return res;
}
wchar_t *quote_end( const wchar_t *in )
const wchar_t *quote_end( const wchar_t *pos )
{
return wcschr( in+1, *in );
wchar_t c = *pos;
while( 1 )
{
pos++;
if( !*pos )
return 0;
if( *pos == L'\\')
{
pos++;
}
else
{
if( *pos == c )
{
return pos;
}
}
}
return 0;
}
const wchar_t *wsetlocale(int category, const wchar_t *locale)
{
@@ -642,12 +627,6 @@ int read_blocked(int fd, void *buf, size_t count)
return res;
}
int writeb( tputs_arg_t b )
{
write( 1, &b, 1 );
// putc( b, stdout );
return 0;
}
void die_mem()
{
@@ -938,74 +917,87 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
break;
}
case L'X':
case L'u':
case L'U':
case L'x':
case L'o':
case L'X':
case L'0':
case L'1':
case L'2':
case L'3':
case L'4':
case L'5':
case L'6':
case L'7':
{
int i;
wchar_t res=0;
long long res=0;
int chars=2;
int base=16;
int byte = 0;
int max_val = 127;
switch( in[in_pos] )
{
case L'u':
{
base=16;
chars=4;
max_val = 35535;
break;
}
case L'U':
{
base=16;
chars=8;
max_val = WCHAR_MAX;
break;
}
case L'x':
{
base=16;
chars=2;
break;
}
case L'X':
{
byte=1;
base=16;
chars=2;
max_val = 255;
break;
}
case L'o':
default:
{
base=8;
chars=3;
in_pos--;
break;
}
}
}
for( i=0; i<chars; i++ )
{
int d = convert_digit( in[++in_pos],base);
if( d < 0 )
{
in_pos--;
break;
}
res=(res*base)|d;
}
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
if( (res > 0) && (res <= max_val) )
{
in[out_pos] = (byte?ENCODE_DIRECT_BASE:0)+res;
}
else
{
free(in);
return 0;
}
break;
}
@@ -1160,6 +1152,30 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
*/
case 1:
{
if( c == L'\\' )
{
switch( in[++in_pos] )
{
case L'\'':
{
in[out_pos]=in[in_pos];
break;
}
case 0:
{
free(in);
return 0;
}
default:
{
in[out_pos++] = L'\\';
in[out_pos]= in[in_pos];
}
}
}
if( c == L'\'' )
{
in[out_pos] = INTERNAL_SEPARATOR;
@@ -1198,11 +1214,12 @@ wchar_t *unescape( const wchar_t * orig, int unescape_special )
}
case L'$':
case '"':
{
in[out_pos]=in[in_pos];
break;
}
default:
{
in[out_pos++] = L'\\';

View File

@@ -47,7 +47,7 @@ typedef char tputs_arg_t;
/**
This is in the unicode private use area.
*/
#define ENCODE_DIRECT_BASE 0xf000
#define ENCODE_DIRECT_BASE 0xf100
/**
Save the shell mode on startup so we can restore them on exit
@@ -88,7 +88,7 @@ extern wchar_t *program_name;
is not noll, all elements of the \c array_list_t are also
registered to \c context using \c halloc_register().
*/
wchar_t **list_to_char_arr( void *context, array_list_t *l );
wchar_t **list_to_char_arr( array_list_t *l );
/**
Read a line from the stream f into the buffer buff of length len. If
@@ -114,6 +114,7 @@ void sort_list( array_list_t *comp );
specified multibyte character string
*/
wchar_t *str2wcs( const char *in );
wchar_t *str2wcs_internal( const char *in, wchar_t *out );
/**
Returns a newly allocated multibyte character string equivalent of
@@ -121,6 +122,8 @@ wchar_t *str2wcs( const char *in );
*/
char *wcs2str( const wchar_t *in );
char *wcs2str_internal( const wchar_t *in, char *out );
/**
Returns a newly allocated wide character string array equivalent of
the specified multibyte character string array
@@ -187,7 +190,7 @@ int my_wcswidth( const wchar_t *c );
\param in the position of the opening quote
*/
wchar_t *quote_end( const wchar_t *in );
const wchar_t *quote_end( const wchar_t *in );
/**
A call to this function will reset the error counter. Some
@@ -220,20 +223,18 @@ int contains_str( const wchar_t *needle, ... );
*/
int read_blocked(int fd, void *buf, size_t count);
/**
This is for writing process notification messages. Has to write to
stdout, so clr_eol and such functions will work correctly. Not an
issue since this function is only used in interactive mode anyway.
*/
int writeb( tputs_arg_t b );
/**
Exit program at once, leaving an error message about running out of memory
*/
void die_mem();
/**
Clean up
Create global_context using halloc
*/
void common_init();
/**
Free global_context using halloc_free
*/
void common_destroy();
@@ -262,8 +263,7 @@ void debug( int level, const wchar_t *msg, ... );
\return The escaped string, or 0 if there is not enough memory
*/
wchar_t *escape( const wchar_t *in,
int escape_all );
wchar_t *escape( const wchar_t *in, int escape_all );
/**
Expand backslashed escapes and substitute them with their unescaped
@@ -279,16 +279,6 @@ wchar_t *escape( const wchar_t *in,
wchar_t *unescape( const wchar_t * in,
int escape_special );
/**
Block SIGCHLD. Calls to block/unblock may be nested, and only once the nest count reaches zero wiull the block be removed.
*/
void block();
/**
undo call to block().
*/
void unblock();
/**
Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL
milliseconds between polls and timing out after timeout seconds,

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,8 @@
/** Separateor between completion and description*/
#define COMPLETE_SEP_STR L"\004"
#define COMPLETE_ITEM_SEP L'\uf500'
/**
Character that separates the completion and description on programmable completions
*/
@@ -162,6 +164,6 @@ int complete_is_valid_argument( const wchar_t *str,
\param cmd the command for which to load command-specific completions
\param reload should the commands completions be reloaded, even if they where previously loaded. (This is set to true on actual completions, so that changed completion are updated in running shells)
*/
void complete_load( wchar_t *cmd, int reload );
void complete_load( const wchar_t *cmd, int reload );
#endif

View File

@@ -1,5 +1,5 @@
# Process this file with autoconf to produce a configure script.
AC_INIT(fish,1.20.2,fish-users@lists.sf.net)
AC_INIT(fish,1.21.0,fish-users@lists.sf.net)
for i in /usr/pkg /sw /opt /opt/local; do
@@ -104,10 +104,6 @@ else
AC_SUBST( PREFIX, [$prefix])
fi
AC_SUBST(fishdir,[/fish.d])
AC_SUBST(fishfile,[/fish])
AC_SUBST(fishinputfile,[/fish_inputrc])
AC_ARG_VAR( [docdir], [Documentation direcotry] )
if test -z $docdir; then
@@ -116,7 +112,9 @@ fi
AC_DEFINE_UNQUOTED( DOCDIR, [L"$(eval echo $docdir)"], [Documentation directory] )
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 locale directory
AC_DEFINE_UNQUOTED( [LOCALEDIR], "$(eval echo $datadir)/locale", [Locale directory])
@@ -199,7 +197,7 @@ AC_CHECK_LIB(rt, nanosleep)
AC_CHECK_LIB(intl, gettext)
# Check for various header files
AC_CHECK_HEADERS([getopt.h termio.h sys/resource.h term.h ncurses/term.h libintl.h])
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.])],
@@ -235,7 +233,7 @@ fi
# Check if we have ncurses, and use it rather than curses if possible.
AC_SEARCH_LIBS( setupterm, [ncurses curses], [ AC_MSG_NOTICE([Found curses implementation])], [AC_MSG_ERROR([Could not find a curses implementation, needed to build fish])] )
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile init/fish init/fish_interactive.fish init/fish_complete.fish seq])
AC_CONFIG_FILES([Makefile fish.spec doc_src/fish.1 doc_src/Doxyfile etc/fish etc/fish_interactive.fish seq])
AC_OUTPUT
echo "Now run 'make' and 'make install' to built and install fish."

View File

@@ -3,10 +3,9 @@
\subsection cd-synopsis Synopsis
<tt>cd [DIRECTORY]</tt>
\subsection cd-description Description
Changes the current directory. If <tt>DIRECTORY</tt> is supplied it
will become the new directory. If \c DIRECTORY is a relative path, the
CDPATH environment variable will be separated using the : as
separator, and the resulting list will be searched for a suitable new
current directory. If CDPATH is not set, it is assumed to be '.'. If
\c DIRECTORY is not specified, \$HOME will be the new directory.
\subsection cd-description Description Changes the current
directory. If <tt>DIRECTORY</tt> is supplied it will become the new
directory. If \c DIRECTORY is a relative path, the paths found in the
CDPATH environment variable array will be tried as prefixes for the
specified path. If CDPATH is not set, it is assumed to be '.'. If \c
DIRECTORY is not specified, \$HOME will be the new directory.

File diff suppressed because it is too large Load Diff

9
doc_src/fish_pager.txt Normal file
View File

@@ -0,0 +1,9 @@
\section fish_pager fish_pager - Internal command used by fish
\subsection fish_pager-description Description
This command is used internally by fish to display a list of
completions. It should not be used by other commands, as it's
interface is liable to change in the future.

View File

@@ -214,7 +214,7 @@ void env_universal_init( wchar_t * p,
void (*sf)(),
void (*cb)( int type, const wchar_t *name, const wchar_t *val ))
{
debug( 2, L"env_universal_init()" );
debug( 3, L"env_universal_init()" );
path=p;
user=u;
start_fishd=sf;
@@ -233,7 +233,7 @@ void env_universal_init( wchar_t * p,
{
env_universal_barrier();
}
debug( 2, L"end env_universal_init()" );
debug( 3, L"end env_universal_init()" );
}
void env_universal_destroy()

View File

@@ -105,7 +105,7 @@ static int get_names_show_unexported;
void env_universal_common_init( void (*cb)(int type, const wchar_t *key, const wchar_t *val ) )
{
debug( 2, L"Init env_universal_common" );
debug( 3, L"Init env_universal_common" );
callback = cb;
hash_init( &env_universal_var, &hash_wcs_func, &hash_wcs_cmp );
}
@@ -229,7 +229,7 @@ static int match( const wchar_t *msg, const wchar_t *cmd )
static void parse_message( wchar_t *msg,
connection_t *src )
{
debug( 2, L"parse_message( %ls );", msg );
debug( 3, L"parse_message( %ls );", msg );
if( msg[0] == L'#' )
return;

View File

@@ -3,6 +3,13 @@
#
# @configure_input@
#
# Set default search paths
#
set -g fish_function_path ~/.fish.d/functions @SYSCONFDIR@/fish.d/functions @DATADIR@/functions
set -g fish_complete_path ~/.fish.d/completions @SYSCONFDIR@/fish.d/completions @DATADIR@/completions
#
# Set default field separators
#
@@ -31,28 +38,12 @@ for i in $path_list
end
#
# Set some value for LANG if nothing was set before, and this is a
# login shell. Also check for i18n information in /etc/sysconfig/i18n
#
if status --is-login
if not set -q LANG >/dev/null
set -gx LANG en_US.UTF-8
end
if test -f /etc/sysconfig/i18n
eval (cat /etc/sysconfig/i18n |sed -ne 's/^\([a-zA-Z]*\)=\(.*\)$/set -gx \1 \2;/p')
end
end
#
# Put linux console in unicode mode. Should this be done in any other
# situation as well?
#
if expr "$LANG" : ".*UTF" >/dev/null
if expr "$LANG" : ".*[Uu][Tt][Ff]" >/dev/null
if test linux = "$TERM"
unicode_start ^/dev/null
end
@@ -70,23 +61,6 @@ for i in DISPLAY
end
end
#
# Alias for gettext (or a fallback if gettext isn't installed) This
# needs to be defined here and not in fish_function.fish, since it is
# used by other init files.
#
function _ -d "Alias for the gettext command"
printf "%s" $argv
end
if test 1 = "@HAVE_GETTEXT@"
if which gettext ^/dev/null >/dev/null
function _ -d "Alias for the gettext command"
gettext fish $argv
end
end
end
#
# Load additional initialization files
#

View File

@@ -22,26 +22,6 @@ function fish_on_exit -d (_ "Commands to execute when fish exits") --on-process
printf (_ "Good bye\n")
end
# Set the default prompt command. Make sure that every terminal escape
# string has a newline before and after, so that fish will know how
# long it is.
function fish_prompt -d (_ "Write out the prompt")
# Just calculate these once, to save a few cycles when displaying the prompt
if not set -q __fish_prompt_hostname
set -g __fish_prompt_hostname (hostname|cut -d . -f 1)
end
if not set -q __fish_prompt_normal
set -g __fish_prompt_normal (set_color normal)
end
set -l prompt_color (set_color $fish_color_cwd)
printf '%s@%s %s%s%s> \n' $USER $__fish_prompt_hostname "$prompt_color" (prompt_pwd) "$__fish_prompt_normal"
end
#
# Set INPUTRC to something nice
#
@@ -109,63 +89,6 @@ set_default fish_color_history_current cyan
set_default CDPATH . ~
#
# Match colors for grep, if supported
#
if grep --color=auto --help 1>/dev/null 2>/dev/null
set_exported_default GREP_COLOR '97;45'
set_exported_default GREP_OPTIONS '--color=auto'
end
#
# Color definitions for ls, if supported
#
if command ls --color=auto --help 1>/dev/null 2>/dev/null
set -l color_document 35
set -l color_image '01;35'
set -l color_sound '01;35'
set -l color_video '01;35'
set -l color_archive '01;31'
set -l color_command '01;32'
set -l color_backup 37
set -l default no=00 fi=00 'di=01;34' 'ln=01;36' 'pi=40;33' 'so=01;35' 'bd=40;33;01' 'cd=40;33;01' 'or=01;05;37;41' 'mi=01;05;37;41' ex=$color_command
for i in .cmd .exe .com .btm .bat .sh .csh .fish
set default $default "*$i=$color_command"
end
for i in .tar .tgz .arj .taz .lhz .zip .z .Z .gz .bz2 .bz .tz .rpm .cpio .jar .deb .rar .bin .hqx
set default $default "*$i=$color_archive"
end
for i in .jpg .jpeg .gif .bmp .xbm .xpm .png .tif
set default $default "*$i=$color_image"
end
for i in .mp3 .au .wav .aiff .ogg .wma
set default $default "*$i=$color_sound"
end
for i in .avi .mpeg .mpg .divx .mov .qt .wmv .rm
set default $default "*$i=$color_video"
end
for i in .htm .html .rtf .wpd .doc .pdf .ps .xls .swf .txt .tex .sxw .dvi INSTALL README ChangeLog
set default $default "*$i=$color_document"
end
for i in '~' .bak
set default $default "*$i=$color_backup"
end
set -gx LS_COLORS $default
end
#
# Remove temporary functions
#

28
event.c
View File

@@ -21,6 +21,7 @@
#include "event.h"
#include "signal.h"
#include "translate.h"
#include "halloc_util.h"
/**
Number of signals that can be queued before an overflow occurs
@@ -194,10 +195,7 @@ const wchar_t *event_get_desc( event_t *e )
{
if( !get_desc_buff )
{
get_desc_buff=malloc(sizeof(string_buffer_t) );
if( !get_desc_buff )
die_mem();
sb_init( get_desc_buff );
get_desc_buff=sb_halloc( global_context );
}
else
{
@@ -255,7 +253,7 @@ void event_add_handler( event_t *event )
e = event_copy( event, 0 );
if( !events )
events = al_new();
events = al_new();
if( e->type == EVENT_SIGNAL )
{
@@ -387,8 +385,6 @@ static void event_fire_internal( event_t *event )
int i, j;
string_buffer_t *b=0;
array_list_t *fire=0;
int was_interactive = is_interactive;
/*
First we free all events that have been removed
@@ -452,7 +448,7 @@ static void event_fire_internal( event_t *event )
for( j=0; j<al_get_count(&event->arguments); j++ )
{
wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 0 );
wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 1 );
sb_append( b, L" " );
sb_append( b, arg_esc );
free( arg_esc );
@@ -464,19 +460,14 @@ 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
*/
is_interactive=0;
proc_push_interactive(0);
parser_push_block( EVENT );
current_block->param1.event = event;
eval( (wchar_t *)b->buff, 0, TOP );
parser_pop_block();
proc_pop_interactive();
}
/*
Restore interactivity flags
*/
is_interactive = was_interactive;
if( b )
{
sb_destroy( b );
@@ -644,13 +635,6 @@ void event_destroy()
free( killme );
killme=0;
}
if( get_desc_buff )
{
sb_destroy( get_desc_buff );
free( get_desc_buff );
}
}
void event_free( event_t *e )

49
exec.c
View File

@@ -38,6 +38,8 @@
#include "env_universal.h"
#include "translate.h"
#include "halloc.h"
#include "halloc_util.h"
#include "parse_util.h"
/**
Prototype for the getpgid library function. The prototype for this
@@ -260,7 +262,7 @@ static int handle_child_io( io_data_t *io, int exit_on_error )
if( io->fd > 2 )
{
/*
Make sure the fd used by this redirection is not used by i.e. a pipe.
Make sure the fd used by this redirection is not used by e.g. a pipe.
*/
free_fd( io, io->fd );
}
@@ -403,7 +405,7 @@ static int setup_child_process( job_t *j, process_t *p )
if( !res )
{
res = handle_child_io( j->io, (p==0) );
res = handle_child_io( j->io, (p!=0) );
}
/* Set the handling for job control signals back to the default. */
@@ -788,9 +790,6 @@ void exec( job_t *j )
{
case INTERNAL_FUNCTION:
{
wchar_t **arg;
int i;
string_buffer_t sb;
wchar_t * def = halloc_register( j, wcsdup( function_get_definition( p->argv[0] )));
//fwprintf( stderr, L"run function %ls\n", argv[0] );
@@ -804,26 +803,9 @@ void exec( job_t *j )
current_block->param2.function_call_process = p;
current_block->param1.function_name = halloc_register( current_block, wcsdup( p->argv[0] ) );
if( builtin_count_args(p->argv)>1 )
{
sb_init( &sb );
for( i=1, arg=p->argv+1; *arg; i++, arg++ )
{
if( i != 1 )
sb_append( &sb, ARRAY_SEP_STR );
sb_append( &sb, *arg );
}
env_set( L"argv", (wchar_t *)sb.buff, ENV_LOCAL );
sb_destroy( &sb );
}
else
{
env_set( L"argv", 0, ENV_LOCAL );
}
parse_util_set_argv( p->argv+1 );
parser_forbid_function( p->argv[0] );
if( p->next )
@@ -1278,10 +1260,16 @@ int exec_subshell( const wchar_t *cmd,
{
wchar_t *el = str2wcs( begin );
if( el )
{
al_push( l, el );
}
else
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
}
}
io_buffer_destroy( io_buffer );
return status;
case '\n':
@@ -1289,7 +1277,14 @@ int exec_subshell( const wchar_t *cmd,
wchar_t *el;
*end=0;
el = str2wcs( begin );
al_push( l, el );
if( el )
{
al_push( l, el );
}
else
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
}
begin = end+1;
break;
}

296
expand.c
View File

@@ -1,7 +1,7 @@
/**\file expand.c
String expansion functions. These functions perform several kinds of
parameter expansion.
parameter expansion.
*/
@@ -36,10 +36,12 @@ parameter expansion.
#include "expand.h"
#include "wildcard.h"
#include "exec.h"
#include "signal.h"
#include "tokenizer.h"
#include "complete.h"
#include "translate.h"
#include "parse_util.h"
#include "halloc_util.h"
/**
Description for child process
@@ -388,8 +390,6 @@ static int find_process( const wchar_t *proc,
This is a numeric job string, like '%2'
*/
// fwprintf( stderr, L"Numeric\n\n\n" );
if( flags & ACCEPT_INCOMPLETE )
{
for( j=first_job; j != 0; j=j->next )
@@ -399,7 +399,6 @@ static int find_process( const wchar_t *proc,
continue;
swprintf( jid, 16, L"%d", j->job_id );
// fwprintf( stderr, L"Jid %ls\n", jid );
if( wcsncmp( proc, jid, wcslen(proc ) )==0 )
{
@@ -557,8 +556,10 @@ static int find_process( const wchar_t *proc,
continue;
}
signal_block();
fgetws2( &cmd, &sz, cmdfile );
signal_unblock();
fclose( cmdfile );
}
else
@@ -710,7 +711,6 @@ static int expand_pid( wchar_t *in,
return 1;
}
/**
Expand all environment variables in the string *ptr.
@@ -725,7 +725,7 @@ static int expand_pid( wchar_t *in,
happens, don't edit it unless you know exactly what you are doing,
and do proper testing afterwards.
*/
static int expand_variables( wchar_t *in, array_list_t *out )
static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
{
wchar_t c;
wchar_t prev_char=0;
@@ -733,7 +733,32 @@ static int expand_variables( wchar_t *in, array_list_t *out )
int is_ok= 1;
int empty=0;
for( i=wcslen(in)-1; (i>=0) && is_ok && !empty; i-- )
static string_buffer_t *var_tmp = 0;
static array_list_t *var_idx_list = 0;
if( !var_tmp )
{
var_tmp = sb_halloc( global_context );
if( !var_tmp )
die_mem();
}
else
{
sb_clear(var_tmp );
}
if( !var_idx_list )
{
var_idx_list = al_halloc( global_context );
if( !var_idx_list )
die_mem();
}
else
{
al_truncate( var_idx_list, 0 );
}
for( i=last_idx; (i>=0) && is_ok && !empty; i-- )
{
c = in[i];
if( ( c == VARIABLE_EXPAND ) || (c == VARIABLE_EXPAND_SINGLE ) )
@@ -741,12 +766,11 @@ static int expand_variables( wchar_t *in, array_list_t *out )
int start_pos = i+1;
int stop_pos;
int var_len, new_len;
wchar_t *var_name;
wchar_t * var_val;
wchar_t * new_in;
array_list_t l;
int is_single = (c==VARIABLE_EXPAND_SINGLE);
int var_name_stop_pos;
stop_pos = start_pos;
while( 1 )
@@ -759,7 +783,8 @@ static int expand_variables( wchar_t *in, array_list_t *out )
stop_pos++;
}
var_name_stop_pos = stop_pos;
/* printf( "Stop for '%c'\n", in[stop_pos]);*/
var_len = stop_pos - start_pos;
@@ -808,23 +833,16 @@ static int expand_variables( wchar_t *in, array_list_t *out )
break;
}
sb_append_substring( var_tmp, &in[start_pos], var_len );
if( !(var_name = malloc( sizeof(wchar_t)*(var_len+1) )))
{
die_mem();
}
wcsncpy( var_name, &in[start_pos], var_len );
var_name[var_len]='\0';
/* printf( "Variable name is %s, len is %d\n", var_name, var_len );*/
wchar_t *var_val_orig = expand_var( var_name );
var_val = expand_var( (wchar_t *)var_tmp->buff );
if( var_val_orig && (var_val = wcsdup( var_val_orig) ) )
if( var_val )
{
int all_vars=1;
array_list_t idx;
al_init( &idx );
al_init( &l );
array_list_t var_item_list;
al_init( &var_item_list );
if( in[stop_pos] == L'[' )
{
wchar_t *end;
@@ -857,43 +875,42 @@ static int expand_variables( wchar_t *in, array_list_t *out )
is_ok = 0;
break;
}
al_push( &idx, (void *)tmp );
al_push( var_idx_list, (void *)tmp );
stop_pos = end-in;
}
}
if( is_ok )
{
expand_variable_array( var_val, &l );
expand_variable_array( var_val, &var_item_list );
if( !all_vars )
{
int j;
for( j=0; j<al_get_count( &idx ); j++)
for( j=0; j<al_get_count( var_idx_list ); j++)
{
int tmp = (int)al_get( &idx, j );
if( tmp < 1 || tmp > al_get_count( &l ) )
int tmp = (int)al_get( var_idx_list, j );
if( tmp < 1 || tmp > al_get_count( &var_item_list ) )
{
error( SYNTAX_ERROR,
-1,
L"Array index out of bounds" );
is_ok=0;
al_truncate( &idx, j );
al_truncate( var_idx_list, j );
break;
}
else
{
/* Move string from list l to list idx */
al_set( &idx, j, al_get( &l, tmp-1 ) );
al_set( &l, tmp-1, 0 );
al_set( var_idx_list, j, al_get( &var_item_list, tmp-1 ) );
al_set( &var_item_list, tmp-1, 0 );
}
}
/* Free remaining strings in list l and truncate it */
al_foreach( &l, (void (*)(const void *))&free );
al_truncate( &l, 0 );
al_foreach( &var_item_list, (void (*)(const void *))&free );
al_truncate( &var_item_list, 0 );
/* Add items from list idx back to list l */
al_push_all( &l, &idx );
al_push_all( &var_item_list, var_idx_list );
}
free( var_val );
}
if( is_ok )
@@ -902,16 +919,15 @@ static int expand_variables( wchar_t *in, array_list_t *out )
if( is_single )
{
string_buffer_t res;
sb_init( &res );
in[i]=0;
sb_init( &res );
sb_append( &res, in );
sb_append_char( &res, INTERNAL_SEPARATOR );
for( j=0; j<al_get_count( &l); j++ )
for( j=0; j<al_get_count( &var_item_list); j++ )
{
wchar_t *next = (wchar_t *)al_get( &l, j );
wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
if( is_ok )
{
@@ -922,52 +938,58 @@ static int expand_variables( wchar_t *in, array_list_t *out )
free( next );
}
sb_append( &res, &in[stop_pos] );
is_ok &= expand_variables( (wchar_t *)res.buff, out );
is_ok &= expand_variables( (wchar_t *)res.buff, out, i );
}
else
{
for( j=0; j<al_get_count( &l); j++ )
for( j=0; j<al_get_count( &var_item_list); j++ )
{
wchar_t *next = (wchar_t *)al_get( &l, j );
if( is_ok )
wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
if( is_ok && (i == 0) && (!in[stop_pos]) )
{
new_len = wcslen(in) - (stop_pos-start_pos+1) + wcslen( next) +2;
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
al_push( out, next );
}
else
{
if( is_ok )
{
die_mem();
}
else
{
wcsncpy( new_in, in, start_pos-1 );
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
new_len = wcslen(in) - (stop_pos-start_pos+1);
new_len += wcslen( next) +2;
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
{
new_in[start_pos-1]=INTERNAL_SEPARATOR;
new_in[start_pos]=L'\0';
die_mem();
}
else
new_in[start_pos-1]=L'\0';
wcscat( new_in, next );
wcscat( new_in, &in[stop_pos] );
{
wcsncpy( new_in, in, start_pos-1 );
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
{
new_in[start_pos-1]=INTERNAL_SEPARATOR;
new_in[start_pos]=L'\0';
}
else
new_in[start_pos-1]=L'\0';
wcscat( new_in, next );
wcscat( new_in, &in[stop_pos] );
// fwprintf( stderr, L"New value %ls\n", new_in );
is_ok &= expand_variables( new_in, out );
is_ok &= expand_variables( new_in, out, i );
}
}
free( next );
}
free( next );
}
}
}
al_destroy( &l );
al_destroy( &idx );
free(in);
free(var_name );
al_destroy( &var_item_list );
return is_ok;
}
else
@@ -993,19 +1015,14 @@ static int expand_variables( wchar_t *in, array_list_t *out )
in[i]=0;
sb_append( &res, in );
sb_append( &res, &in[stop_pos] );
is_ok &= expand_variables( wcsdup((wchar_t *)res.buff), out );
sb_destroy( &res );
is_ok &= expand_variables( (wchar_t *)res.buff, out, i );
free(in);
free(var_name );
return is_ok;
}
}
free(var_name );
}
@@ -1109,7 +1126,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
{
error( SYNTAX_ERROR,
-1,
L"Mismatched brackets" );
_(L"Mismatched brackets") );
return 0;
}
@@ -1172,6 +1189,18 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
int i, j;
const wchar_t *item_begin;
if( !in )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
if( !out )
{
debug( 2, L"Got null pointer on line %d of file %s", __LINE__, __FILE__ );
return 0;
}
switch( parse_util_locate_cmdsubst(in,
&paran_begin,
&paran_end,
@@ -1188,7 +1217,6 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
case 1:
break;
}
len1 = (paran_begin-in);
@@ -1237,10 +1265,10 @@ static int expand_subshell( wchar_t *in, array_list_t *out )
sb_append_substring( &whole_item, sub_item2, item_len );
sb_append_char( &whole_item, INTERNAL_SEPARATOR );
sb_append( &whole_item, tail_item );
al_push( out, whole_item.buff );
al_push( out, whole_item.buff );
}
free( sub_item2 );
}
free(in);
@@ -1371,7 +1399,7 @@ static void remove_internal_separator( const void *s, int conv )
case INTERNAL_SEPARATOR:
in++;
break;
case ANY_CHAR:
in++;
*out++ = conv?L'?':ANY_CHAR;
@@ -1393,7 +1421,8 @@ static void remove_internal_separator( const void *s, int conv )
/**
The real expansion function. expand_one is just a wrapper around this one.
*/
int expand_string( wchar_t *str,
int expand_string( void *context,
wchar_t *str,
array_list_t *end_out,
int flags )
{
@@ -1403,12 +1432,14 @@ int expand_string( wchar_t *str,
int i;
int subshell_ok = 1;
int res = EXPAND_OK;
int start_count = al_get_count( end_out );
// debug( 1, L"Expand %ls", str );
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( str ) )
{
halloc_register( context, str );
al_push( end_out, str );
return EXPAND_OK;
}
@@ -1418,23 +1449,18 @@ int expand_string( wchar_t *str,
if( EXPAND_SKIP_SUBSHELL & flags )
{
wchar_t *pos = str;
while( 1 )
const wchar_t *begin, *end;
if( parse_util_locate_cmdsubst( str,
&begin,
&end,
1 ) != 0 )
{
pos = wcschr( pos, L'(' );
if( pos == 0 )
break;
if( (pos == str) || ( *(pos-1) != L'\\' ) )
{
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
free( str );
al_destroy( &list1 );
al_destroy( &list2 );
return EXPAND_ERROR;
}
pos++;
error( SUBSHELL_ERROR, -1, L"Subshells not allowed" );
free( str );
al_destroy( &list1 );
al_destroy( &list2 );
return EXPAND_ERROR;
}
al_push( &list1, str );
}
@@ -1463,7 +1489,10 @@ int expand_string( wchar_t *str,
free( (void *)al_get( in, i ) );
if( !next )
continue;
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
if( EXPAND_SKIP_VARIABLES & flags )
{
@@ -1472,11 +1501,10 @@ int expand_string( wchar_t *str,
if( *tmp == VARIABLE_EXPAND )
*tmp = L'$';
al_push( out, next );
}
else
{
if(!expand_variables( next, out ))
if(!expand_variables( next, out, wcslen(next)-1 ))
{
al_destroy( in );
al_destroy( out );
@@ -1493,6 +1521,13 @@ int expand_string( wchar_t *str,
for( i=0; i<al_get_count( in ); i++ )
{
wchar_t *next = (wchar_t *)al_get( in, i );
if( !next )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
if( !expand_brackets( next, flags, out ))
{
al_destroy( in );
@@ -1508,6 +1543,13 @@ int expand_string( wchar_t *str,
for( i=0; i<al_get_count( in ); i++ )
{
wchar_t *next = (wchar_t *)al_get( in, i );
if( !next )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
if( !(next=expand_tilde_internal( next ) ) )
{
al_destroy( in );
@@ -1552,7 +1594,14 @@ int expand_string( wchar_t *str,
wchar_t *next = (wchar_t *)al_get( in, i );
int wc_res;
if( !next )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags );
if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) ||
wildcard_has( next, 1 ) )
{
@@ -1569,50 +1618,79 @@ int expand_string( wchar_t *str,
switch( wc_res )
{
case 0:
{
if( !(flags & ACCEPT_INCOMPLETE) )
{
if( res == EXPAND_OK )
res = EXPAND_WILDCARD_NO_MATCH;
break;
}
}
case 1:
{
int j;
res = EXPAND_WILDCARD_MATCH;
sort_list( out );
al_push_all( end_out, out );
for( j=0; j<al_get_count( out ); j++ )
{
wchar_t *next = (wchar_t *)al_get( out, j );
if( !next )
{
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
continue;
}
al_push( end_out, next );
}
al_truncate( out, 0 );
break;
}
}
}
else
{
if( flags & ACCEPT_INCOMPLETE)
{
free( next );
}
else
{
al_push( end_out, next );
}
}
}
al_destroy( in );
al_destroy( out );
}
if( context )
{
for( i=start_count; i<al_get_count( end_out ); i++ )
{
halloc_register( context, (void *)al_get( end_out, i ) );
}
}
return res;
}
wchar_t *expand_one( wchar_t *string, int flags )
wchar_t *expand_one( void *context, wchar_t *string, int flags )
{
array_list_t l;
int res;
wchar_t *one;
if( (!(flags & ACCEPT_INCOMPLETE)) && is_clean( string ) )
{
halloc_register( context, string );
return string;
}
al_init( &l );
res = expand_string( string, &l, flags );
res = expand_string( 0, string, &l, flags );
if( !res )
{
one = 0;
@@ -1632,6 +1710,8 @@ wchar_t *expand_one( wchar_t *string, int flags )
al_foreach( &l, (void(*)(const void *))&free );
al_destroy( &l );
halloc_register( context, one );
return one;
}

View File

@@ -130,7 +130,7 @@ enum
\param out The list to which the result will be appended.
\return One of EXPAND_OK, EXPAND_ERROR, EXPAND_WILDCARD_MATCH and EXPAND_WILDCARD_NO_MATCH
*/
int expand_string( wchar_t *in, array_list_t *out, int flag );
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
@@ -141,14 +141,13 @@ int expand_string( wchar_t *in, array_list_t *out, int flag );
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_SUBSHELL EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
\return The expanded parameter, or 0 on failiure
*/
wchar_t *expand_one( wchar_t *in, int flag );
wchar_t *expand_one( void *context, wchar_t *in, int flag );
/**
Convert the variable value to a human readable form, i.e. escape things, handle arrays, etc. Suitable for pretty-printing.
*/
wchar_t *expand_escape_variable( const wchar_t *in );
/**
Perform tilde expansion and nothing else on the specified string.

View File

@@ -13,40 +13,65 @@ Source0: http://roo.no-ip.org/%{name}/files/%{version}/%{name}-%{
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: doxygen ncurses-devel xorg-x11-devel
%description
fish is a shell geared towards interactive use. It's features are
focused on user friendlieness and discoverability. The language syntax
is simple but incompatible with other shell languages.
%prep
%setup -q
%build
%build
%configure docdir=%_datadir/doc/%{name}-%{version}
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
make install DESTDIR="$RPM_BUILD_ROOT"
%clean
rm -rf $RPM_BUILD_ROOT
%post
if ! grep %_bindir/fish %_sysconfdir/shells >/dev/null; then
echo %_bindir/fish >>%_sysconfdir/shells
fi
%postun
if [ "$1" = 0 ]; then
grep -v %_bindir/fish %_sysconfdir/shells >%_sysconfdir/fish.tmp
mv %_sysconfdir/fish.tmp %_sysconfdir/shells
fi
%files
%defattr(-,root,root,-)
%doc %_datadir/doc/%{name}-%{version}
%_mandir/man1/fish.1*
%_mandir/man1/xsel.1x*
%_mandir/man1/mimedb.1*
@@ -54,6 +79,7 @@ fi
%_mandir/man1/count.1*
%_mandir/man1/fishd.1*
%_mandir/man1/fish_pager.1*
%attr(0755,root,root) %_bindir/fish
%attr(0755,root,root) %_bindir/fishd
%attr(0755,root,root) %_bindir/fish_pager
@@ -61,14 +87,26 @@ fi
%attr(0755,root,root) %_bindir/set_color
%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
%dir %_sysconfdir/fish.d/completions
%config %_sysconfdir/fish.d/completions/*.fish
%dir %_datadir/fish
%_datadir/fish/fish
%dir %_datadir/fish/completions
%_datadir/fish/completions/*.fish
%dir %_datadir/fish/functions
%_datadir/fish/functions/*.fish
%_datadir/locale/*/LC_MESSAGES/fish.mo
%changelog
* Tue Nov 29 2005 Axel Liljencrantz <axel@liljencrantz.se> 1.17.0-0
- 1.17.0

View File

@@ -42,6 +42,8 @@
#include "output.h"
#include "input_common.h"
#include "env_universal.h"
#include "halloc.h"
#include "halloc_util.h"
enum
{
@@ -74,6 +76,7 @@ static struct termios pager_modes;
static int is_ca_mode = 0;
static buffer_t *pager_buffer;
/**
The environment variables used to specify the color of different
@@ -91,8 +94,18 @@ static wchar_t *hightlight_var[] =
static string_buffer_t out_buff;
static FILE *out_file;
typedef struct
{
array_list_t *comp;
wchar_t *desc;
int comp_width;
int desc_width;
int pref_width;
int min_width;
}
comp_t;
int get_color( int highlight )
static int get_color( int highlight )
{
if( highlight < 0 )
return FISH_COLOR_NORMAL;
@@ -101,9 +114,6 @@ int get_color( int highlight )
wchar_t *val = env_universal_get( hightlight_var[highlight]);
if( val == 0 )
return FISH_COLOR_NORMAL;
if( val == 0 )
{
return FISH_COLOR_NORMAL;
@@ -112,7 +122,20 @@ int get_color( int highlight )
return output_color_code( val );
}
int try_sequence( char *seq )
static void recalc_width( array_list_t *l, const wchar_t *prefix )
{
int i;
for( i=0; i<al_get_count( l ); i++ )
{
comp_t *c = (comp_t *)al_get( l, i );
c->min_width = mini( c->desc_width, maxi(0,termsize.ws_col/3 - 2)) +
mini( c->desc_width, maxi(0,termsize.ws_col/5 - 4)) +4;
}
}
static int try_sequence( char *seq )
{
int j, k;
wint_t c=0;
@@ -195,6 +218,110 @@ static wint_t readch()
}
static int pager_buffered_writer( char c)
{
b_append( pager_buffer, &c, 1 );
return 0;
}
static void pager_flush()
{
write( 1, pager_buffer->buff, pager_buffer->used );
pager_buffer->used = 0;
}
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]) )
{
writech( ellipsis_char );
written += wcwidth(ellipsis_char );
break;
}
writech( str[i] );
written+= wcwidth( str[i] );
}
return written;
}
static void completion_print_item( const wchar_t *prefix, comp_t *c, int width )
{
int comp_width=0, desc_width=0;
int i;
int written=0;
if( c->pref_width <= width )
{
/*
The entry fits, we give it as much space as it wants
*/
comp_width = c->comp_width;
desc_width = c->desc_width;
}
else
{
/*
The completion and description won't fit on the
allocated space. Give a maximum of 2/3 of the
space to the completion, and whatever is left to
the description.
*/
int desc_all = c->desc_width?c->desc_width+4:0;
comp_width = maxi( mini( c->comp_width,
2*(width-4)/3 ),
width - desc_all );
if( c->desc_width )
desc_width = width-comp_width-4;
else
c->desc_width=0;
}
for( i=0; i<al_get_count( c->comp ); i++ )
{
const wchar_t *comp = (const wchar_t *)al_get( c->comp, i );
if( i != 0 )
written += print_max( L" ", comp_width - written, 2 );
set_color( get_color(HIGHLIGHT_PAGER_PREFIX),FISH_COLOR_NORMAL );
written += print_max( prefix, comp_width - written, comp[0]?1:0 );
set_color( get_color(HIGHLIGHT_PAGER_COMPLETION),FISH_COLOR_IGNORE );
written += print_max( comp, comp_width - written, i!=(al_get_count(c->comp)-1) );
}
if( desc_width )
{
while( written < (width-desc_width-2))
{
written++;
writech( L' ');
}
written += print_max( L"(", 1, 0 );
set_color( get_color( HIGHLIGHT_PAGER_DESCRIPTION ),
FISH_COLOR_IGNORE );
written += print_max( c->desc, desc_width, 0 );
written += print_max( L")", 1, 0 );
}
else
{
while( written < width )
{
written++;
writech( L' ');
}
}
}
/**
Print the specified part of the completion list, using the
specified column offsets and quoting style.
@@ -219,291 +346,29 @@ static void completion_print( int cols,
int rows = (al_get_count( l )-1)/cols+1;
int i, j;
int prefix_width= my_wcswidth(prefix);
for( i = row_start; i<row_stop; i++ )
{
for( j = 0; j < cols; j++ )
{
wchar_t *el, *el_end;
comp_t *el;
int is_last = (j==(cols-1));
if( al_get_count( l ) <= j*rows + i )
continue;
el = (wchar_t *)al_get( l, j*rows + i );
el_end= wcschr( el, COMPLETE_SEP );
set_color( get_color(HIGHLIGHT_PAGER_PREFIX),FISH_COLOR_NORMAL );
writestr( prefix );
set_color( get_color(HIGHLIGHT_PAGER_COMPLETION),FISH_COLOR_IGNORE );
if( el_end == 0 )
{
/* We do not have a description for this completion */
int written = 0;
int max_written = width[j] - prefix_width - (j==cols-1?0:2);
if( is_quoted )
{
for( i=0; i<max_written; i++ )
{
if( !el[i] )
break;
writech( el[i] );
written+= wcwidth( el[i] );
}
}
else
{
written = write_escaped_str( el, max_written );
}
set_color( get_color( HIGHLIGHT_PAGER_DESCRIPTION ),
FISH_COLOR_IGNORE );
writespace( width[j]-
written-
prefix_width );
}
else
{
int whole_desc_width = my_wcswidth(el_end+1);
int whole_comp_width;
/*
Temporarily drop the description so that wcswidth et
al only calculate the width of the completion.
*/
*el_end = L'\0';
/*
Calculate preferred completion width
*/
if( is_quoted )
{
whole_comp_width = my_wcswidth(el);
}
else
{
wchar_t *tmp = escape( el, 1 );
whole_comp_width = my_wcswidth( tmp );
free(tmp);
}
/*
Calculate how wide this entry 'wants' to be
*/
int pref_width = whole_desc_width + 4 + prefix_width + 2 -
(j==cols-1?2:0) + whole_comp_width;
int comp_width, desc_width;
if( pref_width <= width[j] )
{
/*
The entry fits, we give it as much space as it wants
*/
comp_width = whole_comp_width;
desc_width = whole_desc_width;
}
else
{
/*
The completion and description won't fit on the
allocated space. Give a maximum of 2/3 of the
space to the completion, and whatever is left to
the description.
*/
int sum = width[j] - prefix_width - 4 - 2 + (j==cols-1?2:0);
comp_width = maxi( mini( whole_comp_width,
2*sum/3 ),
sum - whole_desc_width );
desc_width = sum-comp_width;
}
/* First we must print the completion. */
if( is_quoted )
{
writestr_ellipsis( el, comp_width);
}
else
{
write_escaped_str( el, comp_width );
}
/* Put the description back */
*el_end = COMPLETE_SEP;
/* And print it */
set_color( get_color(HIGHLIGHT_PAGER_DESCRIPTION),
FISH_COLOR_IGNORE );
writespace( maxi( 2,
width[j]
- comp_width
- desc_width
- 4
- prefix_width
+ (j==cols-1?2:0) ) );
/* Print description */
writestr(L"(");
writestr_ellipsis( el_end+1, desc_width);
writestr(L")");
if( j != cols-1)
writestr( L" " );
}
el = (comp_t *)al_get( l, j*rows + i );
completion_print_item( prefix, el, width[j] - (is_last?0:2) );
if( !is_last)
writestr( L" " );
}
writech( L'\n' );
}
}
/**
Calculates how long the specified string would be when printed on the command line.
\param str The string to be printed.
\param is_quoted Whether the string would be printed quoted or unquoted
\param pref_width the preferred width for this item
\param min_width the minimum width for this item
*/
static void printed_length( wchar_t *str,
int is_quoted,
int *pref_width,
int *min_width )
{
if( is_quoted )
{
wchar_t *sep = wcschr(str,COMPLETE_SEP);
if( sep )
{
*sep=0;
int cw = my_wcswidth( str );
int dw = my_wcswidth(sep+1);
if( termsize.ws_col > 80 )
dw = mini( dw, termsize.ws_col/3 );
*pref_width = cw+dw+4;
if( dw > termsize.ws_col/3 )
{
dw = termsize.ws_col/3;
}
*min_width=cw+dw+4;
*sep= COMPLETE_SEP;
return;
}
else
{
*pref_width=*min_width= my_wcswidth( str );
return;
}
}
else
{
int comp_len=0, desc_len=0;
int has_description = 0;
while( *str != 0 )
{
if( ( *str >= ENCODE_DIRECT_BASE) &&
( *str < ENCODE_DIRECT_BASE+256) )
{
if( has_description )
desc_len+=4;
else
comp_len+=4;
}
else
{
switch( *str )
{
case L'\n':
case L'\b':
case L'\r':
case L'\e':
case L'\t':
case L'\\':
case L'&':
case L'$':
case L' ':
case L'#':
case L'^':
case L'<':
case L'>':
case L'(':
case L')':
case L'[':
case L']':
case L'{':
case L'}':
case L'?':
case L'*':
case L'|':
case L';':
case L':':
case L'\'':
case L'"':
case L'%':
case L'~':
if( has_description )
desc_len++;
else
comp_len+=2;
break;
case COMPLETE_SEP:
has_description = 1;
break;
default:
if( has_description )
desc_len+= wcwidth(*str);
else
comp_len+= wcwidth(*str);
break;
}
}
str++;
}
if( has_description )
{
/*
Mangle long descriptions to make formating look nicer
*/
debug( 3, L"Desc, width = %d %d\n", comp_len, desc_len );
// if( termsize.ws_col > 80 )
// desc_len = mini( desc_len, termsize.ws_col/3 );
*pref_width = comp_len+ desc_len+4;;
comp_len = mini( comp_len, maxi(0,termsize.ws_col/3 - 2));
desc_len = mini( desc_len, maxi(0,termsize.ws_col/5 - 4));
*min_width = comp_len+ desc_len+4;
return;
}
else
{
debug( 3, L"No desc, width = %d\n", comp_len );
*pref_width=*min_width= comp_len;
return;
}
}
}
/**
Try to print the list of completions l with the prefix prefix using
@@ -551,8 +416,6 @@ static int completion_try_print( int cols,
int pref_tot_width=0;
int min_tot_width = 0;
int prefix_width = my_wcswidth( prefix );
int res=0;
/*
Skip completions on tiny terminals
@@ -560,25 +423,24 @@ static int completion_try_print( int cols,
if( termsize.ws_col < 16 )
return 1;
memset( pref_width, 0, sizeof(pref_width) );
memset( min_width, 0, sizeof(min_width) );
/* Calculate how wide the list would be */
for( j = 0; j < cols; j++ )
{
for( i = 0; i<rows; i++ )
{
int pref,min;
wchar_t *el;
comp_t *c;
if( al_get_count( l ) <= j*rows + i )
continue;
el = (wchar_t *)al_get( l, j*rows + i );
printed_length( el, is_quoted, &pref, &min );
pref += prefix_width;
min += prefix_width;
c = (comp_t *)al_get( l, j*rows + i );
pref = c->pref_width;
min = c->min_width;
if( j != cols-1 )
{
pref += 2;
@@ -660,6 +522,7 @@ static int completion_try_print( int cols,
}
completion_print( cols, width, 0, rows, prefix, is_quoted, l);
pager_flush();
}
else
{
@@ -692,6 +555,7 @@ static int completion_try_print( int cols,
percent );
writestr(msg);
set_color( FISH_COLOR_NORMAL, FISH_COLOR_NORMAL );
pager_flush();
int c = readch();
switch( c )
@@ -753,7 +617,8 @@ static int completion_try_print( int cols,
}
else
{
writembs( flash_screen );
if( flash_screen )
writembs( flash_screen );
}
break;
@@ -777,7 +642,8 @@ static int completion_try_print( int cols,
}
else
{
writembs( flash_screen );
if( flash_screen )
writembs( flash_screen );
}
break;
}
@@ -805,7 +671,9 @@ static int completion_try_print( int cols,
}
/**
Substitute any series of tabs, newlines, etc. with a single space character in completion description
Substitute any series of whitespace with a single space character
inside completion descriptions. Remove all whitespace from
beginning/end of completion descriptions.
*/
static void mangle_descriptions( array_list_t *l )
{
@@ -843,6 +711,125 @@ static void mangle_descriptions( array_list_t *l )
}
}
/**
Merge multiple completions with the same description to the same line
*/
static void join_completions( array_list_t *l )
{
int i, in, out;
hash_table_t desc_table;
hash_init( &desc_table, &hash_wcs_func, &hash_wcs_cmp );
for( i=0; i<al_get_count(l); i++ )
{
wchar_t *item = (wchar_t *)al_get( l, i );
wchar_t *desc = wcschr( item, COMPLETE_SEP );
long prev_idx;
if( !desc )
continue;
desc++;
prev_idx = ((long)hash_get( &desc_table, desc) )-1;
if( prev_idx == -1 )
{
hash_put( &desc_table, halloc_wcsdup( global_context, desc), (void *)(i+1));
}
else
{
string_buffer_t foo;
wchar_t *old = (wchar_t *)al_get( l, prev_idx );
wchar_t *old_end = wcschr( old, COMPLETE_SEP );
if( old_end )
{
*old_end = 0;
sb_init( &foo );
sb_append( &foo, old );
sb_append_char( &foo, COMPLETE_ITEM_SEP );
sb_append( &foo, item );
free( (void *)al_get( l, prev_idx ) );
al_set( l, prev_idx, foo.buff );
free( (void *)al_get( l, i ) );
al_set( l, i, 0 );
}
// debug( 1, L"WOOT WOOT %ls är släkt med %ls", item, al_get( l, prev_idx ) );
}
}
hash_destroy( &desc_table );
out=0;
for( in=0; in < al_get_count(l); in++ )
{
const void * d = al_get( l, in );
if( d )
{
al_set( l, out++, d );
}
}
al_truncate( l, out );
}
/**
Replace completion strings with a comp_t structure
*/
static void mangle_completions( array_list_t *l, const wchar_t *prefix )
{
int i;
for( i=0; i<al_get_count( l ); i++ )
{
wchar_t *next = (wchar_t *)al_get( l, i );
wchar_t *start, *end;
comp_t *comp = halloc( global_context, sizeof( comp_t ) );
comp->comp = al_halloc( global_context );
for( start=end=next; 1; end++ )
{
wchar_t c = *end;
if( (c == COMPLETE_ITEM_SEP) || (c==COMPLETE_SEP) || !c)
{
*end = 0;
wchar_t * str = escape( start, 1 );
comp->comp_width += my_wcswidth( str );
halloc_register( global_context, str );
al_push( comp->comp, str );
start = end+1;
}
if( c == COMPLETE_SEP )
{
comp->desc = halloc_wcsdup( global_context, start );
break;
}
if( !c )
break;
}
comp->comp_width += my_wcswidth(prefix)*al_get_count(comp->comp) + 2*(al_get_count(comp->comp)-1);
comp->desc_width = comp->desc?my_wcswidth( comp->desc ):0;
comp->pref_width = comp->comp_width + comp->desc_width + (comp->desc_width?4:0);
free( next );
al_set( l, i, comp );
}
recalc_width( l, prefix );
}
/**
Respond to a winch signal by checking the terminal size
*/
@@ -887,9 +874,12 @@ static void init()
*/
sb_init( &out_buff );
output_init();
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;
@@ -914,6 +904,9 @@ static void init()
pager_modes.c_cc[VMIN]=1;
pager_modes.c_cc[VTIME]=0;
/*
*/
if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */
{
wperror(L"tcsetattr");
@@ -932,49 +925,51 @@ void destroy()
{
env_universal_destroy();
input_common_destroy();
output_destroy();
halloc_util_destroy();
del_curterm( cur_term );
sb_destroy( &out_buff );
fclose( out_file );
}
int main( int argc, char **argv )
{
int i;
int is_quoted=0;
array_list_t comp;
array_list_t *comp;
wchar_t *prefix;
init();
if( argc < 3 )
{
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 );
al_init( &comp );
for( i=3; i<argc; i++ )
{
wchar_t *wcs = str2wcs( argv[i] );
if( wcs )
{
al_push( &comp, wcs );
al_push( comp, wcs );
}
}
mangle_descriptions( comp );
if( wcscmp( prefix, L"-" ) == 0 )
join_completions( comp );
mangle_completions( comp, prefix );
mangle_descriptions( &comp );
for( i = 6; i>0; i-- )
{
switch( completion_try_print( i, prefix, is_quoted, &comp ) )
switch( completion_try_print( i, prefix, is_quoted, comp ) )
{
case 0:
break;
@@ -988,8 +983,6 @@ int main( int argc, char **argv )
}
al_foreach( &comp, (void(*)(const void *))&free );
al_destroy( &comp );
free(prefix );
fwprintf( out_file, L"%ls", (wchar_t *)out_buff.buff );

View File

@@ -41,6 +41,7 @@
#include "output.h"
#include "exec.h"
#include "event.h"
#include "halloc_util.h"
/**
Number of laps to run performance testing loop
@@ -327,7 +328,7 @@ static void sb_test()
sb_init( &b );
if( res=sb_printf( &b, L"%ls%s", L"Testing ", "string_buffer_t " ) == -1 )
if( (res=sb_printf( &b, L"%ls%s", L"Testing ", "string_buffer_t " )) == -1 )
{
err( L"Error %d while testing stringbuffers", res );
}
@@ -336,7 +337,22 @@ static void sb_test()
{
err( L"Error %d while testing stringbuffers", res );
}
say( (wchar_t *)b.buff );
sb_clear( &b );
#define NUM_ANS L"-7 99999999 1234567 deadbeef DEADBEEFDEADBEEF"
sb_printf( &b, L"%d %u %o %x %llX", -7, 99999999, 01234567, 0xdeadbeef, 0xdeadbeefdeadbeefll );
if( wcscmp( (wchar_t *)b.buff, NUM_ANS) != 0 )
{
err( L"numerical formating is broken, '%ls' != '%ls'", (wchar_t *)b.buff, NUM_ANS );
}
else
say( L"numerical formating works" );
}
/**
@@ -533,7 +549,7 @@ static int expand_test( const wchar_t *in, int flags, ... )
wchar_t *arg;
al_init( &out );
expand_string( wcsdup(in), &out, flags);
expand_string( 0, wcsdup(in), &out, flags);
va_start( va, flags );
@@ -669,7 +685,7 @@ int main( int argc, char **argv )
say( L"Lines beginning with '(ignore):' are not errors, they are warning messages\ngenerated by the fish parser library when given broken input, and can be\nignored. All actual errors begin with 'Error:'." );
proc_init();
output_init();
halloc_util_init();
event_init();
exec_init();
parser_init();
@@ -701,7 +717,7 @@ int main( int argc, char **argv )
wutil_destroy();
exec_destroy();
event_destroy();
output_destroy();
proc_destroy();
halloc_util_destroy();
}

View File

@@ -19,6 +19,8 @@
#include "event.h"
#include "reader.h"
#include "parse_util.h"
#include "env.h"
#include "expand.h"
/**
@@ -33,6 +35,7 @@ typedef struct
const wchar_t *definition_file;
int definition_offset;
int is_binding;
int is_autoload;
}
function_data_t;
@@ -40,6 +43,79 @@ typedef struct
Table containing all functions
*/
static hash_table_t function;
static int is_autoload = 0;
/**
Make sure that if the specified function is a dynamically loaded
function, it has been fully loaded.
*/
static int load( const wchar_t *name )
{
int was_autoload = is_autoload;
int res;
function_data_t *data;
data = (function_data_t *)hash_get( &function, name );
if( data && !data->is_autoload )
return 0;
is_autoload = 1;
res = parse_util_load( name,
L"fish_function_path",
&function_remove,
1 );
is_autoload = was_autoload;
return res;
}
/**
Insert a list of all dynamically loaded functions into the
specified list.
*/
static void autoload_names( array_list_t *out, int get_hidden )
{
int i;
array_list_t path_list;
const wchar_t *path_var = env_get( L"fish_function_path" );
if( ! path_var )
return;
al_init( &path_list );
expand_variable_array( path_var, &path_list );
for( i=0; i<al_get_count( &path_list ); i++ )
{
wchar_t *ndir = (wchar_t *)al_get( &path_list, i );
DIR *dir = wopendir( ndir );
if( !dir )
continue;
struct wdirent *next;
while( (next=wreaddir(dir))!=0 )
{
wchar_t *fn = next->d_name;
wchar_t *suffix;
if( !get_hidden && fn[0] == L'_' )
continue;
suffix = wcsrchr( fn, L'.' );
if( suffix && (wcscmp( suffix, L".fish" ) == 0 ) )
{
const wchar_t *dup;
*suffix = 0;
dup = intern( fn );
if( !dup )
die_mem();
al_push( out, dup );
}
}
closedir(dir);
}
al_foreach( &path_list, (void (*)(const void *))&free );
al_destroy( &path_list );
}
/**
Free all contents of an entry to the function hash table
@@ -92,7 +168,8 @@ void function_add( const wchar_t *name,
d->desc = desc?wcsdup( desc ):0;
d->is_binding = is_binding;
d->definition_file = intern(reader_current_filename());
d->is_autoload = is_autoload;
hash_put( &function, intern(name), d );
for( i=0; i<al_get_count( events ); i++ )
@@ -104,6 +181,10 @@ void function_add( const wchar_t *name,
int function_exists( const wchar_t *cmd )
{
if( parser_is_reserved(cmd) )
return 0;
load( cmd );
return (hash_get(&function, cmd) != 0 );
}
@@ -130,8 +211,9 @@ void function_remove( const wchar_t *name )
const wchar_t *function_get_definition( const wchar_t *argv )
{
function_data_t *data =
(function_data_t *)hash_get( &function, argv );
function_data_t *data;
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return 0;
return data->cmd;
@@ -139,8 +221,9 @@ const wchar_t *function_get_definition( const wchar_t *argv )
const wchar_t *function_get_desc( const wchar_t *argv )
{
function_data_t *data =
(function_data_t *)hash_get( &function, argv );
function_data_t *data;
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return 0;
@@ -149,8 +232,9 @@ const wchar_t *function_get_desc( const wchar_t *argv )
void function_set_desc( const wchar_t *name, const wchar_t *desc )
{
function_data_t *data =
(function_data_t *)hash_get( &function, name );
function_data_t *data;
load( name );
data = (function_data_t *)hash_get( &function, name );
if( data == 0 )
return;
@@ -173,6 +257,8 @@ static void get_names_internal( const void *key,
void function_get_names( array_list_t *list, int get_hidden )
{
autoload_names( list, get_hidden );
if( get_hidden )
hash_get_keys( &function, list );
else
@@ -182,8 +268,9 @@ void function_get_names( array_list_t *list, int get_hidden )
const wchar_t *function_get_definition_file( const wchar_t *argv )
{
function_data_t *data =
(function_data_t *)hash_get( &function, argv );
function_data_t *data;
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return 0;
@@ -193,13 +280,12 @@ const wchar_t *function_get_definition_file( const wchar_t *argv )
int function_get_definition_offset( const wchar_t *argv )
{
function_data_t *data =
(function_data_t *)hash_get( &function, argv );
function_data_t *data;
load( argv );
data = (function_data_t *)hash_get( &function, argv );
if( data == 0 )
return -1;
return data->definition_offset;
}

View File

@@ -69,8 +69,15 @@ int function_exists( const wchar_t *name );
void function_get_names( array_list_t *list,
int get_hidden );
/**
Returns tha absolute path of the file where the specified function
was defined. Returns 0 if the file was defined on the commandline.
*/
const wchar_t *function_get_definition_file( const wchar_t *name );
/**
Returns the linenumber where the definition of the specified function started
*/
int function_get_definition_offset( const wchar_t *name );
#endif

158
halloc.c
View File

@@ -15,10 +15,23 @@
#include "common.h"
#include "halloc.h"
#define HALLOC_BLOCK_SIZE 128
#define HALLOC_SCRAP_SIZE 16
#ifdef HALLOC_DEBUG
static int child_count=0;
static int child_size=0;
static int alloc_count =0;
static int alloc_spill = 0;
static pid_t pid=0;
static int parent_count=0;
#endif
typedef struct halloc
{
array_list_t children;
array_list_t hchildren;
void *scratch;
size_t scratch_free;
long long data[0];
}
halloc_t;
@@ -28,51 +41,130 @@ static halloc_t *halloc_from_data( void *data )
return (halloc_t *)(data - sizeof( halloc_t ) );
}
static void late_free( void *data)
{
}
#ifdef HALLOC_DEBUG
static void woot()
{
if( getpid() == pid )
{
debug( 1, L"%d parents, %d children with average child size of %.2f bytes caused %d allocs, average spill of %.2f bytes",
parent_count, child_count, (double)child_size/child_count,
parent_count+alloc_count, (double)alloc_spill/(parent_count+alloc_count) );
}
}
#endif
void *halloc( void *context, size_t size )
{
{
halloc_t *me, *parent;
me = (halloc_t *)calloc( 1, sizeof(halloc_t) + size );
if( !me )
return 0;
al_init( &me->children );
if( context )
{
parent = halloc_from_data( context );
al_push( &parent->hchildren, &me->data );
}
{
void *res;
return &me->data;
}
#ifdef HALLOC_DEBUG
if( !child_count )
{
pid = getpid();
atexit( woot );
}
child_count++;
child_size += size;
#endif
parent = halloc_from_data( context );
if( size <= parent->scratch_free )
{
res = parent->scratch;
parent->scratch_free -= size;
parent->scratch += size;
}
else
{
void *halloc_register( void *context, void *data )
{
halloc_t *me;
if( !context )
return data;
#ifdef HALLOC_DEBUG
alloc_count++;
#endif
if( parent->scratch_free < HALLOC_SCRAP_SIZE )
{
#ifdef HALLOC_DEBUG
alloc_spill += parent->scratch_free;
#endif
res = calloc( 1, size + HALLOC_BLOCK_SIZE );
parent->scratch = res + size;
parent->scratch_free = HALLOC_BLOCK_SIZE;
}
else
{
res = calloc( 1, size );
}
al_push( &parent->children, &late_free );
al_push( &parent->children, res );
}
return res;
me = halloc_from_data( context );
al_push( &me->children, data );
return data;
}
else
{
me = (halloc_t *)calloc( 1, sizeof(halloc_t) + size + HALLOC_BLOCK_SIZE );
if( !me )
return 0;
#ifdef HALLOC_DEBUG
parent_count++;
#endif
me->scratch = ((void *)me) + sizeof(halloc_t) + size;
me->scratch_free = HALLOC_BLOCK_SIZE;
al_init( &me->children );
return &me->data;
}
}
void halloc_free( void *context )
void halloc_register_function( void *context, void (*func)(void *), void *data )
{
halloc_t *me;
if( !context )
return;
me = halloc_from_data( context );
al_foreach( &me->hchildren, (void (*)(const void *))&halloc_free );
al_foreach( &me->children, (void (*)(const void *))&free );
al_destroy( &me->children );
al_destroy( &me->hchildren );
free(me);
al_push( &me->children, func );
al_push( &me->children, data );
}
void halloc_free( void *context )
{
halloc_t *me;
int i;
if( !context )
return;
me = halloc_from_data( context );
#ifdef HALLOC_DEBUG
alloc_spill += me->scratch_free;
#endif
for( i=0; i<al_get_count(&me->children); i+=2 )
{
void (*func)(void *) = (void (*)(void *))al_get( &me->children, i );
void * data = (void *)al_get( &me->children, i+1 );
if( func != &late_free )
func( data );
}
for( i=0; i<al_get_count(&me->children); i+=2 )
{
void (*func)(void *) = (void (*)(void *))al_get( &me->children, i );
void * data = (void *)al_get( &me->children, i+1 );
if( func == &late_free )
free( data );
}
al_destroy( &me->children );
free(me);
}

View File

@@ -1,35 +1,48 @@
/** \file halloc.h
A hierarchical memory allocation system. Works just like talloc
A hierarchical memory allocation system. Works mostly like talloc
used in Samba, except that an arbitrary block allocated with
malloc() can be registered to be freed by halloc_free.
*/
#ifndef FISH_HALLOC_H
#define FISH_HALLOC_H
/**
Allocate new memory using specified parent memory context. If \c
context is null, a new root context is created. Context _must_ be
either 0 or the result of a previous call to halloc.
Allocate new memory using specified parent memory context. Context
_must_ be either 0 or the result of a previous call to halloc.
If \c context is null, the resulting block must be freed with a
call to halloc_free().
If \c context is null, the resulting block is a root block, and
must be freed with a call to halloc_free().
If \c context is not null, the resulting memory block must never be
If \c context is not null, context must be a halloc root block. the
resulting memory block is a child context, and must never be
explicitly freed, it will be automatically freed whenever the
parent context is freed.
parent context is freed. Child blocks can also never be used as the
context in calls to halloc_register_function, halloc_free, etc.
*/
void *halloc( void *context, size_t size );
/**
Make the specified function run whenever context is free'd, using data as argument.
\c context a halloc root block
*/
void halloc_register_function( void *context, void (*func)(void *), void *data );
/**
Free memory context and all children contexts. Only root contexts
may be freed explicitly.
All functions registered with halloc_register_function are run in
the order they where added. Afterwards, all memory allocated using
halloc itself is free'd.
\c context a halloc root block
*/
void halloc_free( void *context );
/**
Free the memory pointed to by \c data when the memory pointed to by
\c context is free:d. Note that this will _not_ turn the specified
memory area into a valid halloc context. Only memory areas created
using a call to halloc() can be used as a context.
*/
void *halloc_register( void *context, void *data );
#endif

94
halloc_util.c Normal file
View File

@@ -0,0 +1,94 @@
/** \file halloc.c
A hierarchical memory allocation system. Works just like talloc
used in Samba, except that an arbitrary block allocated with
malloc() can be registered to be freed by halloc_free.
*/
#include "config.h"
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "util.h"
#include "common.h"
#include "halloc.h"
void *global_context=0;
void halloc_util_init()
{
global_context = halloc( 0, 0 );
}
void halloc_util_destroy()
{
halloc_free( global_context );
}
array_list_t *al_halloc( void *context )
{
array_list_t *res = halloc( context, sizeof( array_list_t ) );
if( !res )
die_mem();
al_init( res );
halloc_register_function( context, (void (*)(void *)) &al_destroy, res );
return res;
}
string_buffer_t *sb_halloc( void *context )
{
string_buffer_t *res = halloc( context, sizeof( string_buffer_t ) );
if( !res )
die_mem();
sb_init( res );
halloc_register_function( context, (void (*)(void *)) &sb_destroy, res );
return res;
}
static void halloc_passthrough( void *f )
{
void (*func)() = (void (*)() )f;
func();
}
void halloc_register_function_void( void *context, void (*func)() )
{
halloc_register_function( context, &halloc_passthrough, (void *)func );
}
void *halloc_register( void *context, void *data )
{
if( !data )
return 0;
halloc_register_function( context, &free, data );
return data;
}
wchar_t *halloc_wcsdup( void *context, wchar_t *in )
{
size_t len=wcslen(in);
wchar_t *out = halloc( context, sizeof( wchar_t)*(len+1));
if( out == 0 )
{
die_mem();
}
memcpy( out, in, sizeof( wchar_t)*(len+1));
return out;
}
wchar_t *halloc_wcsndup( void * context, const wchar_t *in, int c )
{
wchar_t *res = halloc( context, sizeof(wchar_t)*(c+1) );
if( res == 0 )
{
die_mem();
}
wcslcpy( res, in, c+1 );
res[c] = L'\0';
return res;
}

66
halloc_util.h Normal file
View File

@@ -0,0 +1,66 @@
/**
\file halloc_util.h
Various halloc-related utility functions.
*/
#ifndef FISH_HALLOC_UTIL_H
#define FISH_HALLOC_UTIL_H
/**
This pointer is a valid halloc context that will be freed right
before program shutdown. It may be used to allocate memory that
should be freed when the program shuts down.
*/
extern void *global_context;
/**
Create the global_context halloc object
*/
void halloc_util_init();
/**
Free the global_context halloc object
*/
void halloc_util_destroy();
/**
Allocate a array_list_t that will be automatically disposed of when
the specified context is free'd
*/
array_list_t *al_halloc( void *context );
/**
Allocate a string_buffer_t that will be automatically disposed of
when the specified context is free'd
*/
string_buffer_t *sb_halloc( void *context );
/**
Register the specified function to run when the specified context
is free'd. This function is related to halloc_register_function,
but the specified function dowes not take an argument.
*/
void halloc_register_function_void( void *context, void (*func)() );
/**
Free the memory pointed to by \c data when the memory pointed to by
\c context is free:d. Note that this will _not_ turn the specified
memory area into a valid halloc context. Only memory areas created
using a call to halloc( 0, size ) can be used as a context.
*/
void *halloc_register( void *context, void *data );
/**
Make a copy of the specified string using memory allocated using
halloc and the specified context
*/
wchar_t *halloc_wcsdup( void *context, wchar_t *str );
/**
Make a copy of the specified substring using memory allocated using
halloc and the specified context
*/
wchar_t *halloc_wcsndup( void * context, const wchar_t *in, int c );
#endif

View File

@@ -130,10 +130,10 @@ void highlight_shell( wchar_t * buff,
/*
Command. First check that the command actually exists.
*/
wchar_t *cmd =
(last_type == TOK_STRING) ?
expand_one(wcsdup(tok_last( &tok )),EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES) :
wcsdup(tok_last( &tok ));
wchar_t *cmd = expand_one( 0,
wcsdup(tok_last( &tok )),
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
if( cmd == 0 )
{
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
@@ -145,7 +145,6 @@ 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 ) )
{
@@ -248,7 +247,7 @@ void highlight_shell( wchar_t * buff,
{
case TOK_STRING:
{
target = expand_one( wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL);
target = expand_one( 0, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_SUBSHELL);
/*
Redirect filename may contain a subshell.
If so, it will be ignored/not flagged.

View File

@@ -19,6 +19,7 @@
#include "reader.h"
#include "env.h"
#include "sanity.h"
#include "signal.h"
/*
The history is implemented using a linked list. Searches are done
@@ -102,7 +103,7 @@ static void history_load()
is_loaded = 1;
block();
signal_block();
hash_init2( &used,
&hash_wcs_func,
&hash_wcs_cmp,
@@ -124,7 +125,7 @@ static void history_load()
fclose( in_stream );
free( fn );
free( buff );
unblock();
signal_unblock();
return;
}
@@ -181,7 +182,7 @@ static void history_load()
free( buff );
free( fn );
last_loaded = history_last;
unblock();
signal_unblock();
}
void history_init()

View File

@@ -1,2 +0,0 @@
complete -y btdownloadheadless.py

View File

@@ -1,33 +0,0 @@
# Bittorrent commands
for i in btdownloadcurses.py btdownloadheadless.py;
complete -c $i -l max_uploads -x -d (_ "Maximum uploads at once")
complete -c $i -l keepalive_interval -x -d (_ "Number of seconds between keepalives")
complete -c $i -l download_slice_size -x -d (_ "Bytes per request")
complete -c $i -l request_backlog -x -d (_ "Requests per pipe")
complete -c $i -l max_message_length -x -d (_ "Maximum length prefix encoding")
complete -c $i -l ip -d (_ "IP to report to the tracker") -x -a "(__fish_print_addresses)"
complete -c $i -l minport -d (_ "Minimum port to listen to")
complete -c $i -l maxport -d (_ "Maximum port to listen to")
complete -c $i -l responsefile -r -d (_ "File for server response")
complete -c $i -l url -x -d (_ "URL to get file from")
complete -c $i -l saveas -r -d (_ "Local file target")
complete -c $i -l timeout -x -d (_ "Time to close inactive socket")
complete -c $i -l timeout_check_interval -x -d (_ "Time between checking timeouts")
complete -c $i -l max_slice_length -x -d (_ "Maximum outgoing slice length")
complete -c $i -l max_rate_period -x -d (_ "Maximum time to guess rate")
complete -c $i -l bind -x -d (_ "IP to bind to locally") -a "(__fish_print_addresses)"
complete -c $i -l display_interval -x -d (_ "Time between screen updates")
complete -c $i -l rerequest_interval -x -d (_ "Time to wait between requesting more peers")
complete -c $i -l min_peers -x -d (_ "Minimum number of peers to not do requesting")
complete -c $i -l http_timeout -x -d (_ "Number of seconds before assuming http timeout")
complete -c $i -l max_initiate -x -d (_ "Number of peers at which to stop initiating new connections")
complete -c $i -l max_allow_in -x -d (_ "Maximum number of connections to allow")
complete -c $i -l check_hashes -x -d (_ "Whether to check hashes on disk")
complete -c $i -l max_upload_rate -x -d (_ "Maximum kB/s to upload at")
complete -c $i -l snub_time -x -d (_ "Seconds to wait for data to come in before assuming choking")
complete -c $i -l spew -x -d (_ "Whether to display diagnostic info")
complete -c $i -l rarest_first_cutoff -x -d (_ "Number of downloads at which to switch from random to rarest first")
complete -c $i -l min_uploads -x -d (_ "Number of uploads to fill out to with optimistic unchokes")
complete -c $i -l report_hash_failiures -x -d (_ "Whether to inform the user that hash failures occur")
end;

View File

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

View File

@@ -1 +0,0 @@
complete -y tex

View File

@@ -1 +0,0 @@
complete -y tex

View File

@@ -1,2 +0,0 @@
complete -y ls

View File

@@ -1 +0,0 @@
complete -y tex

View File

@@ -1,2 +0,0 @@
complete -y ls

View File

@@ -1,105 +0,0 @@
#
# Completions for the ls command and its aliases
#
# Test if we are using GNU ls
set -l is_gnu
ls --version >/dev/null ^/dev/null; and set is_gnu --is-gnu
set -l cmds -c ls -c ll -c la
# Shared ls switches
__fish_gnu_complete $cmds -s a -l all -d (_ "Show hidden") $is_gnu
__fish_gnu_complete $cmds -s A -l almost-all -d (_ "Show hidden except . and ..") $is_gnu
__fish_gnu_complete $cmds -s F -l classify -d (_ "Append filetype indicator") $is_gnu
__fish_gnu_complete $cmds -s H -l dereference-command-line -d (_ "Follow symlinks") $is_gnu
__fish_gnu_complete $cmds -s L -l dereference -d (_ "Follow symlinks") $is_gnu
__fish_gnu_complete $cmds -s R -l recursive -d (_ "List subdirectory recursively") $is_gnu
__fish_gnu_complete $cmds -s b -l escape -d (_ "Octal escapes for non graphic characters") $is_gnu
__fish_gnu_complete $cmds -s d -l directory -d (_ "List directories, not their content") $is_gnu
__fish_gnu_complete $cmds -s h -l human-readable -d (_ "Human readable sizes") $is_gnu
__fish_gnu_complete $cmds -s i -l inode -d (_ "Print inode number of files") $is_gnu
__fish_gnu_complete $cmds -s n -l numeric-uid-gid -d (_ "Long format, numeric IDs") $is_gnu
__fish_gnu_complete $cmds -s p -l file-type -d (_ "Append filetype indicator") $is_gnu
__fish_gnu_complete $cmds -s q -l hide-control-chars -d (_ "Replace non-graphic characters with '?'") $is_gnu
__fish_gnu_complete $cmds -s r -l reverse -d (_ "Reverse sort order") $is_gnu
__fish_gnu_complete $cmds -s s -l size -d (_ "Print size of files") $is_gnu
complete $cmds -s C -d (_ "List by columns")
complete $cmds -s S -d (_ "Sort by size")
complete $cmds -s c -d (_ "Show and sort by ctime")
complete $cmds -s f -d (_ "Don't sort")
complete $cmds -s g -d (_ "Long format without owner")
complete $cmds -s k -d (_ "Set blocksize to 1kB")
complete $cmds -s l -d (_ "Long format")
complete $cmds -s m -d (_ "Comma separated format")
complete $cmds -s t -d (_ "Sort by modification time")
complete $cmds -s u -d (_ "Show access time")
complete $cmds -s x -d (_ "List entries by lines")
complete $cmds -s 1 -d (_ "List one file per line")
if test -n "$is_gnu"
# GNU specific features
complete $cmds -l author -d (_ "Print author")
complete $cmds -l blocksize -x -d (_ "Set block size")
complete $cmds -s B -l ignore-backups -d (_ "Ignore files ending with ~")
complete $cmds -l color -f -a "never always auto" -d (_ "Use colors")
complete $cmds -s D -l dired -d (_ "Generate dired output")
complete $cmds -l format -x -a "across commas horizontal long single-column verbose vertical" -d (_ "List format")
complete $cmds -l full-time -d (_ "Long format, full-iso time")
complete $cmds -s G -l no-group -d (_ "Don't print group information")
complete $cmds -l si -d (_ "Human readable sizes, powers of 1000")
complete $cmds -l dereference-command-line-symlink-to-dir #-d (_ "Follow directory symlinks from command line")
complete $cmds -l indicator-style -x -a "none classify file-type" -d (_ "Append filetype indicator")
complete $cmds -s I -l ignore -r -d (_ "Skip entries matching pattern")
complete $cmds -s N -l literal -d (_ "Print raw entry names")
complete $cmds -s o -d (_ "Long format without groups")
complete $cmds -l show-control-chars -d (_ "Non graphic as-is")
complete $cmds -s Q -l quote-name -d (_ "Enclose entry in quotes")
complete $cmds -l quoting-style -x -a "literal locale shell shell-always c escape" -d (_ "Select quoting style")
complete $cmds -l sort -x -d (_ "Sort criteria") -a "
extension\t'Sort by file extension'
none\tDon't\ sort
size\t'Sort by size'
time\t'Sort by modification time'
version\t'Sort by version'
status\t'Sort by file status modification time'
atime\t'Sort by access time'
access\t'Sort by access time'
use\t'Sort by access time'
"
complete $cmds -l time -x -d (_ "Show time type") -a "
time\t'Sort by modification time'
access\t'Sort by access time'
use\t'Sort by use time'
ctime\t'Sort by file status modification time'
status\t'Sort by status time'
"
complete $cmds -l time-style -x -a "full-iso long-iso iso locale" -d (_ "Select time style")
complete $cmds -s T -l tabsize -x -a "1 2 3 4 5 6 7 8 9 10 11 12" -d (_ "Assume tab stops at each COLS")
complete $cmds -s U -d (_ "Do not sort")
complete $cmds -s v -d (_ "Sort by version")
complete $cmds -s w -l width -x -d (_ "Assume screen width")
complete $cmds -s X -d (_ "Sort by extension")
complete $cmds -l help -d (_ "Display help and exit")
complete $cmds -l version -d (_ "Display version and exit")
else
# If not a GNU system, assume we have standard BSD ls features instead
complete $cmds -s B -d (_ "Octal escapes for non graphic characters")
complete $cmds -s G -d (_ "Use colors")
complete $cmds -s I -d (_ "Prevent -A from being automatically set for root")
complete $cmds -s P -d (_ "Don't follow symlinks")
complete $cmds -s T -d (_ "Show modification time")
complete $cmds -s W -d (_ "Show whiteouts when scanning directories")
complete $cmds -s Z -d (_ "Display each file's MAC label")
complete $cmds -s o -d (_ "Include the file flags in a long (-l) output")
complete $cmds -s w -d (_ "Print raw entry names")
end

View File

@@ -1 +0,0 @@
complete -y tex

View File

@@ -1 +0,0 @@
complete -y tex

View File

@@ -1 +0,0 @@
complete -y tex

View File

@@ -1 +0,0 @@
complete -y tex

View File

@@ -1 +0,0 @@
complete -y tex

View File

@@ -1,7 +0,0 @@
set -l cmds -c etex -c tex -c elatex -c latex -c pdflatex -c pdfelatex -c pdftex -c pdfetex -c omega
complete $cmds -o help -d (_ "Display help and exit")
complete $cmds -o version -d (_ "Display version and exit")
complete $cmds -x -a "(
__fish_complete_suffix (commandline -ct) .tex '(La)TeX file'
)"

View File

@@ -1,362 +0,0 @@
# Main file for fish command completions. This file contains various
# common helper functions for the command completions. All actual
# completions are located in the completions subdirectory.
#
# @configure_input@
#
# Don't need completions in non-interactive mode
#
if not status --is-interactive
exit
end
set -g fish_complete_path @SYSCONFDIR@/fish.d/completions ~/.fish.d/completions
# Knowing the location of the whatis database speeds up command
# description lookup.
for i in /var/cache/man/{whatis,windex} /usr{,/local}{,/share}/man/{whatis,windex}
if test -f $i
set -g __fish_whatis_path $i
break
end
end
#
# Convenience functions
#
# The naming heuristic is that __fish_complete_* prints completions
# and descriptions, while __fish_print_* only prints the completion,
# without the description
#
#
# Find files that complete $argv[1], has the suffix $argv[2], and
# output them as completions with description $argv[3]
#
function __fish_complete_suffix -d "Complete using files"
set -- comp $argv[1]
set -- suff $argv[2]
set -- desc $argv[3]
set -- base (echo $comp |sed -e 's/\.[a-zA-Z0-9]*$//')
eval "set -- files $base*$suff"
if test $files[1]
printf "%s\t$desc\n" $files
end
#
# Also do directory completion, since there might be files
# with the correct suffix in a subdirectory
#
__fish_complete_directory $comp
end
#
# Find directories that complete $argv[1], output them as completions
# with description $argv[2] if defined, otherwise use 'Directory'
#
function __fish_complete_directory -d "Complete using directories"
set -- comp $argv[1]
set -- desc (_ Directory)
if test (count $argv) -gt 1
set desc $argv[2]
end
eval "set -- dirs "$comp"*/"
if test $dirs[1]
printf "%s\t$desc\n" $dirs
end
end
function __fish_complete_users -d "Print a list of local users, with the real user name as a description"
cat /etc/passwd | sed -e "s/^\([^:]*\):[^:]*:[^:]*:[^:]*:\([^:]*\):.*/\1\t\2/"
end
function __fish_complete_groups -d "Print a list of local groups, with group members as the description"
cat /etc/group | sed -e "s/^\([^:]*\):[^:]*:[^:]*:\(.*\)/\1\tMembers: \2/"
end
function __fish_complete_pids -d "Print a list of process identifiers along with brief descriptions"
# This may be a bit slower, but it's nice - having the tty displayed is really handy
ps --no-heading -o pid,comm,tty --ppid %self -N | sed -r 's/ *([0-9]+) +([^ ].*[^ ]|[^ ]) +([^ ]+)$/\1\t\2 [\3]/' ^/dev/null
# If the above is too slow, this is faster but a little less useful
# pgrep -l -v -P %self | sed 's/ /\t/'
end
function __fish_complete_command -d "Complete using all available commands"
printf "%s\n" (commandline -ct)(complete -C (commandline -ct))
end
function __fish_complete_subcommand -d "Complete subcommand"
set -l res ""
set -l had_cmd 0
set -l cmd (commandline -cop) (commandline -ct)
set -l skip_next 1
for i in $cmd
if test "$skip_next" = 1
set skip_next 0
continue
end
if test "$had_cmd" = 1
set res "$res $i"
else
if contains -- $i $argv
set skip_next 1
continue
end
switch $i
case '-*'
case '*'
set had_cmd 1
set res $i
end
end
end
printf "%s\n" (commandline -ct)(complete -C $res)
end
function __fish_print_hostnames -d "Print a list of known hostnames"
# Print all hosts from /etc/hosts
if test -f /etc/hosts
sed </etc/hosts -e 's/[0-9.]*\( \|\t\)*\(.*\)/\2/'|sed -e 's/\#.*//'|tr \t \n |grep -v '^$'
end
# Print nfs servers from /etc/fstab
if test -f /etc/fstab
grep </etc/fstab "^\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\|[a-zA-Z.]*\):"|cut -d : -f 1
end
# Print hosts with known ssh keys
cat ~/.ssh/known_hosts{,2} ^/dev/null|cut -d ' ' -f 1| cut -d , -f 1
end
function __fish_print_interfaces -d "Print a list of known network interfaces"
netstat -i -n -a | awk 'NR>2'|awk '{print $1}'
end
function __fish_print_addresses -d "Print a list of known network addresses"
/sbin/ifconfig |grep 'inet addr'|cut -d : -f 2|cut -d ' ' -f 1
end
function __fish_print_users -d "Print a list of local users"
cat /etc/passwd | cut -d : -f 1
end
function __fish_contains_opt -d "Checks if a specific option has been given in the current commandline"
set -l next_short
set -l short_opt
set -l long_opt
for i in $argv
if test $next_short
set next_short
set -- short_opt $short_opt $i
else
switch $i
case -s
set next_short 1
case '-*'
echo __fish_contains_opt: Unknown option $i
return 1
case '**'
set -- long_opt $long_opt $i
end
end
end
for i in $short_opt
if test -z $i
continue
end
if commandline -cpo | grep -- "^-"$i"\|^-[^-]*"$i >/dev/null
return 0
end
if commandline -ct | grep -- "^-"$i"\|^-[^-]*"$i >/dev/null
return 0
end
end
for i in $long_opt
if test -z $i
continue
end
if contains -- --$i (commandline -cpo)
return 0
end
end
return 1
end
#
# Completions for the shell and it's builtin commands and functions
#
set -l __fish_help_desc (_ "Display help and exit")
for i in (builtin -n|grep -vE '(while|for|if|function|switch)' )
complete -c $i -s h -l help -d $__fish_help_desc
end
function __fish_print_packages
# apt-cache is much, much faster than rpm, and can do this in real
# time. We use it if available.
switch (commandline -tc)
case '-**'
return
end
#Get the word 'Package' in the current language
set -l package (_ Package)
if which apt-cache >/dev/null ^/dev/null
# Apply the following filters to output of apt-cache:
# 1) Remove package names with parentesis in them, since these seem to not correspond to actual packages as reported by rpm
# 2) Remove package names that are .so files, since these seem to not correspond to actual packages as reported by rpm
# 3) Remove path information such as /usr/bin/, as rpm packages do not have paths
apt-cache --no-generate pkgnames (commandline -tc)|grep -v \( |grep -v '\.so\(\.[0-9]\)*$'|sed -e 's/\/.*\///'|sed -e 's/$/\t'$package'/'
return
end
# Rpm is too slow for this job, so we set it up to do completions
# as a background job and cache the results.
if which rpm >/dev/null ^/dev/null
# If the cache is less than five minutes old, we do not recalculate it
set cache_file /tmp/.rpm-cache.$USER
if test -f $cache_file
cat $cache_file
set age (echo (date +%s) - (stat -c '%Y' $cache_file) | bc)
set max_age 250
if test $age -lt $max_age
return
end
end
# Remove package version information from output and pipe into cache file
rpm -qa >$cache_file |sed -e 's/-[^-]*-[^-]*$//' | sed -e 's/$/\t'$package'/' &
end
# This completes the package name from the portage tree.
# True for installing new packages. Function for printing
# installed on the system packages is in completions/emerge.fish
if which emerge >/dev/null ^/dev/null
emerge -s \^(commandline -tc) |grep "^*" |cut -d\ -f3 |cut -d/ -f2
return
end
end
function __fish_append -d "Internal completion function for appending string to the commandline"
set separator $argv[1]
set -e argv[1]
set str (commandline -tc| sed -ne "s/\(.*$separator\)[^$separator]*/\1/p"|sed -e "s/--.*=//")
printf "%s\n" "$str"$argv "$str"(printf "%s\n" $argv|sed -e "s/\(\t\|\$\)/,\1/")
end
function __fish_gnu_complete -d "Wrapper for the complete builtin. Skips the long completions on non-GNU systems"
set is_gnu 0
# Check if we are using a gnu system
for i in (seq (count $argv))
switch $argv[$i]
case -g --is-gnu
set -e argv[$i]
set is_gnu 1
break
end
end
# Remove long option if not on a gnu system
if test $is_gnu = 0
for i in (seq (count $argv))
if test $argv[$i] = -l
set -e argv[$i]
set -e argv[$i]
break
end
end
end
complete $argv
end
function __fish_is_first_token -d 'Test if no non-switch argument has been specified yet'
set -- cmd (commandline -poc)
set -e -- cmd[1]
for i in $cmd
switch $i
case '-*'
case '*'
return 1;
end
end
return 0
end
function __fish_no_arguments -d "Internal fish function"
set -l cmd (commandline -poc) (commandline -tc)
set -e cmd[1]
for i in $cmd
switch $i
case '-*'
case '*'
return 1
end
end
return 0
end
#
# Completions for SysV startup scripts
#
complete -x -p "/etc/init.d/*" -a start\t(_ 'Start service')
complete -x -p "/etc/init.d/*" -a stop\t(_ 'Stop service')
complete -x -p "/etc/init.d/*" -a status\t(_ 'Print service status')
complete -x -p "/etc/init.d/*" -a restart\t(_ 'Stop and then start service')
complete -x -p "/etc/init.d/*" -a reload\t(_ 'Reload service configuration')

File diff suppressed because it is too large Load Diff

View File

@@ -55,7 +55,9 @@ implementation in fish is as of yet incomplete.
#include "env.h"
#include "expand.h"
#include "event.h"
#include "signal.h"
#include "translate.h"
#include "output.h"
static void input_read_inputrc( wchar_t *fn );
@@ -1085,7 +1087,7 @@ static void input_read_inputrc( wchar_t *fn )
int error=0;
// fwprintf( stderr, L"read %ls\n", fn );
block();
signal_block();
rc = wfopen( fn, "r" );
if( rc )
@@ -1120,7 +1122,7 @@ static void input_read_inputrc( wchar_t *fn )
free( buff );
fclose( rc );
}
unblock();
signal_unblock();
inputrc_skip_block_count=0;
inputrc_block_count=0;

2
kill.c
View File

@@ -136,7 +136,7 @@ static void kill_check_x_buffer()
for( i=0; i<al_get_count( &list ); i++ )
{
wchar_t *next_line = escape( (wchar_t *)al_get( &list, i ), 0);
wchar_t *next_line = escape( (wchar_t *)al_get( &list, i ), 0 );
if( i==0 )
{
new_cut_buffer = next_line;

44
main.c
View File

@@ -57,6 +57,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "event.h"
#include "output.h"
#include "translate.h"
#include "halloc_util.h"
/**
Parse init files
@@ -73,7 +74,8 @@ static int read_init()
}
env_set( L"__fish_help_dir", DOCDIR, 0);
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; . fish 2>/dev/null", 0, TOP );
eval( L"builtin cd " SYSCONFDIR L" 2>/dev/null; . fish 2>/dev/null", 0, TOP );
eval( L"builtin cd 2>/dev/null;. .fish 2>/dev/null", 0, TOP );
@@ -120,6 +122,10 @@ int main( int argc, char **argv )
"command", required_argument, 0, 'c'
}
,
{
"debug-level", required_argument, 0, 'd'
}
,
{
"interactive", no_argument, 0, 'i'
}
@@ -150,14 +156,14 @@ int main( int argc, char **argv )
int opt = getopt_long( argc,
argv,
"hilvc:p:",
"hilvc:p:d:",
long_options,
&opt_index );
#else
int opt = getopt( argc,
argv,
"hilvc:p:" );
"hilvc:p:d:" );
#endif
if( opt == -1 )
break;
@@ -172,6 +178,22 @@ int main( int argc, char **argv )
is_interactive_session = 0;
break;
case 'd':
{
char *end;
int tmp = strtol(optarg, &end, 10);
if( tmp >= 0 && tmp <=10 && !*end )
{
debug_level=tmp;
}
else
{
debug( 0, _(L"Invalid value '%s' for debug level switch"), optarg );
exit(1);
}
break;
}
case 'h':
cmd = "help";
break;
@@ -203,16 +225,17 @@ int main( int argc, char **argv )
my_optind = optind;
is_login |= strcmp( argv[0], "-fish") == 0;
is_login |= (strcmp( argv[0], "-fish") == 0);
is_interactive_session &= (cmd == 0);
is_interactive_session &= (my_optind == argc);
is_interactive_session &= isatty(STDIN_FILENO);
is_interactive_session |= force_interactive;
translate_init();
common_init();
halloc_util_init();
proc_init();
output_init();
event_init();
exec_init();
wutil_init();
@@ -230,7 +253,7 @@ int main( int argc, char **argv )
wchar_t *cmd_wcs = str2wcs( cmd );
res = eval( cmd_wcs, 0, TOP );
free(cmd_wcs);
reader_exit(0);
reader_exit(0);
}
else
{
@@ -293,20 +316,19 @@ int main( int argc, char **argv )
proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res );
complete_destroy();
proc_destroy();
env_destroy();
builtin_destroy();
function_destroy();
complete_destroy();
reader_destroy();
parser_destroy();
wutil_destroy();
common_destroy();
exec_destroy();
event_destroy();
output_destroy();
translate_destroy();
common_destroy();
halloc_util_destroy();
intern_free_all();
return res;

145
output.c
View File

@@ -43,6 +43,7 @@
#include "expand.h"
#include "common.h"
#include "output.h"
#include "halloc_util.h"
#include "highlight.h"
/**
@@ -50,6 +51,8 @@
*/
#define COLORS (sizeof(col)/sizeof(wchar_t *))
static int writeb_internal( char c );
/**
Names of different colors.
*/
@@ -101,15 +104,22 @@ static size_t writestr_buff_sz=0;
*/
static char *writestr_buff = 0;
void output_init()
{
}
/**
The function used for output
*/
void output_destroy()
static int (*out)(char c) = &writeb_internal;
static void output_destroy()
{
free( writestr_buff );
}
void output_set_writer( int (*writer)(char) )
{
out = writer;
}
void set_color( int c, int c2 )
{
@@ -133,7 +143,9 @@ void set_color( int c, int c2 )
{
c = c2 = FISH_COLOR_NORMAL;
if( fg )
{
writembs( tparm( fg, 0 ) );
}
writembs( exit_attribute_mode );
return;
}
@@ -193,12 +205,14 @@ void set_color( int c, int c2 )
if( c==FISH_COLOR_NORMAL )
{
if( fg )
{
writembs( tparm( fg, 0 ) );
}
writembs( exit_attribute_mode );
last_color2 = FISH_COLOR_NORMAL;
}
else if( ( c >= 0) && ( c < FISH_COLOR_NORMAL ) )
else if( ( c >= 0 ) && ( c < FISH_COLOR_NORMAL ) )
{
if( fg )
{
@@ -218,15 +232,15 @@ void set_color( int c, int c2 )
writembs( tparm( bg, 0 ) );
}
writembs(exit_attribute_mode);
if(( last_color != FISH_COLOR_NORMAL ) && fg )
writembs( exit_attribute_mode );
if( ( last_color != FISH_COLOR_NORMAL ) && fg )
{
writembs(tparm( fg, last_color ));
writembs( tparm( fg, last_color ) );
}
last_color2 = c2;
}
else if ((c2 >= 0 ) &&(c2 < FISH_COLOR_NORMAL))
else if ( ( c2 >= 0 ) && ( c2 < FISH_COLOR_NORMAL ) )
{
if( bg )
{
@@ -237,40 +251,96 @@ void set_color( int c, int c2 )
}
}
/**
perm_left_cursor and parm_right_cursor don't seem to be properly
emulated by many terminal emulators, so we only use plain
curor_left, curor_right...
*/
void move_cursor( int steps )
{
int i;
if( !steps )
return;
if( steps < 0 ){
for( i=0; i>steps; i--)
{
writembs(cursor_left);
}
}
else
{
for( i=0; i<steps; i++)
{
writembs(cursor_right);
}
}
}
static int writeb_internal( char c )
{
write( 1, &c, 1 );
return 0;
}
int writeb( tputs_arg_t b )
{
out( b );
return 0;
}
int writembs( char *str )
{
#ifdef TPUTS_KLUDGE
write( 1, str, strlen(str));
while( *str )
{
out( *str );
}
#else
tputs(str,1,&writeb);
tputs(str,1,writeb);
#endif
return 0;
}
int writech( wint_t ch )
{
static mbstate_t out_state;
char buff[MB_CUR_MAX];
size_t bytes = wcrtomb( buff, ch, &out_state );
int err;
while( (err =write( 1, buff, bytes ) ) )
mbstate_t state;
int i;
char buff[MB_CUR_MAX+1];
size_t bytes;
if( ( ch >= ENCODE_DIRECT_BASE) &&
( ch < ENCODE_DIRECT_BASE+256) )
{
if( err >= 0 )
break;
buff[0] = ch - ENCODE_DIRECT_BASE;
bytes=1;
}
else
{
memset( &state, 0, sizeof(state) );
bytes= wcrtomb( buff, ch, &state );
if( errno == EINTR )
continue;
wperror( L"write" );
return 1;
switch( bytes )
{
case (size_t)(-1):
{
return 1;
}
}
}
for( i=0; i<bytes; i++ )
{
out( buff[i] );
}
return 0;
}
void writestr( const wchar_t *str )
{
char *pos;
// while( *str )
// writech( *str++ );
@@ -292,9 +362,16 @@ void writestr( const wchar_t *str )
*/
if( writestr_buff_sz < len )
{
if( !writestr_buff )
{
halloc_register_function_void( global_context, &output_destroy );
}
writestr_buff = realloc( writestr_buff, len );
if( !writestr_buff )
{
die_mem();
}
writestr_buff_sz = len;
}
@@ -308,8 +385,10 @@ void writestr( const wchar_t *str )
/*
Write
*/
write( 1, writestr_buff, strlen( writestr_buff ) );
for( pos = writestr_buff; *pos; pos++ )
{
out( *pos );
}
}
@@ -328,7 +407,9 @@ void writestr_ellipsis( const wchar_t *str, int max_width )
{
int w = wcwidth( *str );
if( written+w+wcwidth( ellipsis_char )>max_width )
{
break;
}
written+=w;
writech( *(str++) );
}
@@ -386,13 +467,13 @@ int writespace( int c )
}
else
{
write( 1, " ", mini(c,8) );
if( c>8)
int i;
for( i=0; i<c; i++ )
{
writespace( c-8);
out( ' ' );
}
}
return 0;
}
@@ -411,7 +492,11 @@ int output_color_code( const wchar_t *val )
}
if( color >= 0 )
{
return color;
}
else
{
return FISH_COLOR_NORMAL;
}
}

View File

@@ -80,7 +80,9 @@ void set_color( int c, int c2 );
/**
Write a char * narrow string to FD 1, needed for the terminfo
strings.
strings. This is usually just a wrapper aound tputs, using writeb
as the sending function. But a weird bug on PPC Linux means that on
this platform, write is instead used directly.
*/
int writembs( char *str );
@@ -117,13 +119,25 @@ int writespace( int c );
int output_color_code( const wchar_t *val );
/**
Initialize static data
perm_left_cursor and parm_right_cursor don't seem to be defined
very often so we use cursor_left and cursor_right as a fallback.
*/
void output_init();
void move_cursor( int steps );
/**
Destroy static data
This is for writing process notification messages. Has to write to
stdout, so clr_eol and such functions will work correctly. Not an
issue since this function is only used in interactive mode anyway.
*/
void output_destroy();
int writeb( tputs_arg_t b );
/**
Set the function used for writing in move_cursor, writespace and
set_color and all other output functions in this library. By
default, the write call is used to give completely unbuffered
output to stdout.
*/
void output_set_writer( int (*writer)(char) );
#endif

View File

@@ -1,6 +1,7 @@
/** \file parse_util.c
Various utility functions for parsing a command
Various mostly unrelated utility functions related to parsing,
loading and evaluating fish code.
*/
#include "config.h"
@@ -13,6 +14,7 @@
#include <wchar.h>
#include <time.h>
#include <assert.h>
#include "util.h"
@@ -20,13 +22,30 @@
#include "common.h"
#include "tokenizer.h"
#include "parse_util.h"
#include "expand.h"
#include "intern.h"
#include "exec.h"
#include "env.h"
#include "wildcard.h"
#include "halloc_util.h"
/**
Set of files which have been autoloaded
*/
static hash_table_t *all_loaded=0;
int parse_util_lineno( const wchar_t *str, int len )
{
static int res = 1;
static int i=0;
/**
First cached state
*/
static const wchar_t *prev_str = 0;
static int i=0;
static int res = 1;
/**
Second cached state
*/
static const wchar_t *prev_str2 = 0;
static int i2 = 0;
static int res2 = 1;
@@ -84,7 +103,7 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
{
if( wcschr( L"\'\"", *pos ) )
{
wchar_t *end = quote_end( pos );
const wchar_t *end = quote_end( pos );
if( end && *end)
{
pos=end;
@@ -98,7 +117,7 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
{
if(( paran_count == 0)&&(paran_begin==0))
paran_begin = pos;
paran_count++;
}
else if( *pos == ')' )
@@ -136,16 +155,12 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
return 0;
}
*begin = paran_begin;
*end = paran_count?in+wcslen(in):paran_end;
if( begin )
*begin = paran_begin;
if( end )
*end = paran_count?in+wcslen(in):paran_end;
/* assert( *begin >= in );
assert( *begin < (in+wcslen(in) ) );
assert( *end >= *begin );
assert( *end < (in+wcslen(in) ) );
*/
return 1;
}
@@ -228,7 +243,6 @@ static void job_or_process_extent( const wchar_t *buff,
return;
pos = cursor_pos - (begin - buff);
// fwprintf( stderr, L"Subshell extent: %d %d %d\n", begin-buff, end-buff, pos );
if( a )
{
@@ -246,14 +260,12 @@ static void job_or_process_extent( const wchar_t *buff,
{
die_mem();
}
// fwprintf( stderr, L"Strlen: %d\n", wcslen(buffcpy ) );
for( tok_init( &tok, buffcpy, TOK_ACCEPT_UNFINISHED );
tok_has_next( &tok ) && !finished;
tok_next( &tok ) )
{
int tok_begin = tok_get_pos( &tok );
// fwprintf( stderr, L".");
switch( tok_last_type( &tok ) )
{
@@ -264,8 +276,6 @@ static void job_or_process_extent( const wchar_t *buff,
case TOK_END:
case TOK_BACKGROUND:
{
// fwprintf( stderr, L"New cmd at %d\n", tok_begin );
if( tok_begin >= pos )
{
@@ -284,7 +294,6 @@ static void job_or_process_extent( const wchar_t *buff,
}
}
// fwprintf( stderr, L"Res: %d %d\n", *a-buff, *b-buff );
free( buffcpy);
tok_destroy( &tok );
@@ -418,5 +427,263 @@ void parse_util_token_extent( const wchar_t *buff,
}
/**
Free hash value, but not hash key
*/
static void clear_hash_value( const void *key, const void *data )
{
free( (void *)data );
}
/**
Part of the autoloader cleanup
*/
static void clear_loaded_entry( const void *key, const void *data )
{
hash_table_t *loaded = (hash_table_t *)data;
hash_foreach( loaded,
&clear_hash_value );
hash_destroy( loaded );
free( loaded );
free( (void *)key );
}
/**
The autoloader cleanup function. It is run on shutdown and frees
any memory used by the autoloader code to keep track of loaded
files.
*/
static void parse_util_destroy()
{
if( all_loaded )
{
hash_foreach( all_loaded,
&clear_loaded_entry );
hash_destroy( all_loaded );
free( all_loaded );
all_loaded = 0;
}
}
void parse_util_load_reset( const wchar_t *path_var )
{
if( all_loaded )
{
void *key, *data;
hash_remove( all_loaded, path_var, (const void **)&key, (const void **)&data );
if( key )
clear_loaded_entry( key, data );
}
}
int parse_util_load( const wchar_t *cmd,
const wchar_t *path_var_name,
void (*on_load)(const wchar_t *cmd),
int reload )
{
static array_list_t *path_list=0;
static string_buffer_t *path=0;
int i;
time_t *tm;
int reloaded = 0;
hash_table_t *loaded;
const wchar_t *path_var = env_get( path_var_name );
/*
Do we know where to look
*/
if( !path_var )
return 0;
if( !all_loaded )
{
all_loaded = malloc( sizeof( hash_table_t ) );
halloc_register_function_void( global_context, &parse_util_destroy );
if( !all_loaded )
{
die_mem();
}
hash_init( all_loaded, &hash_wcs_func, &hash_wcs_cmp );
}
loaded = (hash_table_t *)hash_get( all_loaded, path_var_name );
if( !loaded )
{
loaded = malloc( sizeof( hash_table_t ) );
if( !loaded )
{
die_mem();
}
hash_init( loaded, &hash_wcs_func, &hash_wcs_cmp );
hash_put( all_loaded, wcsdup(path_var_name), loaded );
}
/*
Get modification time of file
*/
tm = (time_t *)hash_get( loaded, cmd );
/*
Did we just check this?
*/
if( tm )
{
if(time(0)-tm[1]<=1)
{
return 0;
}
}
/*
Return if already loaded and we are skipping reloading
*/
if( !reload && tm )
return 0;
if( !path_list )
path_list = al_halloc( global_context);
if( !path )
path = sb_halloc( global_context );
else
sb_clear( path );
expand_variable_array( path_var, path_list );
/*
Iterate over path searching for suitable completion files
*/
for( i=0; i<al_get_count( path_list ); i++ )
{
struct stat buf;
wchar_t *next = (wchar_t *)al_get( path_list, i );
sb_clear( path );
sb_append2( path, next, L"/", cmd, L".fish", (void *)0 );
if( (wstat( (wchar_t *)path->buff, &buf )== 0) &&
(waccess( (wchar_t *)path->buff, R_OK ) == 0) )
{
if( !tm || (tm[0] != buf.st_mtime ) )
{
wchar_t *esc = escape( (wchar_t *)path->buff, 1 );
wchar_t *src_cmd = wcsdupcat( L". ", esc );
if( !tm )
{
tm = malloc(sizeof(time_t)*2);
if( !tm )
die_mem();
}
tm[0] = buf.st_mtime;
tm[1] = time(0);
hash_put( loaded,
intern( cmd ),
tm );
free( esc );
if( on_load )
on_load(cmd );
/*
Source the completion file for the specified completion
*/
exec_subshell( src_cmd, 0 );
free(src_cmd);
reloaded = 1;
break;
}
}
}
/*
If no file was found we insert the current time. Later we only
research if the current time is at least five seconds later.
This way, the files won't be searched over and over again.
*/
if( !tm )
{
tm = malloc(sizeof(time_t)*2);
if( !tm )
die_mem();
tm[0] = 0;
tm[1] = time(0);
hash_put( loaded, intern( cmd ), tm );
}
al_foreach( path_list, (void (*)(const void *))&free );
al_truncate( path_list, 0 );
return reloaded;
}
void parse_util_set_argv( wchar_t **argv )
{
if( *argv )
{
wchar_t **arg;
string_buffer_t sb;
sb_init( &sb );
for( arg=argv; *arg; arg++ )
{
if( arg != argv )
sb_append( &sb, ARRAY_SEP_STR );
sb_append( &sb, *arg );
}
env_set( L"argv", (wchar_t *)sb.buff, ENV_LOCAL );
sb_destroy( &sb );
}
else
{
env_set( L"argv", 0, ENV_LOCAL );
}
}
wchar_t *parse_util_unescape_wildcards( const wchar_t *str )
{
wchar_t *in, *out;
wchar_t *unescaped = wcsdup(str);
if( !unescaped )
die_mem();
for( in=out=unescaped; *in; in++ )
{
switch( *in )
{
case L'\\':
if( *(in+1) )
{
in++;
*(out++)=*in;
}
*(out++)=*in;
break;
case L'*':
*(out++)=ANY_STRING;
break;
case L'?':
*(out++)=ANY_CHAR;
break;
default:
*(out++)=*in;
break;
}
}
return unescaped;
}

View File

@@ -1,6 +1,7 @@
/** \file parse_util.h
Various utility functions for parsing a command
Various mostly unrelated utility functions related to parsing,
loading and evaluating fish code.
*/
#ifndef FISH_PARSE_UTIL_H
@@ -9,7 +10,7 @@
#include <wchar.h>
/**
Locate the first subshell in the specified string.
Find the beginning and end of the first subshell in the specified string.
\param in the string to search for subshells
\param begin the starting paranthesis of the subshell
@@ -23,23 +24,54 @@ int parse_util_locate_cmdsubst( const wchar_t *in,
const wchar_t **end,
int allow_incomplete );
/**
Find the beginning and end of the command substitution under the cursor
\param buff the string to search for subshells
\param cursor_pos the position of the cursor
\param a the start of the searched string
\param b the end of the searched string
*/
void parse_util_cmdsubst_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **a,
const wchar_t **b );
/**
Find the beginning and end of the process definition under the cursor
\param buff the string to search for subshells
\param cursor_pos the position of the cursor
\param a the start of the searched string
\param b the end of the searched string
*/
void parse_util_process_extent( const wchar_t *buff,
int pos,
int cursor_pos,
const wchar_t **a,
const wchar_t **b );
/**
Find the beginning and end of the job definition under the cursor
\param buff the string to search for subshells
\param cursor_pos the position of the cursor
\param a the start of the searched string
\param b the end of the searched string
*/
void parse_util_job_extent( const wchar_t *buff,
int pos,
int cursor_pos,
const wchar_t **a,
const wchar_t **b );
/**
Find the beginning and end of the token under the cursor
\param buff the string to search for subshells
\param cursor_pos the position of the cursor
\param a the start of the searched string
\param b the end of the searched string
*/
void parse_util_token_extent( const wchar_t *buff,
int cursor_pos,
const wchar_t **tok_begin,
@@ -47,7 +79,41 @@ void parse_util_token_extent( const wchar_t *buff,
const wchar_t **prev_begin,
const wchar_t **prev_end );
/**
Get the linenumber at the specified character offset
*/
int parse_util_lineno( const wchar_t *str, int len );
/**
Autoload the specified file, if it exists in the specified path. Do
not load it multiple times unless it's timestamp changes.
\param cmd the filename to search for. The suffix '.fish' is always added to this name
\param path_var_name the name of an environment variable containing a search path
\param on_load a callback function to run if a suitable file is found, which has not already been run
\param reload wheter to recheck file timestamps on already loaded files
*/
int parse_util_load( const wchar_t *cmd,
const wchar_t *path_var_name,
void (*on_load)(const wchar_t *cmd),
int reload );
/**
Reset the loader for the specified path variable
*/
void parse_util_load_reset( const wchar_t *path_var );
/**
Set the argv environment variable to the specified null-terminated
array of strings.
*/
void parse_util_set_argv( wchar_t **argv );
/**
Make a duplicate of the specified string, unescape wildcard
characters but not performing any other character transformation.
*/
wchar_t *parse_util_unescape_wildcards( const wchar_t *in );
#endif

327
parser.c
View File

@@ -39,6 +39,7 @@ The fish parser. Contains functions for parsing code.
#include "intern.h"
#include "parse_util.h"
#include "halloc.h"
#include "halloc_util.h"
/**
Maximum number of block levels in code. This is not the same as
@@ -70,9 +71,9 @@ The fish parser. Contains functions for parsing code.
#define TOK_ERR_MSG _( L"Tokenizer error: '%ls'")
/**
Error message for short circut command error.
Error message for short circuit command error.
*/
#define COND_ERR_MSG _( L"Short circut command requires additional command")
#define COND_ERR_MSG _( L"Short circuit command requires additional command")
/**
Error message on reaching maximum recusrion depth
@@ -340,15 +341,13 @@ static int block_count( block_t *b )
void parser_push_block( int type )
{
block_t *new = halloc( 0, sizeof( block_t ));
new->src_lineno = parser_get_lineno();
new->src_filename = parser_current_filename()?intern(parser_current_filename()):0;
// debug( 3, L"Block push %ls %d\n", parser_get_block_desc(type), block_count( current_block)+1 );
new->outer = current_block;
new->type = (current_block && current_block->skip)?FAKE:type;
/*
New blocks should be skipped if the outer block is skipped,
except TOP ans SUBST block, which open up new environments. Fake
@@ -356,12 +355,15 @@ void parser_push_block( int type )
*/
new->skip=current_block?current_block->skip:0;
if( type == TOP || type == SUBST )
{
new->skip = 0;
}
if( type == FAKE )
{
new->skip = 1;
}
new->job = 0;
new->loop_status=LOOP_NORMAL;
current_block = new;
@@ -371,20 +373,12 @@ void parser_push_block( int type )
(new->type != TOP) )
{
env_push( type == FUNCTION_CALL );
halloc_register_function_void( current_block, &env_pop );
}
}
void parser_pop_block()
{
// debug( 3, L"Block pop %ls %d\n", parser_get_block_desc(current_block->type), block_count(current_block)-1 );
if( (current_block->type != FUNCTION_DEF ) &&
(current_block->type != FAKE) &&
(current_block->type != TOP) )
{
env_pop();
}
block_t *old = current_block;
current_block = current_block->outer;
halloc_free( old );
@@ -470,7 +464,7 @@ int parser_is_subcommand( const wchar_t *cmd )
Test if the specified string is command that opens a new block
*/
static int parser_is_block( wchar_t *word)
static int parser_is_block( const wchar_t *word)
{
return contains_str( word,
L"for",
@@ -482,7 +476,7 @@ static int parser_is_block( wchar_t *word)
(void *)0 );
}
int parser_is_reserved( wchar_t *word)
int parser_is_reserved( const wchar_t *word)
{
return parser_is_block(word) ||
parser_is_subcommand( word ) ||
@@ -605,7 +599,7 @@ wchar_t *parser_cdpath_get( wchar_t *dir )
return 0;
if( dir[0] == L'/' )
if( dir[0] == L'/'|| (wcsncmp( dir, L"./", 2 )==0) )
{
struct stat buf;
if( wstat( dir, &buf ) == 0 )
@@ -714,9 +708,9 @@ wchar_t *get_filename( const wchar_t *cmd )
{
wchar_t *path;
debug( 2, L"get_filename( '%ls' )", cmd );
debug( 3, L"get_filename( '%ls' )", cmd );
if(wcschr( cmd, '/' ) != 0 )
if(wcschr( cmd, L'/' ) != 0 )
{
if( waccess( cmd, X_OK )==0 )
{
@@ -744,11 +738,10 @@ wchar_t *get_filename( const wchar_t *cmd )
wchar_t *path_cpy = wcsdup( path );
wchar_t *nxt_path = path;
wchar_t *state;
if( (new_cmd==0) || (path_cpy==0) )
{
die_mem();
}
for( nxt_path = wcstok( path_cpy, ARRAY_SEP_STR, &state );
@@ -757,9 +750,9 @@ wchar_t *get_filename( const wchar_t *cmd )
{
int path_len = wcslen( nxt_path );
wcscpy( new_cmd, nxt_path );
if( new_cmd[path_len-1] != '/' )
if( new_cmd[path_len-1] != L'/' )
{
new_cmd[path_len++]='/';
new_cmd[path_len++]=L'/';
}
wcscpy( &new_cmd[path_len], cmd );
if( waccess( new_cmd, X_OK )==0 )
@@ -768,7 +761,9 @@ wchar_t *get_filename( const wchar_t *cmd )
if( wstat( new_cmd, &buff )==-1 )
{
if( errno != EACCES )
{
wperror( L"stat" );
}
continue;
}
if( S_ISREG(buff.st_mode) )
@@ -787,10 +782,12 @@ wchar_t *get_filename( const wchar_t *cmd )
case ENOTDIR:
break;
default:
{
debug( 1,
MISSING_COMMAND_ERR_MSG,
new_cmd );
wperror( L"access" );
}
}
}
}
@@ -823,8 +820,10 @@ static void print_profile( array_list_t *p,
int my_time;
if( pos >= al_get_count( p ) )
{
return;
}
me= (profile_element_t *)al_get( p, pos );
if( !me->skipped )
{
@@ -834,12 +833,20 @@ static void print_profile( array_list_t *p,
{
prev = (profile_element_t *)al_get( p, i );
if( prev->skipped )
{
continue;
}
if( prev->level <= me->level )
{
break;
}
if( prev->level > me->level+1 )
{
continue;
}
my_time -= prev->parse;
my_time -= prev->exec;
}
@@ -926,9 +933,9 @@ int eval_args( const wchar_t *line, array_list_t *args )
tokenizer *previous_tokenizer=current_tokenizer;
int previous_pos=current_tokenizer_pos;
int do_loop=1;
int was_interactive = is_interactive;
is_interactive = 0;
proc_push_interactive(0);
current_tokenizer_pos = 0;
tok_init( &tok, line, 0 );
@@ -940,26 +947,27 @@ int eval_args( const wchar_t *line, array_list_t *args )
switch(tok_last_type( &tok ) )
{
case TOK_STRING:
switch( expand_string( wcsdup(tok_last( &tok )), args, 0 ) )
{
wchar_t *tmp = wcsdup(tok_last( &tok ));
if( !tmp )
{
case EXPAND_ERROR:
{
err_pos=tok_get_pos( &tok );
do_loop=0;
break;
}
default:
{
break;
}
die_mem();
}
if( expand_string( 0, tmp, args, 0 ) == EXPAND_ERROR )
{
err_pos=tok_get_pos( &tok );
do_loop=0;
}
break;
}
case TOK_END:
{
break;
}
case TOK_ERROR:
{
error( SYNTAX_ERROR,
@@ -972,6 +980,7 @@ int eval_args( const wchar_t *line, array_list_t *args )
}
default:
{
error( SYNTAX_ERROR,
tok_get_pos( &tok ),
UNEXPECTED_TOKEN_ERR_MSG,
@@ -979,16 +988,16 @@ int eval_args( const wchar_t *line, array_list_t *args )
do_loop=0;
break;
}
}
}
print_errors();
tok_destroy( &tok );
current_tokenizer=previous_tokenizer;
current_tokenizer_pos = previous_pos;
is_interactive = was_interactive;
proc_pop_interactive();
return 1;
}
@@ -1013,27 +1022,37 @@ void parser_stack_trace( block_t *b, string_buffer_t *buff)
switch( b->type)
{
case SOURCE:
{
sb_printf( buff, _(L"in . (source) call of file '%ls',\n"), b->param1.source_dest );
break;
}
case FUNCTION_CALL:
{
sb_printf( buff, _(L"in function '%ls',\n"), b->param1.function_name );
break;
}
case SUBST:
{
sb_printf( buff, _(L"in command substitution\n") );
break;
}
}
const wchar_t *file = b->src_filename;
if( file )
{
sb_printf( buff,
_(L"\tcalled on line %d of file '%ls',\n"),
b->src_lineno,
file );
}
else
{
sb_printf( buff,
_(L"\tcalled on standard input,\n") );
}
if( b->type == FUNCTION_CALL )
{
if( b->param2.function_call_process->argv[1] )
@@ -1169,7 +1188,7 @@ wchar_t *parser_current_line()
/*
Calculate line number, line offset, etc.
*/
for( i=0; i<current_tokenizer_pos; i++ )
for( i=0; i<current_tokenizer_pos && whole_str[i]; i++ )
{
if( whole_str[i] == L'\n' )
{
@@ -1179,6 +1198,9 @@ wchar_t *parser_current_line()
}
}
// lineno = current_tokenizer_pos;
current_line_width=printed_width(whole_str+current_line_start, current_tokenizer_pos-current_line_start );
if( (function_name = is_function()) )
@@ -1318,11 +1340,10 @@ static void parse_job_main_loop( process_t *p,
while( 1 )
{
/* debug( 2, L"Read token %ls\n", wcsdup(tok_last( tok )) ); */
switch( tok_last_type( tok ) )
{
case TOK_PIPE:
{
if( (p->type == INTERNAL_EXEC) )
{
error( SYNTAX_ERROR,
@@ -1331,29 +1352,33 @@ static void parse_job_main_loop( process_t *p,
return;
}
p->pipe_fd = wcstol( tok_last( tok ), 0, 10 );
p->argv = list_to_char_arr( j, args );
if( !p->argv )
halloc_register( j, p->argv = list_to_char_arr( args ) );
p->next = halloc( j, sizeof( process_t ) );
if( p->next == 0 )
{
die_mem();
}
tok_next( tok );
if( !parse_job( p->next, j, tok ))
{
/*
Don't do anything on failiure. parse_job will notice the error flag beeing set
*/
/*
Don't do anything on failiure. parse_job will notice the error flag beeing set
*/
parse_job( p->next, j, tok );
}
is_finished = 1;
break;
}
case TOK_BACKGROUND:
{
j->fg = 0;
}
case TOK_END:
{
p->argv = list_to_char_arr( j, args );
if( !p->argv )
halloc_register( j, p->argv = list_to_char_arr( args ) );
if( tok_has_next(tok))
tok_next(tok);
@@ -1399,7 +1424,7 @@ static void parse_job_main_loop( process_t *p,
}
switch( expand_string( wcsdup(tok_last( tok )), args, 0 ) )
switch( expand_string( j, wcsdup(tok_last( tok )), args, 0 ) )
{
case EXPAND_ERROR:
{
@@ -1420,7 +1445,7 @@ static void parse_job_main_loop( process_t *p,
unmatched_wildcard = 1;
if( !unmatched )
{
unmatched = halloc_register( j, wcsdup( tok_last( tok )));
unmatched = halloc_wcsdup( j, tok_last( tok ));
unmatched_pos = tok_get_pos( tok );
}
@@ -1487,7 +1512,7 @@ static void parse_job_main_loop( process_t *p,
{
case TOK_STRING:
{
target = (wchar_t *)halloc_register( j, expand_one( wcsdup( tok_last( tok ) ), 0));
target = (wchar_t *)expand_one( j, wcsdup( tok_last( tok ) ), 0);
if( target == 0 && error_code == 0 )
{
@@ -1634,35 +1659,35 @@ static int parse_job( process_t *p,
job_t *j,
tokenizer *tok )
{
array_list_t args; // The list that will become the argc array for the program
array_list_t *args = al_halloc( j ); // The list that will become the argc array for the program
int use_function = 1; // May functions be considered when checking what action this command represents
int use_builtin = 1; // May builtins be considered when checking what action this command represents
int is_new_block=0; // Does this command create a new block?
block_t *prev_block = current_block;
al_init( &args );
int prev_tokenizer_pos = current_tokenizer_pos;
current_tokenizer_pos = tok_get_pos( tok );
while( al_get_count( &args ) == 0 )
while( al_get_count( args ) == 0 )
{
wchar_t *nxt=0;
switch( tok_last_type( tok ))
{
case TOK_STRING:
{
nxt = expand_one( wcsdup(tok_last( tok )),
nxt = expand_one( j,
wcsdup(tok_last( tok )),
EXPAND_SKIP_SUBSHELL | EXPAND_SKIP_VARIABLES);
if( nxt == 0 )
{
error( SYNTAX_ERROR,
tok_get_pos( tok ),
ILLEGAL_CMD_ERR_MSG,
tok_last( tok ) );
al_destroy( &args );
current_tokenizer_pos = prev_tokenizer_pos;
return 0;
}
break;
@@ -1675,7 +1700,7 @@ static int parse_job( process_t *p,
TOK_ERR_MSG,
tok_last(tok) );
al_destroy( &args );
current_tokenizer_pos = prev_tokenizer_pos;
return 0;
}
@@ -1697,7 +1722,7 @@ static int parse_job( process_t *p,
tok_get_desc( tok_last_type(tok) ) );
}
al_destroy( &args );
current_tokenizer_pos = prev_tokenizer_pos;
return 0;
}
@@ -1708,13 +1733,16 @@ static int parse_job( process_t *p,
CMD_ERR_MSG,
tok_get_desc( tok_last_type(tok) ) );
al_destroy( &args );
current_tokenizer_pos = prev_tokenizer_pos;
return 0;
}
}
int mark = tok_get_pos( tok );
int consumed = 0;
if( wcscmp( L"command", nxt )==0 )
{
tok_next( tok );
@@ -1726,8 +1754,7 @@ static int parse_job( process_t *p,
{
use_function = 0;
use_builtin=0;
free( nxt );
continue;
consumed=1;
}
}
else if( wcscmp( L"builtin", nxt )==0 )
@@ -1740,8 +1767,7 @@ static int parse_job( process_t *p,
else
{
use_function = 0;
free( nxt );
continue;
consumed=1;
}
}
else if( wcscmp( L"not", nxt )==0 )
@@ -1754,8 +1780,7 @@ static int parse_job( process_t *p,
else
{
j->negate=1-j->negate;
free( nxt );
continue;
consumed=1;
}
}
else if( wcscmp( L"and", nxt )==0 )
@@ -1768,8 +1793,7 @@ static int parse_job( process_t *p,
else
{
j->skip = proc_get_last_status();
free( nxt );
continue;
consumed=1;
}
}
else if( wcscmp( L"or", nxt )==0 )
@@ -1782,8 +1806,7 @@ static int parse_job( process_t *p,
else
{
j->skip = !proc_get_last_status();
free( nxt );
continue;
consumed=1;
}
}
else if( wcscmp( L"exec", nxt )==0 )
@@ -1793,8 +1816,7 @@ static int parse_job( process_t *p,
error( SYNTAX_ERROR,
tok_get_pos( tok ),
EXEC_ERR_MSG );
al_destroy( &args );
free(nxt);
current_tokenizer_pos = prev_tokenizer_pos;
return 0;
}
@@ -1808,8 +1830,8 @@ static int parse_job( process_t *p,
use_function = 0;
use_builtin=0;
p->type=INTERNAL_EXEC;
free( nxt );
continue;
consumed=1;
current_tokenizer_pos = prev_tokenizer_pos;
}
}
else if( wcscmp( L"while", nxt ) ==0 )
@@ -1837,10 +1859,8 @@ static int parse_job( process_t *p,
current_block->tok_pos = mark;
}
free( nxt );
consumed=1;
is_new_block=1;
continue;
}
else if( wcscmp( L"if", nxt ) ==0 )
{
@@ -1851,12 +1871,16 @@ static int parse_job( process_t *p,
current_block->param1.if_state=0;
current_block->tok_pos = mark;
free( nxt );
is_new_block=1;
consumed=1;
}
if( consumed )
{
continue;
}
if( use_function)
if( use_function && !current_block->skip )
{
int nxt_forbidden;
wchar_t *forbid;
@@ -1885,7 +1909,7 @@ static int parse_job( process_t *p,
}
}
}
al_push( &args, nxt );
al_push( args, nxt );
}
if( error_code == 0 )
@@ -1893,10 +1917,10 @@ static int parse_job( process_t *p,
if( !p->type )
{
if( use_builtin &&
builtin_exists( (wchar_t *)al_get( &args, 0 ) ) )
builtin_exists( (wchar_t *)al_get( args, 0 ) ) )
{
p->type = INTERNAL_BUILTIN;
is_new_block = parser_is_block( (wchar_t *)al_get( &args, 0 ) );
is_new_block = parser_is_block( (wchar_t *)al_get( args, 0 ) );
}
}
@@ -1912,7 +1936,7 @@ static int parse_job( process_t *p,
}
else
{
p->actual_cmd = halloc_register(j, get_filename( (wchar_t *)al_get( &args, 0 ) ));
p->actual_cmd = halloc_register(j, get_filename( (wchar_t *)al_get( args, 0 ) ));
/*
Check if the specified command exists
@@ -1926,16 +1950,16 @@ static int parse_job( process_t *p,
implicit command.
*/
wchar_t *pp =
parser_cdpath_get( (wchar_t *)al_get( &args, 0 ) );
parser_cdpath_get( (wchar_t *)al_get( args, 0 ) );
if( pp )
{
wchar_t *tmp;
free( pp );
tmp = (wchar_t *)al_get( &args, 0 );
al_truncate( &args, 0 );
al_push( &args, wcsdup( L"cd" ) );
al_push( &args, tmp );
tmp = (wchar_t *)al_get( args, 0 );
al_truncate( args, 0 );
al_push( args, wcsdup( L"cd" ) );
al_push( args, tmp );
/*
If we have defined a wrapper around cd, use it,
otherwise use the cd builtin
@@ -1947,31 +1971,54 @@ static int parse_job( process_t *p,
}
else
{
if( wcschr( (wchar_t *)al_get( &args, 0 ), L'=' ) )
{
error( EVAL_ERROR,
tok_get_pos( tok ),
COMMAND_ASSIGN_ERR_MSG,
(wchar_t *)al_get( &args, 0 ) );
int tmp;
/*
We couln't find the specified command.
What we want to happen now is that the
specified job won't get executed, and an
error message is printed on-screen, but
otherwise, the parsing/execution of the
file continues. Because of this, we don't
want to call error(), since that would stop
execution of the file. Instead we let
p->actual_command be 0 (null), which will
cause the job to silently not execute. We
also print an error message.
*/
if( wcschr( (wchar_t *)al_get( args, 0 ), L'=' ) )
{
debug( 0,
COMMAND_ASSIGN_ERR_MSG,
(wchar_t *)al_get( args, 0 ) );
}
else
{
error( EVAL_ERROR,
tok_get_pos( tok ),
debug( 0,
_(L"Unknown command '%ls'"),
(wchar_t *)al_get( &args, 0 ) );
(wchar_t *)al_get( args, 0 ) );
}
tmp = current_tokenizer_pos;
current_tokenizer_pos = tok_get_pos(tok);
fwprintf( stderr, L"%ls", parser_current_line() );
current_tokenizer_pos=tmp;
j->skip=1;
}
}
}
}
}
if( is_new_block )
{
const wchar_t *end=parser_find_end( tok_string( tok ) +
current_tokenizer_pos );
tokenizer subtok;
@@ -1982,6 +2029,7 @@ static int parse_job( process_t *p,
error( SYNTAX_ERROR,
tok_get_pos( tok ),
BLOCK_END_ERR_MSG );
}
if( !make_sub_block )
@@ -2020,8 +2068,7 @@ static int parse_job( process_t *p,
end_pos - current_tokenizer_pos);
p->type = INTERNAL_BLOCK;
free( (void *)al_get( &args, 0 ) );
al_set( &args, 0, sub_block );
al_set( args, 0, sub_block );
tok_set_pos( tok,
end_pos );
@@ -2039,27 +2086,19 @@ static int parse_job( process_t *p,
if( !error_code )
{
if( p->type == INTERNAL_BUILTIN && parser_skip_arguments( (wchar_t *)al_get(&args, 0) ) )
{
p->argv = list_to_char_arr( j, &args );
// tok_next(tok);
if( p->type == INTERNAL_BUILTIN && parser_skip_arguments( (wchar_t *)al_get(args, 0) ) )
{
if( !p->argv )
halloc_register( j, p->argv = list_to_char_arr( args ) );
}
else
{
parse_job_main_loop( p, j, tok, &args );
parse_job_main_loop( p, j, tok, args );
}
}
if( error_code )
{
/*
We don't know what the state of the args array and the argv
vector is on error, so we do an internal cleanup here.
*/
al_foreach( &args,
(void (*)(const void *))&free );
free(p->argv);
p->argv=0;
/*
Make sure the block stack is consistent
*/
@@ -2067,10 +2106,8 @@ static int parse_job( process_t *p,
{
parser_pop_block();
}
}
al_destroy( &args );
current_tokenizer_pos = prev_tokenizer_pos;
return !error_code;
}
@@ -2143,7 +2180,8 @@ static void eval_job( tokenizer *tok )
long long t1=0, t2=0, t3=0;
profile_element_t *p=0;
int skip = 0;
int job_begin_pos, prev_tokenizer_pos;
if( profile )
{
p=malloc( sizeof(profile_element_t));
@@ -2177,6 +2215,8 @@ static void eval_job( tokenizer *tok )
j->first_process = halloc( j, sizeof( process_t ) );
job_begin_pos = tok_get_pos( tok );
if( parse_job( j->first_process, j, tok ) &&
j->first_process->argv )
{
@@ -2188,8 +2228,9 @@ static void eval_job( tokenizer *tok )
if( newline )
stop_pos = mini( stop_pos, newline - tok_string(tok) );
j->command = halloc_register( j, wcsndup( tok_string(tok)+start_pos,
stop_pos-start_pos ));
j->command = halloc_wcsndup( j,
tok_string(tok)+start_pos,
stop_pos-start_pos );
}
else
j->command = L"";
@@ -2210,9 +2251,11 @@ static void eval_job( tokenizer *tok )
int was_builtin = 0;
// if( j->first_process->type==INTERNAL_BUILTIN && !j->first_process->next)
// was_builtin = 1;
prev_tokenizer_pos = current_tokenizer_pos;
current_tokenizer_pos = job_begin_pos;
exec( j );
current_tokenizer_pos = prev_tokenizer_pos;
/* Only external commands require a new fishd barrier */
if( !was_builtin )
proc_had_barrier=0;
@@ -2334,7 +2377,7 @@ int eval( const wchar_t *cmd, io_data_t *io, int block_type )
{
forbidden_function = al_new();
}
forbid_count = al_get_count( forbidden_function );
block_io = io;
@@ -2573,7 +2616,7 @@ int parser_test( wchar_t * buff,
}
/*
The short circut commands requires _two_ additional commands.
The short circuit commands requires _two_ additional commands.
*/
if( contains_str( tok_last( &tok ),
L"or",

View File

@@ -257,7 +257,7 @@ int parser_is_subcommand( const wchar_t *cmd );
\param word The command name to test
\return 1 of the command parameter is a command, 0 otherwise
*/
int parser_is_reserved( wchar_t *word );
int parser_is_reserved( const wchar_t *word );
/**
Returns a string describing the current parser pisition in the format 'FILENAME (line LINE_NUMBER): LINE'.

8665
po/de.po Normal file

File diff suppressed because it is too large Load Diff

6260
po/sv.po

File diff suppressed because it is too large Load Diff

24
proc.c
View File

@@ -54,6 +54,8 @@ Some of the code in this file is based on code from the Glibc manual.
#include "event.h"
#include "translate.h"
#include "halloc.h"
#include "halloc_util.h"
#include "output.h"
/**
Size of message buffer
@@ -76,7 +78,7 @@ static int last_status=0;
static sig_atomic_t got_signal=0;
job_t *first_job=0;
int is_interactive=0;
int is_interactive=-1;
int is_interactive_session=0;
int is_subshell=0;
int is_block=0;
@@ -101,14 +103,18 @@ static string_buffer_t event_pid;
*/
static string_buffer_t event_status;
static array_list_t *interactive_stack;
void proc_init()
{
interactive_stack = al_halloc( global_context );
proc_push_interactive( 0 );
al_init( &event.arguments );
sb_init( &event_pid );
sb_init( &event_status );
}
/**
Remove job from list of jobs
*/
@@ -1076,3 +1082,19 @@ void proc_sanity_check()
}
}
void proc_push_interactive( int value )
{
int old = is_interactive;
al_push( interactive_stack, (void *)(long)is_interactive );
is_interactive = value;
if( old != value )
signal_set_handlers();
}
void proc_pop_interactive()
{
int old = is_interactive;
is_interactive= (int)(long)al_pop(interactive_stack);
if( is_interactive != old )
signal_set_handlers();
}

13
proc.h
View File

@@ -298,7 +298,6 @@ int job_reap( int interactive );
*/
void job_handle_signal( int signal, siginfo_t *info, void *con );
#ifdef HAVE__PROC_SELF_STAT
/**
Use the procfs filesystem to look up how many jiffies of cpu time
@@ -337,4 +336,16 @@ void proc_init();
*/
void proc_destroy();
/**
Set new value for is_interactive flag, saving previous value. If
needed, update signal handlers.
*/
void proc_push_interactive( int value );
/**
Set is_interactive flag to the previous value. If needed, update
signal handlers.
*/
void proc_pop_interactive();
#endif

View File

@@ -567,11 +567,12 @@ static void remove_duplicates( array_list_t *l )
prev = (wchar_t *)al_get( l, 0 );
for( in=1, out=1; in < al_get_count( l ); in++ )
{
{
wchar_t *curr = (wchar_t *)al_get( l, in );
if( fldcmp( prev, curr )==0 )
{
free( curr );
free( curr );
}
else
{
@@ -606,7 +607,6 @@ void reader_write_title()
wchar_t *title;
array_list_t l;
wchar_t *term = env_get( L"TERM" );
int was_interactive = is_interactive;
/*
This is a pretty lame heuristic for detecting terminals that do
@@ -628,7 +628,7 @@ void reader_write_title()
al_init( &l );
is_interactive = 0;
proc_push_interactive(0);
if( exec_subshell( title, &l ) != -1 )
{
int i;
@@ -639,8 +639,8 @@ void reader_write_title()
}
writestr( L"\7" );
}
is_interactive = was_interactive;
proc_pop_interactive();
al_foreach( &l, (void (*)(const void *))&free );
al_destroy( &l );
set_color( FISH_COLOR_RESET, FISH_COLOR_RESET );
@@ -790,8 +790,8 @@ static void write_prompt()
if( data->prompt )
{
int was_interactive = is_interactive;
is_interactive = 0;
proc_push_interactive( 0 );
if( exec_subshell( data->prompt, &prompt_list ) == -1 )
{
/* If executing the prompt fails, make sure we at least don't print any junk */
@@ -799,7 +799,7 @@ static void write_prompt()
al_destroy( &prompt_list );
al_init( &prompt_list );
}
is_interactive = was_interactive;
proc_pop_interactive();
}
data->prompt_width=calc_prompt_width( &prompt_list );
@@ -835,25 +835,6 @@ static void write_cmdline()
}
}
/**
perm_left_cursor and parm_right_cursor don't seem to be defined as
often as cursor_left and cursor_right, so we use this workalike.
*/
static void move_cursor( int steps )
{
int i;
if( steps < 0 ){
for( i=0; i>steps; i--)
{
writembs(cursor_left);
}
}
else
for( i=0; i<steps; i++)
writembs(cursor_right);
}
void reader_init()
{
@@ -875,10 +856,9 @@ void reader_destroy()
void reader_exit( int do_exit )
{
if( is_interactive )
if( data )
data->end_loop=do_exit;
else
end_loop=do_exit;
end_loop=do_exit;
}
void repaint()
@@ -1221,7 +1201,7 @@ static wchar_t get_quote( wchar_t *cmd, int l )
if( cmd[i] == L'\'' || cmd[i] == L'\"' )
{
wchar_t *end = quote_end( &cmd[i] );
const wchar_t *end = quote_end( &cmd[i] );
//fwprintf( stderr, L"Jump %d\n", end-cmd );
if(( end == 0 ) || (!*end) || (end-cmd > l))
{
@@ -1418,6 +1398,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
sb_init( &cmd );
sb_printf( &cmd,
L"fish_pager %d %ls",
// L"valgrind --track-fds=yes --log-file=pager.txt --leak-check=full ./fish_pager %d %ls",
is_quoted,
prefix_esc );
@@ -1463,7 +1444,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
/**
Handle the list of completions. This means the following:
- If the list is empty, flash the terminal.
- If the list contains one element, write the whole element, and if
the element does not end on a '/', '@', ':', or a '=', also write a trailing
@@ -1472,7 +1453,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
the prefix.
- If the list contains multiple elements without
a common prefix, call run_pager to display a list of completions
\param comp the list of completion strings
*/
@@ -1480,7 +1461,7 @@ static void run_pager( wchar_t *prefix, int is_quoted, array_list_t *comp )
static int handle_completions( array_list_t *comp )
{
int i;
if( al_get_count( comp ) == 0 )
{
if( flash_screen != 0 )
@@ -2056,7 +2037,6 @@ void reader_set_buffer( wchar_t *b, int p )
else
{
data->buff_pos=l;
// fwprintf( stderr, L"Pos %d\n", l );
}
reader_super_highlight_me_plenty( data->buff,
@@ -2307,7 +2287,6 @@ static int read_i()
{
prev_end_loop=0;
}
error_reset();
}
reader_pop();
@@ -2793,8 +2772,8 @@ wchar_t *reader_readline()
case R_CLEAR_SCREEN:
{
writembs( clear_screen );
if( clear_screen )
writembs( clear_screen );
repaint();
break;
}
@@ -2955,7 +2934,6 @@ static int read_ni( int fd )
free( buff );
res=1;
}
error_reset();
return res;
}
@@ -2967,20 +2945,19 @@ int reader_read( int fd )
we need to preserve is_interactive, so we save the
original state. We also update the signal handlers.
*/
int shell_was_interactive = is_interactive;
is_interactive = ((fd == 0) && isatty(STDIN_FILENO));
signal_set_handlers();
proc_push_interactive( ((fd == 0) && isatty(STDIN_FILENO)));
res= is_interactive?read_i():read_ni( fd );
/*
If the exit command was called in a script, only exit the
script, not the program
*/
if( data )
data->end_loop = 0;
end_loop = 0;
is_interactive = shell_was_interactive;
signal_set_handlers();
proc_pop_interactive();
return res;
}

2
seq.in
View File

@@ -1,4 +1,4 @@
#!@prefix@/bin/fish
#!/usr/bin/env fish
#
# Fallback implementation of the seq command
#

View File

@@ -12,7 +12,7 @@ complete -c apropos -s h -l help -d (_ "Display help and exit")
complete -f -c apropos -s d -l debug -d (_ "Print debugging info")
complete -f -c apropos -s v -l verbose -d (_ "Verbose mode")
complete -f -c apropos -s r -l regex -d (_ "Keyword as regex")
complete -f -c apropos -s w -l wildcard -d (_ "Keyword as wildwards")
complete -f -c apropos -s w -l wildcard -d (_ "Keyword as wildcards")
complete -f -c apropos -s e -l exact -d (_ "Keyword as exactly match")
complete -x -c apropos -s m -l system -d (_ "Search for other system")
complete -x -c apropos -s M -l manpath -a '(echo $MANPATH)' -d (_ "Specify man path")

View File

@@ -0,0 +1 @@
__fish_complete_bittorrent btdownloadcurses.py

View File

@@ -0,0 +1 @@
__fish_complete_bittorrent btdownloadheadless.py

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