mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-23 13:11:15 -03:00
Compare commits
411 Commits
1.22.3
...
pre_fishfi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71bff26607 | ||
|
|
23bc10dfe6 | ||
|
|
8ae00697c9 | ||
|
|
b0c6d891e9 | ||
|
|
548164cd5e | ||
|
|
f12fd3707e | ||
|
|
8b407a32ff | ||
|
|
344b9bdba3 | ||
|
|
834ea94eb9 | ||
|
|
a060cc5893 | ||
|
|
7ef0b3b821 | ||
|
|
39a2fd1717 | ||
|
|
c66ec4df3d | ||
|
|
c25c48f763 | ||
|
|
5105d8d87e | ||
|
|
35af336ff6 | ||
|
|
157ca12d4b | ||
|
|
e9d1a54983 | ||
|
|
c8981c048f | ||
|
|
1ae44c6b3c | ||
|
|
b2887477e3 | ||
|
|
8e2db29c9a | ||
|
|
d38de7365a | ||
|
|
cde6067cae | ||
|
|
2583638f4b | ||
|
|
11360b018f | ||
|
|
bdfc62184d | ||
|
|
74f06d550a | ||
|
|
46986ad4c2 | ||
|
|
6a5d6471c5 | ||
|
|
cf0850edfd | ||
|
|
fd4ac87382 | ||
|
|
164144f126 | ||
|
|
f2ad4a2e8e | ||
|
|
df23913bb8 | ||
|
|
4ccf26fbcc | ||
|
|
081e277fe4 | ||
|
|
dcecab384a | ||
|
|
4f9b07e979 | ||
|
|
9b97c55546 | ||
|
|
364d3dbbf8 | ||
|
|
9f3a4d1640 | ||
|
|
5fca92994f | ||
|
|
fefd17fe5e | ||
|
|
6b243fbcd3 | ||
|
|
82f8c3834e | ||
|
|
e0ba91db31 | ||
|
|
fa148bf59f | ||
|
|
1b0ce33669 | ||
|
|
0cf2a1eb33 | ||
|
|
8a46a8ecb2 | ||
|
|
4f0221bc4f | ||
|
|
ce08bb2ad2 | ||
|
|
93f797326e | ||
|
|
ceba377ab8 | ||
|
|
b9b6e867df | ||
|
|
f47caefdb9 | ||
|
|
41ae7bccc2 | ||
|
|
1e27024d75 | ||
|
|
6654fff377 | ||
|
|
89d999df72 | ||
|
|
a941d82be3 | ||
|
|
694cdf5ae1 | ||
|
|
2bfe4afea2 | ||
|
|
d559c3fe2e | ||
|
|
27df727ca1 | ||
|
|
8910226d2f | ||
|
|
04f58b1a31 | ||
|
|
1b9dd0c75f | ||
|
|
a7af415b6a | ||
|
|
f8a5a59513 | ||
|
|
ac3dfb3f96 | ||
|
|
d957d23d8f | ||
|
|
d049947801 | ||
|
|
21a10c3c74 | ||
|
|
04951f8b34 | ||
|
|
c08bae6aeb | ||
|
|
3aa107c4ae | ||
|
|
e196091714 | ||
|
|
d35d65cc40 | ||
|
|
7f7b30959b | ||
|
|
70322077d2 | ||
|
|
f529b2e057 | ||
|
|
c6372a1b3f | ||
|
|
41b8db063c | ||
|
|
1b16758d7e | ||
|
|
51b5adc306 | ||
|
|
56f8993b8c | ||
|
|
8c4d1ca587 | ||
|
|
ec8b3593f3 | ||
|
|
5c9b42e260 | ||
|
|
7914c92824 | ||
|
|
208be0f4d4 | ||
|
|
7cfac5bb59 | ||
|
|
1bd09bfd40 | ||
|
|
517751f2a3 | ||
|
|
006952c571 | ||
|
|
7a8b7201a1 | ||
|
|
1157e4d7b2 | ||
|
|
6b8e7b16f6 | ||
|
|
1eb089d722 | ||
|
|
e50d0c18b0 | ||
|
|
810d5f9548 | ||
|
|
e0c317dfd4 | ||
|
|
d5320fb9f9 | ||
|
|
14c84ffbcb | ||
|
|
f71c6f3f0e | ||
|
|
6dbb9e070d | ||
|
|
47ae2a05ce | ||
|
|
810262118a | ||
|
|
f5be301a2f | ||
|
|
b1357d11b2 | ||
|
|
5fc42fcaff | ||
|
|
c1cf6a4071 | ||
|
|
972f3e121e | ||
|
|
0dd8ae4843 | ||
|
|
8a93b6f26d | ||
|
|
07717a3570 | ||
|
|
79784d3e18 | ||
|
|
c08c313c0a | ||
|
|
dfd70057b3 | ||
|
|
07dec5c3ed | ||
|
|
1ed5decf2c | ||
|
|
9b95dda6bf | ||
|
|
41015691db | ||
|
|
7e1ac2d806 | ||
|
|
35258bf1fb | ||
|
|
72025a6a38 | ||
|
|
05341b055b | ||
|
|
9d7224d756 | ||
|
|
33ec8b45a0 | ||
|
|
1dc49a4062 | ||
|
|
1123467991 | ||
|
|
4f54da3795 | ||
|
|
c8de3d24c8 | ||
|
|
31439ffb52 | ||
|
|
9111b85437 | ||
|
|
c6427c5a47 | ||
|
|
36c3bd4e8d | ||
|
|
dad549afd1 | ||
|
|
e73c2be216 | ||
|
|
b0d324f1a7 | ||
|
|
d7396ac59f | ||
|
|
3f439e9cd3 | ||
|
|
0b722864c0 | ||
|
|
75e26f0f94 | ||
|
|
8cacb33347 | ||
|
|
bf7d62fd91 | ||
|
|
4ac31e637d | ||
|
|
0ad64ad2e4 | ||
|
|
523096e5d8 | ||
|
|
0de629e009 | ||
|
|
1f6fa1208e | ||
|
|
b86856b454 | ||
|
|
6598320534 | ||
|
|
0a66dc4a31 | ||
|
|
88a2b622df | ||
|
|
e10f75483f | ||
|
|
1a66fc4c5d | ||
|
|
905b792de7 | ||
|
|
804f5ab334 | ||
|
|
f974c7c416 | ||
|
|
f3b6b74568 | ||
|
|
ab94a397c3 | ||
|
|
537ab32dd9 | ||
|
|
a2660cfb76 | ||
|
|
3743a5758b | ||
|
|
e510d10c77 | ||
|
|
f5540ff958 | ||
|
|
c2b28063e1 | ||
|
|
8d2564291d | ||
|
|
87db9517e9 | ||
|
|
ab3502fc8b | ||
|
|
22472ea980 | ||
|
|
ef705be6a5 | ||
|
|
d50fac7fe5 | ||
|
|
39c16a7770 | ||
|
|
2aad9d5a95 | ||
|
|
52aaf60510 | ||
|
|
3a2f7d0edf | ||
|
|
605fffa9d2 | ||
|
|
2229fad410 | ||
|
|
8e9384e2e8 | ||
|
|
394776c56b | ||
|
|
e3d3a1062d | ||
|
|
b4042b18c6 | ||
|
|
5379200b9e | ||
|
|
9c38ed8238 | ||
|
|
cb59da7a6f | ||
|
|
bdec900aca | ||
|
|
564d19e3bd | ||
|
|
063c4d7e67 | ||
|
|
30cfa2a445 | ||
|
|
71c2cde390 | ||
|
|
da4a4bcc18 | ||
|
|
286ce1d6a4 | ||
|
|
5064cec16d | ||
|
|
f5f5e63ddf | ||
|
|
ae878ed6ea | ||
|
|
2c5151bb78 | ||
|
|
f506f1f495 | ||
|
|
374fc09af0 | ||
|
|
54b1986986 | ||
|
|
6e9489f4f5 | ||
|
|
a52bd219b9 | ||
|
|
bdd1b6b4b2 | ||
|
|
6dfdb3ba6e | ||
|
|
48d5637178 | ||
|
|
d724b160ea | ||
|
|
7a4dc6f700 | ||
|
|
c9f43fb02d | ||
|
|
da02905250 | ||
|
|
80060229f8 | ||
|
|
10b9b06ef7 | ||
|
|
e9aba6a878 | ||
|
|
5fee5a2890 | ||
|
|
3f3fe634c8 | ||
|
|
a5156c54cb | ||
|
|
74cd64ba21 | ||
|
|
348e991d7c | ||
|
|
a1af86cb6b | ||
|
|
baa6a40d6f | ||
|
|
5082054bcb | ||
|
|
2160777d2f | ||
|
|
a97faaf664 | ||
|
|
0c1b40e3b3 | ||
|
|
e54ce9a147 | ||
|
|
36e08dc49e | ||
|
|
dd02e96712 | ||
|
|
4163040e56 | ||
|
|
0bea4c46e3 | ||
|
|
0f6fe652a4 | ||
|
|
afa0ed124f | ||
|
|
8904ab47aa | ||
|
|
25305c6b24 | ||
|
|
89c27c6d9d | ||
|
|
175dd75a3d | ||
|
|
9b74687384 | ||
|
|
fcd474afe8 | ||
|
|
3ca3b6209d | ||
|
|
9299515f3e | ||
|
|
188f0454b7 | ||
|
|
e55739296d | ||
|
|
68857220ac | ||
|
|
713c84d821 | ||
|
|
d34d05ca8b | ||
|
|
dac2129048 | ||
|
|
8cd8c3002e | ||
|
|
4b85eb32d7 | ||
|
|
5870ee7723 | ||
|
|
feec9579c2 | ||
|
|
dde3838f2d | ||
|
|
97b77d1b3a | ||
|
|
addb5a698d | ||
|
|
db0a982570 | ||
|
|
3a73b60956 | ||
|
|
f4f10a8226 | ||
|
|
d6c7e25bea | ||
|
|
f28e83d3e9 | ||
|
|
0e716763d8 | ||
|
|
50f5941a82 | ||
|
|
093cb71f91 | ||
|
|
df4fdf33c4 | ||
|
|
5694d3f027 | ||
|
|
cf8e746d0c | ||
|
|
af9c2067e1 | ||
|
|
d44dd73682 | ||
|
|
5938a93018 | ||
|
|
79ac330afb | ||
|
|
e6764f3130 | ||
|
|
710a01c945 | ||
|
|
0b7b20f013 | ||
|
|
819c20e1d8 | ||
|
|
61ebc12dd4 | ||
|
|
449a75756d | ||
|
|
5e2e9e2b9b | ||
|
|
737935ebe4 | ||
|
|
0679a6351f | ||
|
|
657e3f8147 | ||
|
|
e6b9955fc1 | ||
|
|
e1afe17671 | ||
|
|
16e2c4805a | ||
|
|
5ecd0e22bf | ||
|
|
1420744669 | ||
|
|
048f903a9d | ||
|
|
dab7e6c7b9 | ||
|
|
06de2602cb | ||
|
|
65d223e672 | ||
|
|
c0aac8996d | ||
|
|
3692074e7e | ||
|
|
954c99a5ad | ||
|
|
8c4770a26c | ||
|
|
624878d35f | ||
|
|
2375578310 | ||
|
|
084c0c5f80 | ||
|
|
d2d397d9eb | ||
|
|
607e970659 | ||
|
|
3b39b1fa03 | ||
|
|
64933d31a6 | ||
|
|
c780f1a8c9 | ||
|
|
76bb8e79b2 | ||
|
|
370aeec44d | ||
|
|
b0ae3dc9cc | ||
|
|
a900d16540 | ||
|
|
3fc1ba0f0e | ||
|
|
38ed4c0f9b | ||
|
|
5a61ae3e0d | ||
|
|
c9fe154c01 | ||
|
|
2a3b01a7a0 | ||
|
|
c2c4b24174 | ||
|
|
74a270ea32 | ||
|
|
2994378e1a | ||
|
|
baeca81305 | ||
|
|
151943f89e | ||
|
|
ad02bb9b48 | ||
|
|
e464b4270c | ||
|
|
e076f2c239 | ||
|
|
3cb24e0681 | ||
|
|
27baa6e62b | ||
|
|
fa9d00a81a | ||
|
|
04948702e0 | ||
|
|
20526687b2 | ||
|
|
0a0870180d | ||
|
|
972edef341 | ||
|
|
8ed521c817 | ||
|
|
88199d6b51 | ||
|
|
782a739736 | ||
|
|
cd19320ab2 | ||
|
|
58fd6b895a | ||
|
|
df55e89bbb | ||
|
|
91de143003 | ||
|
|
748d726ddf | ||
|
|
2caaa7526d | ||
|
|
778aa1c304 | ||
|
|
c40eb8a716 | ||
|
|
1c6236831c | ||
|
|
c1b4fa847f | ||
|
|
a6644631d9 | ||
|
|
e4f5bc69e2 | ||
|
|
03f322c715 | ||
|
|
a72d877752 | ||
|
|
d0585befb3 | ||
|
|
784c5d9fa3 | ||
|
|
52e7a7ec1c | ||
|
|
c00e1fcf26 | ||
|
|
5425970706 | ||
|
|
419b3166c8 | ||
|
|
e2714b05eb | ||
|
|
2c02b59703 | ||
|
|
ee94424b0f | ||
|
|
2b7535bb51 | ||
|
|
c5805cfd47 | ||
|
|
7ca76ef743 | ||
|
|
2c743173d3 | ||
|
|
003dfb99da | ||
|
|
dd48de068d | ||
|
|
cb179c448b | ||
|
|
c323fc226f | ||
|
|
176c1a487b | ||
|
|
2872df66d7 | ||
|
|
45412f2b1f | ||
|
|
e9790db64a | ||
|
|
8ab1d0254c | ||
|
|
4c858a10c9 | ||
|
|
b4ccce2dc3 | ||
|
|
06688fb9ea | ||
|
|
4d5c50cbb3 | ||
|
|
91d1dee06b | ||
|
|
3e030bc6c6 | ||
|
|
b9009eba96 | ||
|
|
90c5cea43d | ||
|
|
52f9560b4f | ||
|
|
91ca8610ee | ||
|
|
2efb88a30a | ||
|
|
87223c68f4 | ||
|
|
5c9570eb56 | ||
|
|
778b6a31ad | ||
|
|
4d6751c274 | ||
|
|
a03a4d1ba3 | ||
|
|
5a670e2a96 | ||
|
|
edf896f7cd | ||
|
|
e128fa1a8e | ||
|
|
e8ba091161 | ||
|
|
65d99117aa | ||
|
|
94a483d46b | ||
|
|
e750f1a3c2 | ||
|
|
3f4b47b4af | ||
|
|
f6b3fcb4f5 | ||
|
|
8fe90e4327 | ||
|
|
a17019e439 | ||
|
|
b5baac8291 | ||
|
|
f36508837b | ||
|
|
3969c1b453 | ||
|
|
1e524fbc7a | ||
|
|
3e1b0e587e | ||
|
|
2aea1d5a84 | ||
|
|
6616543991 | ||
|
|
83a3706099 | ||
|
|
7c96cb2ff8 | ||
|
|
a3c5718eb9 | ||
|
|
9b10fa4762 | ||
|
|
0f51d5ec18 | ||
|
|
73a67c2a43 | ||
|
|
6859e012d9 | ||
|
|
680cf17570 | ||
|
|
854c4aee9a | ||
|
|
104ec963c2 | ||
|
|
08eb92707a | ||
|
|
e50f43416b | ||
|
|
58755fc579 | ||
|
|
31ca1218d4 |
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
*.o
|
||||
*~
|
||||
|
||||
Doxyfile.help
|
||||
Makefile
|
||||
autom4te.cache/
|
||||
command_list.txt
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
configure
|
||||
doc.h
|
||||
doc_src/commands.hdr
|
||||
doc_src/index.hdr
|
||||
etc/config.fish
|
||||
po/*.gmo
|
||||
fish
|
||||
fish.spec
|
||||
fish_indent
|
||||
fish_pager
|
||||
fish_tests
|
||||
fishd
|
||||
mimedb
|
||||
seq
|
||||
set_color
|
||||
share/config.fish
|
||||
share/man/
|
||||
toc.txt
|
||||
user_doc/
|
||||
xsel-1.2.0/
|
||||
tests/*tmp.*
|
||||
tests/foo.txt
|
||||
3
CHANGELOG
Normal file
3
CHANGELOG
Normal file
@@ -0,0 +1,3 @@
|
||||
24-01-2012 Jan Kanis
|
||||
* Added a changelog file
|
||||
* removed unescaping if the 'commandline' builtin is called without the -o (tokenise) flag
|
||||
936
Doxyfile.help.in
936
Doxyfile.help.in
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,8 @@ ABBREVIATE_BRIEF = YES
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = YES
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
@@ -19,7 +19,7 @@ DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
TAB_SIZE = 8
|
||||
ALIASES =
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
SUBGROUPING = YES
|
||||
@@ -44,7 +44,7 @@ GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_DIRECTORIES = YES
|
||||
@@ -53,19 +53,19 @@ WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
INPUT =
|
||||
WARN_LOGFILE =
|
||||
INPUT =
|
||||
FILE_PATTERNS = doc.h
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXCLUDE_PATTERNS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
@@ -75,17 +75,17 @@ REFERENCES_RELATION = YES
|
||||
VERBATIM_HEADERS = YES
|
||||
ALPHABETICAL_INDEX = NO
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
IGNORE_PREFIX =
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER = user_doc.head.html
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
@@ -99,8 +99,8 @@ LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
@@ -109,33 +109,33 @@ GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
@@ -151,8 +151,8 @@ INCLUDED_BY_GRAPH = YES
|
||||
CALL_GRAPH = YES
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
MAX_DOT_GRAPH_WIDTH = 750
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
|
||||
2
INSTALL
2
INSTALL
@@ -49,7 +49,7 @@ Then, use following commands to compile fish:
|
||||
Finally, if you wish to use fish as your default shell, use the
|
||||
following command:
|
||||
|
||||
% chsh -s /usr/local/bin/fish
|
||||
% chsh -s /usr/local/bin/fish
|
||||
|
||||
chsh will prompt you for your password, and change your default shell.
|
||||
|
||||
|
||||
289
Makefile.in
289
Makefile.in
@@ -31,6 +31,8 @@
|
||||
# hallucinations.
|
||||
#
|
||||
|
||||
# Used by docdir
|
||||
PACKAGE_TARNAME = @PACKAGE_TARNAME@
|
||||
|
||||
#
|
||||
# Programs
|
||||
@@ -46,6 +48,7 @@ INSTALL:=@INSTALL@
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
datarootdir = @datarootdir@
|
||||
datadir = @datadir@
|
||||
bindir = @bindir@
|
||||
mandir = @mandir@
|
||||
@@ -55,16 +58,20 @@ localedir = @localedir@
|
||||
prefix = @prefix@
|
||||
optbindirs = @optbindirs@
|
||||
|
||||
|
||||
#
|
||||
# Various flags
|
||||
#
|
||||
|
||||
MACROS=-DLOCALEDIR=\"$(localedir)\" -DPREFIX=L\"$(prefix)\" -DDATADIR=L\"$(datadir)\" -DSYSCONFDIR=L\"$(sysconfdir)\"
|
||||
CFLAGS=@CFLAGS@ $(MACROS)
|
||||
CPPFLAGS=@CPPFLAGS@
|
||||
LDFLAGS= @LIBS@ @LDFLAGS@
|
||||
|
||||
MACROS = -DLOCALEDIR=\"$(localedir)\" -DPREFIX=L\"$(prefix)\" -DDATADIR=L\"$(datadir)\" -DSYSCONFDIR=L\"$(sysconfdir)\"
|
||||
CFLAGS = @CFLAGS@ $(MACROS) $(EXTRA_CFLAGS)
|
||||
CPPFLAGS = @CPPFLAGS@
|
||||
LDFLAGS = @LIBS@ @LDFLAGS@
|
||||
LDFLAGS_FISH = ${LDFLAGS} @LIBS_FISH@ @LDFLAGS_FISH@
|
||||
LDFLAGS_FISH_INDENT = ${LDFLAGS} @LIBS_FISH_INDENT@
|
||||
LDFLAGS_FISH_PAGER = ${LDFLAGS} @LIBS_FISH_PAGER@
|
||||
LDFLAGS_FISHD = ${LDFLAGS} @LIBS_FISHD@
|
||||
LDFLAGS_MIMEDB = ${LDFLAGS} @LIBS_MIMEDB@
|
||||
LDFLAGS_SET_COLOR = ${LDFLAGS} @LIBS_SET_COLOR@
|
||||
|
||||
#
|
||||
# Set to 1 if we have gettext
|
||||
@@ -82,15 +89,18 @@ COMMON_FILES := util.c halloc.c halloc_util.c fallback.c
|
||||
|
||||
|
||||
#
|
||||
# All objects that the system needs to build fish, except main.o
|
||||
# All objects that the system needs to build fish, except fish.o
|
||||
#
|
||||
|
||||
FISH_OBJS := function.o builtin.o complete.o env.o exec.o expand.o \
|
||||
highlight.o history.o kill.o parser.o proc.o reader.o sanity.o \
|
||||
tokenizer.o wildcard.o wgetopt.o wutil.o input.o output.o intern.o \
|
||||
env_universal.o env_universal_common.o input_common.o event.o \
|
||||
signal.o io.o parse_util.o common.o screen.o path.o
|
||||
signal.o io.o parse_util.o common.o screen.o path.o \
|
||||
parser_keywords.o
|
||||
|
||||
FISH_INDENT_OBJS := fish_indent.o print_help.o common.o \
|
||||
parser_keywords.o wutil.o tokenizer.o
|
||||
|
||||
#
|
||||
# Additional files used by builtin.o
|
||||
@@ -104,7 +114,7 @@ BUILTIN_FILES := builtin_set.c builtin_commandline.c \
|
||||
# All objects that the system needs to build fish_pager
|
||||
#
|
||||
|
||||
FISH_PAGER_OBJS := fish_pager.o output.o wutil.o tokenizer.o \
|
||||
FISH_PAGER_OBJS := fish_pager.o output.o wutil.o \
|
||||
input_common.o env_universal.o env_universal_common.o common.o \
|
||||
print_help.o
|
||||
|
||||
@@ -151,7 +161,7 @@ HDR_FILES_SRC := doc_src/index.hdr.in doc_src/commands.hdr.in doc_src/design.hdr
|
||||
HDR_FILES := $(subst .hdr.in,.hdr,$(HDR_FILES_SRC))
|
||||
|
||||
#
|
||||
# Files containing documentation for external commands.
|
||||
# Files containing documentation for external commands.
|
||||
#
|
||||
|
||||
HELP_SRC := $(wildcard doc_src/*.txt)
|
||||
@@ -181,12 +191,12 @@ DOC_SRC_DIR_FILES := $(HDR_FILES_SRC) $(HELP_SRC)
|
||||
|
||||
MAIN_DIR_FILES_UNSORTED := Doxyfile Doxyfile.user Doxyfile.help.in \
|
||||
Makefile.in configure configure.ac config.h.in install-sh \
|
||||
set_color.c count.c key_reader.c $(MIME_OBJS:.o=.h) \
|
||||
set_color.c key_reader.c $(MIME_OBJS:.o=.h) \
|
||||
$(MIME_OBJS:.o=.c) $(FISH_OBJS:.o=.h) $(BUILTIN_FILES) \
|
||||
$(COMMON_FILES) $(COMMON_FILES:.c=.h) $(FISH_OBJS:.o=.c) \
|
||||
fish.spec.in INSTALL README user_doc.head.html xsel-0.9.6.tar \
|
||||
ChangeLog config.sub config.guess fish_tests.c main.c fish_pager.c \
|
||||
fishd.c seq.in
|
||||
ChangeLog config.sub config.guess fish_tests.c fish.c fish_pager.c \
|
||||
fishd.c seq.in make_vcs_completions.fish $(FISH_INDENT_OBJS:.o=.c)
|
||||
|
||||
#
|
||||
# The sorting is not meaningful in itself, but it has the side effect
|
||||
@@ -201,14 +211,14 @@ MAIN_DIR_FILES := $(sort $(MAIN_DIR_FILES_UNSORTED))
|
||||
# Files in ./etc/
|
||||
#
|
||||
|
||||
ETC_DIR_FILES :=etc/config.fish.in etc/fish_inputrc
|
||||
ETC_DIR_FILES :=etc/config.fish.in
|
||||
|
||||
|
||||
#
|
||||
# Files in ./share/
|
||||
#
|
||||
|
||||
SHARE_DIR_FILES :=share/config.fish.in share/config_interactive.fish.in
|
||||
SHARE_DIR_FILES :=share/config.fish.in
|
||||
|
||||
|
||||
#
|
||||
@@ -237,8 +247,8 @@ FUNCTIONS_DIR_FILES := $(wildcard share/functions/*.fish)
|
||||
# Programs to install
|
||||
#
|
||||
|
||||
SIMPLE_PROGRAMS := fish set_color mimedb count fish_pager fishd
|
||||
PROGRAMS := $(SIMPLE_PROGRAMS) @XSEL@ @SEQ_FALLBACK@
|
||||
SIMPLE_PROGRAMS := fish set_color mimedb fish_pager fishd fish_indent
|
||||
PROGRAMS := $(SIMPLE_PROGRAMS) @XSEL_BIN@ @SEQ_FALLBACK@
|
||||
|
||||
|
||||
#
|
||||
@@ -257,12 +267,19 @@ TRANSLATIONS_SRC := $(wildcard po/*.po)
|
||||
TRANSLATIONS := $(TRANSLATIONS_SRC:.po=.gmo)
|
||||
|
||||
|
||||
#
|
||||
# Extra util
|
||||
#
|
||||
|
||||
XSEL := @XSEL@
|
||||
XSEL_BIN := @XSEL_BIN@
|
||||
|
||||
#
|
||||
# Make everything needed for installing fish
|
||||
#
|
||||
|
||||
all: $(PROGRAMS) user_doc share/man etc/config.fish share/config.fish share/config_interactive.fish $(TRANSLATIONS)
|
||||
@echo fish has now been built.
|
||||
all: $(PROGRAMS) user_doc share/man etc/config.fish share/config.fish $(TRANSLATIONS)
|
||||
@echo fish has now been built.
|
||||
@echo Use \'$(MAKE) install\' to install fish.
|
||||
.PHONY: all
|
||||
|
||||
@@ -285,17 +302,22 @@ Makefile: Makefile.in configure
|
||||
#
|
||||
|
||||
debug:
|
||||
$(MAKE) fish CFLAGS="@CFLAGS@ $(MACROS) -O0 -Wno-unused -Werror -g"
|
||||
$(MAKE) all EXTRA_CFLAGS="-O0 -Wno-unused -Werror -g"
|
||||
.PHONY: debug
|
||||
|
||||
prof:
|
||||
$(MAKE) all EXTRA_CFLAGS="-pg" LDFLAGS="-pg"
|
||||
.PHONY: prof
|
||||
|
||||
#
|
||||
# User documentation, describing the features of the fish shell.
|
||||
#
|
||||
|
||||
# Depend on the sources (*.hdr.in) and manually make the
|
||||
# intermediate *.hdr and doc.h files if needed
|
||||
|
||||
user_doc: $(HDR_FILES) Doxyfile.user user_doc.head.html
|
||||
$(MAKE) doc.h # Depend on the sources (*.hdr) and manually make the intermediate doc.h file if needed
|
||||
user_doc: $(HDR_FILES_SRC) Doxyfile.user user_doc.head.html $(HELP_SRC)
|
||||
$(MAKE) doc.h $(HDR_FILES)
|
||||
doxygen Doxyfile.user
|
||||
touch user_doc
|
||||
|
||||
@@ -304,19 +326,19 @@ user_doc: $(HDR_FILES) Doxyfile.user user_doc.head.html
|
||||
# Source code documentation. Also includes user documentation.
|
||||
#
|
||||
|
||||
doc: *.h *.c doc.h Doxyfile
|
||||
doxygen;
|
||||
doc: *.h *.c doc.h Doxyfile
|
||||
doxygen;
|
||||
|
||||
|
||||
#
|
||||
# PDF version of the source code documentation.
|
||||
#
|
||||
|
||||
doc/refman.pdf: doc
|
||||
cd doc/latex;
|
||||
make;
|
||||
mv refman.pdf ..;
|
||||
cd ../..;
|
||||
doc/refman.pdf: doc
|
||||
cd doc/latex;
|
||||
make;
|
||||
mv refman.pdf ..;
|
||||
cd ../..;
|
||||
rm -r doc/latex;
|
||||
|
||||
|
||||
@@ -333,11 +355,8 @@ test: $(PROGRAMS) fish_tests
|
||||
# Build the xsel program, which is maintained in its own tarball
|
||||
#
|
||||
|
||||
xsel-0.9.6:
|
||||
tar -xf xsel-0.9.6.tar
|
||||
|
||||
xsel-0.9.6/xsel: xsel-0.9.6
|
||||
cd xsel-0.9.6; ./configure; make
|
||||
$(XSEL_BIN):
|
||||
$(MAKE) -C $(XSEL) || echo "Failed to build xsel - either add the required dependencies or use './configure --without-xsel' to disable it."
|
||||
|
||||
|
||||
#
|
||||
@@ -353,7 +372,7 @@ doc_src/commands.hdr:$(HELP_SRC) doc_src/commands.hdr.in
|
||||
echo >>command_list.tmp; \
|
||||
echo >>command_list.tmp; \
|
||||
echo "Back to <a href='index.html#toc-commands'>index</a>". >>command_list.tmp; \
|
||||
done
|
||||
done
|
||||
mv command_list.tmp command_list.txt
|
||||
cat $@.in | awk '{if ($$0 ~ /@command_list@/){ system("cat command_list.txt");} else{ print $$0;}}' >$@
|
||||
|
||||
@@ -391,19 +410,19 @@ doc.h: $(HDR_FILES)
|
||||
#
|
||||
|
||||
%.doxygen:%.txt
|
||||
echo "/** \page " `basename $*` >$@;
|
||||
cat $*.txt >>$@;
|
||||
echo "/** \page " `basename $*` >$@;
|
||||
cat $*.txt >>$@;
|
||||
echo "*/" >>$@
|
||||
|
||||
%: %.in Makefile
|
||||
%: %.in
|
||||
sed <$@.in >$@ \
|
||||
-e "s,@sysconfdir\@,$(sysconfdir),g" \
|
||||
-e "s,@datadir\@,$(datadir),g" \
|
||||
-e "s,@docdir\@,$(docdir),g" \
|
||||
-e "s|@configure_input\@|$@, generated from $@.in by the Makefile. DO NOT MANUALLY EDIT THIS FILE!|g" \
|
||||
-e "s,@prefix\@,$(prefix),g" \
|
||||
-e "s,@optbindirs\@,$(optbindirs),g"
|
||||
#-e "s,@\@,$(),"
|
||||
-e "s,@optbindirs\@,$(optbindirs),g"
|
||||
#-e "s,@\@,$(),"
|
||||
|
||||
|
||||
#
|
||||
@@ -411,7 +430,7 @@ doc.h: $(HDR_FILES)
|
||||
#
|
||||
|
||||
%.gmo:
|
||||
if test $(HAVE_GETTEXT) = 1; then \
|
||||
if test "$(HAVE_GETTEXT)" = 1; then \
|
||||
msgfmt -o $*.gmo $*.po; \
|
||||
fi
|
||||
|
||||
@@ -468,8 +487,8 @@ common.o: $(COMMON_FILES)
|
||||
# (__fish_print_help)
|
||||
# ||
|
||||
# \/
|
||||
# formated text
|
||||
# with escape
|
||||
# formated text
|
||||
# with escape
|
||||
# sequences
|
||||
#
|
||||
#
|
||||
@@ -491,7 +510,7 @@ share/man: $(HELP_SRC)
|
||||
for i in $(HELP_SRC); do \
|
||||
CMD_NAME=`basename $$i .txt`; \
|
||||
sed -e "s/\(.\)\\.SH/\1/" -e "s/$$CMD_NAME *\\\\- *\"\(.*\)\"/\1/" <help_doc/man/man1/$$CMD_NAME.1 >share/man/$$CMD_NAME.1; \
|
||||
done
|
||||
done
|
||||
rm doc_src/*.doxygen # Clean up intermediate files in doc_src/
|
||||
rm -r help_doc # Clean up intermediate help_doc tree
|
||||
|
||||
@@ -541,10 +560,6 @@ install-sh:
|
||||
if test -x $@; then true; else chmod 755 $@; fi
|
||||
.PHONY: install-sh
|
||||
|
||||
make_mercurial_completions.fish:
|
||||
if test -x $@; then true; else chmod 755 $@; fi
|
||||
.PHONY: make_mercurial_completions.fish
|
||||
|
||||
|
||||
#
|
||||
# Try to install after checking for incompatible installed versions.
|
||||
@@ -560,7 +575,7 @@ install: all install-sh check-uninstall install-force
|
||||
#
|
||||
|
||||
install-force: all install-translations
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(bindir)
|
||||
for i in $(PROGRAMS); do\
|
||||
$(INSTALL) -m 755 $$i $(DESTDIR)$(bindir) ; \
|
||||
done;
|
||||
@@ -571,7 +586,6 @@ install-force: all install-translations
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(datadir)/fish/man
|
||||
$(INSTALL) -m 644 etc/config.fish $(DESTDIR)$(sysconfdir)/fish/
|
||||
$(INSTALL) -m 644 share/config.fish $(DESTDIR)$(datadir)/fish/
|
||||
$(INSTALL) -m 644 share/config_interactive.fish $(DESTDIR)$(datadir)/fish/
|
||||
for i in $(COMPLETIONS_DIR_FILES); do \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/completions/; \
|
||||
done;
|
||||
@@ -581,7 +595,6 @@ install-force: all install-translations
|
||||
for i in share/man/*.1; do \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(datadir)/fish/man/; \
|
||||
done;
|
||||
$(INSTALL) -m 644 etc/fish_inputrc $(DESTDIR)$(sysconfdir)/fish/fish_inputrc;
|
||||
$(INSTALL) -m 755 -d $(DESTDIR)$(docdir)
|
||||
for i in user_doc/html/* ChangeLog; do \
|
||||
if test -f $$i; then \
|
||||
@@ -592,7 +605,7 @@ install-force: all install-translations
|
||||
for i in $(MANUALS); do \
|
||||
$(INSTALL) -m 644 $$i $(DESTDIR)$(mandir)/man1/; \
|
||||
done;
|
||||
@echo fish is now installed on your system.
|
||||
@echo fish is now installed on your system.
|
||||
@echo To run fish, type \'fish\' in your terminal.
|
||||
@echo
|
||||
@echo To use fish as your login shell:
|
||||
@@ -613,7 +626,6 @@ uninstall: uninstall-translations
|
||||
done;
|
||||
-rm -f $(DESTDIR)$(bindir)/xsel
|
||||
-rm -f $(DESTDIR)$(sysconfdir)/fish/config.fish
|
||||
-rm -f $(DESTDIR)$(sysconfdir)/fish/fish_inputrc
|
||||
-rmdir $(DESTDIR)$(sysconfdir)/fish
|
||||
-if test -d $(DESTDIR)$(datadir)/fish; then \
|
||||
rm -r $(DESTDIR)$(datadir)/fish; \
|
||||
@@ -638,6 +650,7 @@ 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
|
||||
-rm -f $(DESTDIR)$(sysconfdir)/fish/fish_inputrc
|
||||
-if test -d $(DESTDIR)$(sysconfdir)/fish.d/completions; then \
|
||||
for i in $(COMPLETIONS_DIR_FILES); do \
|
||||
basename=`basename $$i`; \
|
||||
@@ -649,7 +662,7 @@ uninstall-legacy: uninstall
|
||||
-rmdir $(DESTDIR)$(sysconfdir)/fish.d/completions
|
||||
-rmdir $(DESTDIR)$(sysconfdir)/fish.d
|
||||
-rm $(DESTDIR)$(sysconfdir)/fish
|
||||
@echo The previous fish installation has been removed.
|
||||
@echo The previous fish installation has been removed.
|
||||
.PHONY: uninstall-legacy
|
||||
|
||||
install-translations: $(TRANSLATIONS)
|
||||
@@ -662,7 +675,7 @@ install-translations: $(TRANSLATIONS)
|
||||
fi;
|
||||
.PHONY: install-translations
|
||||
|
||||
uninstall-translations:
|
||||
uninstall-translations:
|
||||
if test $(HAVE_GETTEXT) = 1; then \
|
||||
for i in $(TRANSLATIONS_SRC); do \
|
||||
rm -f $(DESTDIR)$(datadir)/locale/*/LC_MESSAGES/fish.mo; \
|
||||
@@ -679,8 +692,8 @@ uninstall-translations:
|
||||
# Build the fish program.
|
||||
#
|
||||
|
||||
fish: $(FISH_OBJS) main.o
|
||||
$(CC) $(FISH_OBJS) main.o $(LDFLAGS) -o $@
|
||||
fish: $(FISH_OBJS) fish.o
|
||||
$(CC) $(FISH_OBJS) fish.o $(LDFLAGS_FISH) -o $@
|
||||
|
||||
|
||||
#
|
||||
@@ -688,15 +701,15 @@ fish: $(FISH_OBJS) main.o
|
||||
#
|
||||
|
||||
fish_pager: $(FISH_PAGER_OBJS)
|
||||
$(CC) $(FISH_PAGER_OBJS) $(LDFLAGS) -o $@
|
||||
$(CC) $(FISH_PAGER_OBJS) $(LDFLAGS_FISH_PAGER) -o $@
|
||||
|
||||
|
||||
#
|
||||
# Build the fishd program.
|
||||
#
|
||||
|
||||
fishd: $(FISHD_OBJS)
|
||||
$(CC) $(FISHD_OBJS) $(LDFLAGS) -o $@
|
||||
fishd: $(FISHD_OBJS)
|
||||
$(CC) $(FISHD_OBJS) $(LDFLAGS_FISHD) -o $@
|
||||
|
||||
|
||||
#
|
||||
@@ -704,7 +717,7 @@ fishd: $(FISHD_OBJS)
|
||||
#
|
||||
|
||||
fish_tests: $(FISH_TESTS_OBJS)
|
||||
$(CC) $(FISH_TESTS_OBJS) $(LDFLAGS) -o $@
|
||||
$(CC) $(FISH_TESTS_OBJS) $(LDFLAGS_FISH) -o $@
|
||||
|
||||
|
||||
#
|
||||
@@ -714,17 +727,7 @@ fish_tests: $(FISH_TESTS_OBJS)
|
||||
#
|
||||
|
||||
mimedb: $(MIME_OBJS)
|
||||
$(CC) $(MIME_OBJS) $(LDFLAGS) -o $@
|
||||
|
||||
|
||||
#
|
||||
# Build the count program.
|
||||
#
|
||||
# count does not need any libraries, so we don't use LDFLAGS here.
|
||||
#
|
||||
|
||||
count: count.o
|
||||
$(CC) count.o -o $@
|
||||
$(CC) $(MIME_OBJS) $(LDFLAGS_MIMEDB) -o $@
|
||||
|
||||
|
||||
#
|
||||
@@ -732,7 +735,7 @@ count: count.o
|
||||
#
|
||||
|
||||
set_color: set_color.o print_help.o common.o
|
||||
$(CC) set_color.o print_help.o common.o wutil.o $(LDFLAGS) -o $@
|
||||
$(CC) set_color.o print_help.o common.o wutil.o $(LDFLAGS_SET_COLOR) -o $@
|
||||
|
||||
|
||||
#
|
||||
@@ -743,19 +746,27 @@ tokenizer_test: tokenizer.c tokenizer.h wutil.o common.o
|
||||
$(CC) $(CFLAGS) tokenizer.c wutil.o common.o -D TOKENIZER_TEST $(LDFLAGS) -o $@
|
||||
|
||||
|
||||
#
|
||||
# Build the fish_indent program.
|
||||
#
|
||||
|
||||
fish_indent: $(FISH_INDENT_OBJS)
|
||||
$(CC) $(FISH_INDENT_OBJS) $(LDFLAGS_FISH_INDENT) -o $@
|
||||
|
||||
|
||||
#
|
||||
# Neat little program to show output from terminal
|
||||
#
|
||||
|
||||
key_reader: key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o
|
||||
$(CC) key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o $(LDFLAGS) -o $@
|
||||
$(CC) key_reader.o input_common.o common.o env_universal.o env_universal_common.o wutil.o $(LDFLAGS_FISH) -o $@
|
||||
|
||||
|
||||
#
|
||||
# Update dependencies
|
||||
#
|
||||
depend:
|
||||
makedepend -fMakefile.in -Y *.c
|
||||
makedepend -fMakefile.in -Y *.c
|
||||
./config.status
|
||||
.PHONY: depend
|
||||
|
||||
@@ -764,7 +775,7 @@ depend:
|
||||
# an archive from it. Simplest way I could think of to make an archive
|
||||
# witout backups, autogenerated files, etc.
|
||||
#
|
||||
# Uses install instead of mkdir so build won't fail if the directory
|
||||
# Uses install instead of mkdir so build won't fail if the directory
|
||||
# exists
|
||||
#
|
||||
|
||||
@@ -816,28 +827,13 @@ dist: fish-@PACKAGE_VERSION@.tar.bz2
|
||||
.PHONY: dist
|
||||
|
||||
#
|
||||
# Build the RPM spec file.
|
||||
# Build the RPM spec file.
|
||||
#
|
||||
|
||||
fish.spec: fish.spec.in
|
||||
./config.status
|
||||
|
||||
|
||||
#
|
||||
# Completion files which are autogenerated using various scripts
|
||||
#
|
||||
|
||||
share/completions/darcs.fish: make_mercurial_completions.fish
|
||||
./make_mercurial_completions.fish darcs 'complete -c darcs -n "not __fish_use_subcommand" -a "(test -f _darcs/prefs/repos; and cat _darcs/prefs/repos)" --description "Darcs repo"' 'complete -c darcs -a "test predist boringfile binariesfile" -n "contains setpref (commandline -poc)" -d "woot" -x' >$@
|
||||
|
||||
share/completions/hg.fish: make_mercurial_completions.fish
|
||||
./make_mercurial_completions.fish hg >$@
|
||||
|
||||
share/completions/svn.fish: make_mercurial_completions.fish
|
||||
./make_mercurial_completions.fish svn >$@
|
||||
|
||||
share/completions/cvs.fish: make_mercurial_completions.fish
|
||||
./make_mercurial_completions.fish cvs >$@
|
||||
|
||||
#
|
||||
# Create .rpm file for the current systems architecture and an
|
||||
@@ -868,9 +864,10 @@ rpm: fish-@PACKAGE_VERSION@.tar.bz2 fish.spec
|
||||
#
|
||||
|
||||
distclean: clean
|
||||
rm -f fish.spec Doxyfile.help
|
||||
rm -f etc/config.fish share/config_interactive.fish seq share/config.fish
|
||||
rm -f fish.spec Doxyfile.help
|
||||
rm -f etc/config.fish seq share/config.fish
|
||||
rm -f config.status config.log config.h Makefile
|
||||
rm -rf $(XSEL)
|
||||
.PHONY: distclean
|
||||
|
||||
|
||||
@@ -882,49 +879,51 @@ distclean: clean
|
||||
clean:
|
||||
rm -f *.o doc.h doc.tmp doc_src/*.doxygen doc_src/*.c doc_src/*.o doc_src/commands.hdr
|
||||
rm -f tests/tmp.err tests/tmp.out tests/tmp.status tests/foo.txt
|
||||
rm -f tokenizer_test fish key_reader set_color mimedb
|
||||
rm -f fishd fish_pager count fish_tests
|
||||
rm -f fish-@PACKAGE_VERSION@.tar
|
||||
rm -f fish-@PACKAGE_VERSION@.tar.gz
|
||||
rm -f $(PROGRAMS) fish_tests tokenizer_test key_reader
|
||||
rm -f share/config.fish etc/config.fish doc_src/index.hdr doc_src/commands.hdr
|
||||
rm -f fish-@PACKAGE_VERSION@.tar
|
||||
rm -f fish-@PACKAGE_VERSION@.tar.gz
|
||||
rm -f fish-@PACKAGE_VERSION@.tar.bz2
|
||||
rm -rf doc;
|
||||
rm -rf doc;
|
||||
rm -rf fish-@PACKAGE_VERSION@
|
||||
rm -rf xsel-0.9.6/
|
||||
rm -f $(TRANSLATIONS)
|
||||
test ! -d "$(XSEL)" || make -C $(XSEL) clean
|
||||
.PHONY: clean
|
||||
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
builtin.o: config.h fallback.h util.h wutil.h builtin.h function.h complete.h
|
||||
builtin.o: proc.h io.h parser.h event.h reader.h env.h common.h wgetopt.h
|
||||
builtin.o: sanity.h tokenizer.h wildcard.h input_common.h input.h intern.h
|
||||
builtin.o: signal.h halloc.h halloc_util.h parse_util.h expand.h path.h
|
||||
builtin.o: builtin_set.c builtin_commandline.c builtin_complete.c
|
||||
builtin.o: builtin_ulimit.c builtin_jobs.c
|
||||
builtin.o: config.h fallback.h util.h wutil.h builtin.h io.h function.h
|
||||
builtin.o: complete.h proc.h parser.h event.h reader.h env.h common.h
|
||||
builtin.o: wgetopt.h sanity.h tokenizer.h wildcard.h input_common.h input.h
|
||||
builtin.o: intern.h signal.h exec.h highlight.h halloc.h halloc_util.h
|
||||
builtin.o: parse_util.h parser_keywords.h expand.h path.h builtin_set.c
|
||||
builtin.o: builtin_commandline.c builtin_complete.c builtin_ulimit.c
|
||||
builtin.o: builtin_jobs.c
|
||||
builtin_commandline.o: config.h signal.h fallback.h util.h wutil.h builtin.h
|
||||
builtin_commandline.o: common.h wgetopt.h reader.h proc.h io.h parser.h
|
||||
builtin_commandline.o: io.h common.h wgetopt.h reader.h proc.h parser.h
|
||||
builtin_commandline.o: event.h tokenizer.h input_common.h input.h
|
||||
builtin_commandline.o: parse_util.h
|
||||
builtin_complete.o: config.h signal.h fallback.h util.h wutil.h builtin.h
|
||||
builtin_complete.o: common.h complete.h wgetopt.h parser.h proc.h io.h
|
||||
builtin_complete.o: io.h common.h complete.h wgetopt.h parser.h proc.h
|
||||
builtin_complete.o: event.h reader.h
|
||||
builtin_jobs.o: config.h fallback.h util.h wutil.h builtin.h proc.h io.h
|
||||
builtin_jobs.o: config.h fallback.h util.h wutil.h builtin.h io.h proc.h
|
||||
builtin_jobs.o: parser.h event.h common.h wgetopt.h
|
||||
builtin_set.o: config.h signal.h fallback.h util.h wutil.h builtin.h env.h
|
||||
builtin_set.o: expand.h common.h wgetopt.h proc.h io.h parser.h event.h
|
||||
builtin_ulimit.o: config.h fallback.h util.h builtin.h common.h wgetopt.h
|
||||
builtin_set.o: config.h signal.h fallback.h util.h wutil.h builtin.h io.h
|
||||
builtin_set.o: env.h expand.h common.h wgetopt.h proc.h parser.h event.h
|
||||
builtin_ulimit.o: config.h fallback.h util.h builtin.h io.h common.h
|
||||
builtin_ulimit.o: wgetopt.h
|
||||
common.o: config.h fallback.h util.h wutil.h common.h expand.h proc.h io.h
|
||||
common.o: wildcard.h parser.h event.h util.c halloc.c halloc.h halloc_util.c
|
||||
common.o: fallback.c
|
||||
complete.o: config.h signal.h fallback.h util.h tokenizer.h wildcard.h proc.h
|
||||
complete.o: io.h parser.h event.h function.h complete.h builtin.h env.h
|
||||
complete.o: exec.h expand.h common.h reader.h history.h intern.h parse_util.h
|
||||
complete.o: halloc.h halloc_util.h wutil.h path.h
|
||||
count.o: config.h
|
||||
complete.o: parser_keywords.h halloc.h halloc_util.h wutil.h path.h
|
||||
env.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h env.h
|
||||
env.o: sanity.h expand.h history.h reader.h parser.h event.h env_universal.h
|
||||
env.o: env_universal_common.h input_common.h complete.h
|
||||
env.o: env_universal_common.h input_common.h path.h halloc.h halloc_util.h
|
||||
env.o: complete.h
|
||||
env_universal.o: config.h signal.h fallback.h util.h common.h wutil.h
|
||||
env_universal.o: env_universal_common.h env_universal.h
|
||||
env_universal_common.o: config.h signal.h fallback.h util.h common.h wutil.h
|
||||
@@ -938,30 +937,36 @@ expand.o: config.h signal.h fallback.h util.h common.h wutil.h env.h proc.h
|
||||
expand.o: io.h parser.h event.h expand.h wildcard.h exec.h tokenizer.h
|
||||
expand.o: complete.h parse_util.h halloc.h halloc_util.h
|
||||
fallback.o: config.h fallback.h util.h
|
||||
fishd.o: config.h signal.h fallback.h util.h common.h wutil.h
|
||||
fishd.o: env_universal_common.h halloc.h halloc_util.h path.h
|
||||
fish.o: config.h signal.h fallback.h util.h common.h reader.h io.h builtin.h
|
||||
fish.o: function.h complete.h wutil.h env.h sanity.h proc.h parser.h event.h
|
||||
fish.o: expand.h intern.h exec.h output.h halloc.h halloc_util.h history.h
|
||||
fish.o: path.h
|
||||
fish_indent.o: config.h fallback.h util.h common.h wutil.h halloc.h
|
||||
fish_indent.o: halloc_util.h tokenizer.h print_help.h parser_keywords.h
|
||||
fish_pager.o: config.h signal.h fallback.h util.h wutil.h common.h complete.h
|
||||
fish_pager.o: output.h input_common.h env_universal.h env_universal_common.h
|
||||
fish_pager.o: halloc.h halloc_util.h
|
||||
fish_pager.o: halloc.h halloc_util.h print_help.h
|
||||
fish_tests.o: config.h signal.h fallback.h util.h common.h proc.h io.h
|
||||
fish_tests.o: reader.h builtin.h function.h complete.h wutil.h env.h expand.h
|
||||
fish_tests.o: parser.h event.h tokenizer.h output.h exec.h halloc_util.h
|
||||
fish_tests.o: parser.h event.h tokenizer.h output.h exec.h path.h halloc.h
|
||||
fish_tests.o: halloc_util.h
|
||||
fishd.o: config.h signal.h fallback.h util.h common.h wutil.h
|
||||
fishd.o: env_universal_common.h halloc.h halloc_util.h path.h print_help.h
|
||||
function.o: config.h signal.h wutil.h fallback.h util.h function.h proc.h
|
||||
function.o: io.h parser.h event.h common.h intern.h reader.h parse_util.h
|
||||
function.o: env.h expand.h halloc.h halloc_util.h
|
||||
function.o: parser_keywords.h env.h expand.h halloc.h halloc_util.h
|
||||
halloc.o: config.h fallback.h util.h common.h halloc.h
|
||||
halloc_util.o: config.h fallback.h util.h common.h halloc.h
|
||||
highlight.o: config.h signal.h fallback.h util.h wutil.h highlight.h
|
||||
highlight.o: tokenizer.h proc.h io.h parser.h event.h parse_util.h builtin.h
|
||||
highlight.o: function.h env.h expand.h sanity.h common.h complete.h output.h
|
||||
highlight.o: halloc.h halloc_util.h wildcard.h path.h
|
||||
history2.o: config.h fallback.h util.h wutil.h history.h common.h halloc.h
|
||||
history2.o: halloc_util.h intern.h path.h
|
||||
highlight.o: tokenizer.h proc.h io.h parser.h event.h parse_util.h
|
||||
highlight.o: parser_keywords.h builtin.h function.h env.h expand.h sanity.h
|
||||
highlight.o: common.h complete.h output.h halloc.h halloc_util.h wildcard.h
|
||||
highlight.o: path.h
|
||||
history.o: config.h fallback.h util.h wutil.h history.h common.h halloc.h
|
||||
history.o: halloc_util.h intern.h path.h signal.h
|
||||
input.o: config.h signal.h fallback.h util.h wutil.h reader.h proc.h io.h
|
||||
input.o: config.h signal.h fallback.h util.h wutil.h reader.h io.h proc.h
|
||||
input.o: common.h sanity.h input_common.h input.h parser.h event.h env.h
|
||||
input.o: expand.h output.h intern.h
|
||||
input.o: expand.h output.h intern.h halloc.h halloc_util.h
|
||||
input_common.o: config.h fallback.h util.h common.h wutil.h input_common.h
|
||||
input_common.o: env_universal.h env_universal_common.h
|
||||
intern.o: config.h fallback.h util.h wutil.h common.h intern.h
|
||||
@@ -969,48 +974,44 @@ io.o: config.h fallback.h util.h wutil.h exec.h proc.h io.h common.h halloc.h
|
||||
key_reader.o: config.h fallback.h input_common.h
|
||||
kill.o: config.h signal.h fallback.h util.h wutil.h kill.h proc.h io.h
|
||||
kill.o: sanity.h common.h env.h exec.h halloc.h path.h
|
||||
main.o: config.h signal.h fallback.h util.h common.h reader.h builtin.h
|
||||
main.o: function.h complete.h wutil.h env.h sanity.h proc.h io.h parser.h
|
||||
main.o: event.h expand.h intern.h exec.h output.h halloc.h halloc_util.h
|
||||
main.o: history.h path.h
|
||||
mimedb.o: config.h xdgmime.h fallback.h util.h
|
||||
mimedb.o: config.h xdgmime.h fallback.h util.h print_help.h
|
||||
output.o: config.h signal.h fallback.h util.h wutil.h expand.h common.h
|
||||
output.o: output.h halloc_util.h highlight.h
|
||||
parser.o: config.h signal.h fallback.h util.h common.h wutil.h proc.h io.h
|
||||
parser.o: parser.h event.h tokenizer.h exec.h wildcard.h function.h builtin.h
|
||||
parser.o: env.h expand.h reader.h sanity.h env_universal.h
|
||||
parser.o: env_universal_common.h intern.h parse_util.h halloc.h halloc_util.h
|
||||
parser.o: path.h
|
||||
parse_util.o: config.h fallback.h util.h wutil.h common.h tokenizer.h
|
||||
parse_util.o: parse_util.h expand.h intern.h exec.h proc.h io.h env.h
|
||||
parse_util.o: signal.h wildcard.h halloc_util.h
|
||||
parser.o: config.h signal.h fallback.h util.h common.h wutil.h proc.h io.h
|
||||
parser.o: parser.h event.h parser_keywords.h tokenizer.h exec.h wildcard.h
|
||||
parser.o: function.h builtin.h env.h expand.h reader.h sanity.h
|
||||
parser.o: env_universal.h env_universal_common.h intern.h parse_util.h
|
||||
parser.o: halloc.h halloc_util.h path.h
|
||||
parser_keywords.o: config.h fallback.h common.h util.h parser_keywords.h
|
||||
path.o: config.h fallback.h util.h common.h env.h wutil.h halloc.h
|
||||
path.o: halloc_util.h path.h expand.h
|
||||
print_help.o: print_help.h
|
||||
proc.o: config.h signal.h fallback.h util.h wutil.h proc.h io.h common.h
|
||||
proc.o: reader.h sanity.h env.h parser.h event.h halloc.h halloc_util.h
|
||||
proc.o: output.h
|
||||
reader.o: config.h signal.h fallback.h util.h wutil.h highlight.h reader.h
|
||||
reader.o: proc.h io.h parser.h event.h complete.h history.h common.h sanity.h
|
||||
reader.o: io.h proc.h parser.h event.h complete.h history.h common.h sanity.h
|
||||
reader.o: env.h exec.h expand.h tokenizer.h kill.h input_common.h input.h
|
||||
reader.o: function.h output.h screen.h parse_util.h
|
||||
reader.o: function.h output.h screen.h halloc.h halloc_util.h parse_util.h
|
||||
sanity.o: config.h signal.h fallback.h util.h common.h sanity.h proc.h io.h
|
||||
sanity.o: history.h reader.h kill.h wutil.h
|
||||
screen.o: config.h fallback.h common.h util.h wutil.h output.h highlight.h
|
||||
screen.o: screen.h env.h
|
||||
set_color.o: config.h fallback.h print_help.h
|
||||
signal.o: config.h signal.h common.h util.h fallback.h wutil.h event.h
|
||||
signal.o: reader.h proc.h io.h
|
||||
test.o: stringtab.h
|
||||
signal.o: reader.h io.h proc.h
|
||||
tokenizer.o: config.h fallback.h util.h wutil.h tokenizer.h common.h
|
||||
tokenizer.o: wildcard.h
|
||||
util.o: config.h fallback.h util.h common.h wutil.h
|
||||
wgetopt.o: config.h wgetopt.h wutil.h fallback.h
|
||||
wildcard.o: config.h fallback.h util.h wutil.h complete.h common.h wildcard.h
|
||||
wildcard.o: reader.h expand.h
|
||||
wildcard.o: reader.h io.h expand.h exec.h proc.h halloc_util.h
|
||||
wutil.o: config.h fallback.h util.h common.h wutil.h halloc.h halloc_util.h
|
||||
xdgmimealias.o: xdgmimealias.h xdgmime.h xdgmimeint.h
|
||||
xdgmime.o: xdgmime.h xdgmimeint.h xdgmimeglob.h xdgmimemagic.h xdgmimealias.h
|
||||
xdgmime.o: xdgmimeparent.h
|
||||
xdgmimealias.o: xdgmimealias.h xdgmime.h xdgmimeint.h
|
||||
xdgmimeglob.o: xdgmimeglob.h xdgmime.h xdgmimeint.h
|
||||
xdgmimeint.o: xdgmimeint.h xdgmime.h
|
||||
xdgmimemagic.o: xdgmimemagic.h xdgmime.h xdgmimeint.h
|
||||
|
||||
21
builtin.h
21
builtin.h
@@ -8,6 +8,7 @@
|
||||
#include <wchar.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "io.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -63,7 +64,7 @@ enum
|
||||
#define BUILTIN_FOR_ERR_IN _( L"%ls: Second argument must be 'in'\n" )
|
||||
|
||||
/**
|
||||
Error message for insufficient number of arguments
|
||||
Error message for insufficient number of arguments
|
||||
*/
|
||||
#define BUILTIN_FOR_ERR_COUNT _( L"%ls: Expected at least two arguments, got %d\n")
|
||||
|
||||
@@ -107,7 +108,7 @@ extern int builtin_err_redirect;
|
||||
|
||||
|
||||
/**
|
||||
Initialize builtin data.
|
||||
Initialize builtin data.
|
||||
*/
|
||||
void builtin_init();
|
||||
|
||||
@@ -122,16 +123,17 @@ void builtin_destroy();
|
||||
int builtin_exists( wchar_t *cmd );
|
||||
|
||||
/**
|
||||
Execute a builtin command
|
||||
Execute a builtin command
|
||||
|
||||
\param argv Array containing the command and parameters
|
||||
\param argv Array containing the command and parameters
|
||||
of the builtin. The list is terminated by a
|
||||
null pointer. This syntax resembles the syntax
|
||||
null pointer. This syntax resembles the syntax
|
||||
for exec.
|
||||
\param io the io redirections to perform on this builtin.
|
||||
|
||||
\return the exit status of the builtin command
|
||||
*/
|
||||
int builtin_run( wchar_t **argv );
|
||||
int builtin_run( wchar_t **argv, io_data_t *io );
|
||||
|
||||
/**
|
||||
Insert all builtin names into l. These are not copies of the strings and should not be freed after use.
|
||||
@@ -164,10 +166,11 @@ const wchar_t *builtin_complete_get_temporary_buffer();
|
||||
|
||||
|
||||
/**
|
||||
Return the help text for the specified builtin command.
|
||||
|
||||
\param cmd The command for which to obtain help text
|
||||
Run the __fish_print_help function to obtain the help information
|
||||
for the specified command. The resulting string will be valid until
|
||||
the next time this function is called, and must never be free'd manually.
|
||||
*/
|
||||
|
||||
wchar_t *builtin_help_get( const wchar_t *cmd );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** \file builtin_commandline.c Functions defining the commandline builtin
|
||||
|
||||
Functions used for implementing the commandline builtin.
|
||||
Functions used for implementing the commandline builtin.
|
||||
|
||||
*/
|
||||
#include "config.h"
|
||||
@@ -52,7 +52,15 @@ enum
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Pointer to what the commandline builtin considers to be the current
|
||||
contents of the command line buffer.
|
||||
*/
|
||||
static wchar_t *current_buffer=0;
|
||||
/**
|
||||
What the commandline builtin considers to be the current cursor
|
||||
position.
|
||||
*/
|
||||
static int current_cursor_pos = -1;
|
||||
|
||||
/**
|
||||
@@ -88,20 +96,20 @@ static void replace_part( const wchar_t *begin,
|
||||
const wchar_t *buff = get_buffer();
|
||||
string_buffer_t out;
|
||||
int out_pos=get_cursor_pos();
|
||||
|
||||
|
||||
sb_init( &out );
|
||||
|
||||
sb_append_substring( &out, buff, begin-buff );
|
||||
|
||||
|
||||
switch( append_mode)
|
||||
{
|
||||
case REPLACE_MODE:
|
||||
{
|
||||
|
||||
|
||||
sb_append( &out, insert );
|
||||
out_pos = wcslen( insert ) + (begin-buff);
|
||||
out_pos = wcslen( insert ) + (begin-buff);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
case APPEND_MODE:
|
||||
{
|
||||
@@ -115,7 +123,7 @@ static void replace_part( const wchar_t *begin,
|
||||
sb_append_substring( &out, begin, cursor );
|
||||
sb_append( &out, insert );
|
||||
sb_append_substring( &out, begin+cursor, end-begin-cursor );
|
||||
out_pos += wcslen( insert );
|
||||
out_pos += wcslen( insert );
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -123,7 +131,7 @@ static void replace_part( const wchar_t *begin,
|
||||
reader_set_buffer( (wchar_t *)out.buff, out_pos );
|
||||
sb_destroy( &out );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Output the specified selection.
|
||||
|
||||
@@ -132,11 +140,11 @@ static void replace_part( const wchar_t *begin,
|
||||
\param cut_at_cursor whether printing should stop at the surrent cursor position
|
||||
\param tokenize whether the string should be tokenized, printing one string token on every line and skipping non-string tokens
|
||||
*/
|
||||
static void write_part( const wchar_t *begin,
|
||||
const wchar_t *end,
|
||||
int cut_at_cursor,
|
||||
static void write_part( const wchar_t *begin,
|
||||
const wchar_t *end,
|
||||
int cut_at_cursor,
|
||||
int tokenize )
|
||||
{
|
||||
{
|
||||
tokenizer tok;
|
||||
string_buffer_t out;
|
||||
wchar_t *buff;
|
||||
@@ -149,7 +157,7 @@ static void write_part( const wchar_t *begin,
|
||||
buff = wcsndup( begin, end-begin );
|
||||
// fwprintf( stderr, L"Subshell: %ls, end char %lc\n", buff, *end );
|
||||
sb_init( &out );
|
||||
|
||||
|
||||
for( tok_init( &tok, buff, TOK_ACCEPT_UNFINISHED );
|
||||
tok_has_next( &tok );
|
||||
tok_next( &tok ) )
|
||||
@@ -157,47 +165,45 @@ static void write_part( const wchar_t *begin,
|
||||
if( (cut_at_cursor) &&
|
||||
(tok_get_pos( &tok)+wcslen(tok_last( &tok)) >= pos) )
|
||||
break;
|
||||
|
||||
|
||||
switch( tok_last_type( &tok ) )
|
||||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
wchar_t *tmp = unescape( tok_last( &tok ), UNESCAPE_INCOMPLETE );
|
||||
sb_append2( &out, tmp, L"\n", (void *)0 );
|
||||
sb_append( &out, tmp, L"\n", (void *)0 );
|
||||
free( tmp );
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sb_append( sb_out,
|
||||
(wchar_t *)out.buff );
|
||||
|
||||
|
||||
free( buff );
|
||||
tok_destroy( &tok );
|
||||
sb_destroy( &out );
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *buff, *esc;
|
||||
|
||||
wchar_t *buff;
|
||||
|
||||
if( cut_at_cursor )
|
||||
{
|
||||
end = begin+pos;
|
||||
end = begin+pos;
|
||||
}
|
||||
|
||||
buff = wcsndup( begin, end-begin );
|
||||
esc = unescape( buff, UNESCAPE_INCOMPLETE );
|
||||
|
||||
// debug( 0, L"woot2 %ls -> %ls", buff, esc );
|
||||
|
||||
sb_append( sb_out, esc );
|
||||
sb_append( sb_out, buff );
|
||||
sb_append( sb_out, L"\n" );
|
||||
|
||||
free( esc );
|
||||
|
||||
free( buff );
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,15 +217,17 @@ static int builtin_commandline( wchar_t **argv )
|
||||
|
||||
int buffer_part=0;
|
||||
int cut_at_cursor=0;
|
||||
|
||||
|
||||
int argc = builtin_count_args( argv );
|
||||
int append_mode=0;
|
||||
|
||||
int function_mode = 0;
|
||||
|
||||
int tokenize = 0;
|
||||
|
||||
|
||||
int tokenize = 0;
|
||||
|
||||
int cursor_mode = 0;
|
||||
int line_mode = 0;
|
||||
int search_mode = 0;
|
||||
wchar_t *begin, *end;
|
||||
|
||||
current_buffer = (wchar_t *)builtin_complete_get_temporary_buffer();
|
||||
@@ -235,19 +243,29 @@ static int builtin_commandline( wchar_t **argv )
|
||||
|
||||
if( !get_buffer() )
|
||||
{
|
||||
sb_append2( sb_err,
|
||||
argv[0],
|
||||
L": Can not set commandline in non-interactive mode\n",
|
||||
(void *)0 );
|
||||
if (is_interactive_session)
|
||||
{
|
||||
/*
|
||||
Prompt change requested while we don't have
|
||||
a prompt, most probably while reading the
|
||||
init files. Just ignore it.
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
sb_append( sb_err,
|
||||
argv[0],
|
||||
L": Can not set commandline in non-interactive mode\n",
|
||||
(void *)0 );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
woptind=0;
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
const static struct woption
|
||||
static const struct woption
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
@@ -273,11 +291,11 @@ static int builtin_commandline( wchar_t **argv )
|
||||
{
|
||||
L"current-token", no_argument, 0, 't'
|
||||
}
|
||||
,
|
||||
,
|
||||
{
|
||||
L"current-buffer", no_argument, 0, 'b'
|
||||
}
|
||||
,
|
||||
,
|
||||
{
|
||||
L"cut-at-cursor", no_argument, 0, 'c'
|
||||
}
|
||||
@@ -294,7 +312,7 @@ static int builtin_commandline( wchar_t **argv )
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
{
|
||||
L"input", required_argument, 0, 'I'
|
||||
}
|
||||
,
|
||||
@@ -303,21 +321,29 @@ static int builtin_commandline( wchar_t **argv )
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
L"line", no_argument, 0, 'L'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"search-mode", no_argument, 0, 'S'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
int opt_index = 0;
|
||||
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"aijpctwforhI:C",
|
||||
long_options,
|
||||
argv,
|
||||
L"abijpctwforhI:CLS",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
|
||||
switch( opt )
|
||||
{
|
||||
case 0:
|
||||
@@ -330,11 +356,16 @@ static int builtin_commandline( wchar_t **argv )
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
case L'a':
|
||||
append_mode = APPEND_MODE;
|
||||
break;
|
||||
|
||||
|
||||
case L'b':
|
||||
buffer_part = STRING_MODE;
|
||||
break;
|
||||
|
||||
|
||||
case L'i':
|
||||
append_mode = INSERT_MODE;
|
||||
break;
|
||||
@@ -342,11 +373,11 @@ static int builtin_commandline( wchar_t **argv )
|
||||
case L'r':
|
||||
append_mode = REPLACE_MODE;
|
||||
break;
|
||||
|
||||
|
||||
case 'c':
|
||||
cut_at_cursor=1;
|
||||
break;
|
||||
|
||||
|
||||
case 't':
|
||||
buffer_part = TOKEN_MODE;
|
||||
break;
|
||||
@@ -371,51 +402,59 @@ static int builtin_commandline( wchar_t **argv )
|
||||
current_buffer = woptarg;
|
||||
current_cursor_pos = wcslen( woptarg );
|
||||
break;
|
||||
|
||||
|
||||
case 'C':
|
||||
cursor_mode = 1;
|
||||
break;
|
||||
|
||||
|
||||
case 'L':
|
||||
line_mode = 1;
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
search_mode = 1;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
||||
case L'?':
|
||||
builtin_unknown_option( argv[0], argv[woptind-1] );
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( function_mode )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
/*
|
||||
Check for invalid switch combinations
|
||||
*/
|
||||
if( buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode )
|
||||
if( buffer_part || cut_at_cursor || append_mode || tokenize || cursor_mode || line_mode || search_mode )
|
||||
{
|
||||
sb_printf(sb_err,
|
||||
BUILTIN_ERR_COMBO,
|
||||
argv[0] );
|
||||
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( argc == woptind )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
BUILTIN_ERR_MISSING,
|
||||
argv[0] );
|
||||
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
for( i=woptind; i<argc; i++ )
|
||||
{
|
||||
wint_t c = input_get_code( argv[i] );
|
||||
wint_t c = input_function_get_code( argv[i] );
|
||||
if( c != -1 )
|
||||
{
|
||||
/*
|
||||
@@ -428,24 +467,24 @@ static int builtin_commandline( wchar_t **argv )
|
||||
else
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Unknown readline function '%ls'\n"),
|
||||
argv[0],
|
||||
argv[i] );
|
||||
_(L"%ls: Unknown input function '%ls'\n"),
|
||||
argv[0],
|
||||
argv[i] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Check for invalid switch combinations
|
||||
*/
|
||||
if( cursor_mode && (argc-woptind > 1) )
|
||||
if( (search_mode || line_mode || cursor_mode) && (argc-woptind > 1) )
|
||||
{
|
||||
|
||||
sb_append2( sb_err,
|
||||
|
||||
sb_append( sb_err,
|
||||
argv[0],
|
||||
L": Too many arguments\n",
|
||||
(void *)0 );
|
||||
@@ -453,16 +492,16 @@ static int builtin_commandline( wchar_t **argv )
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( (buffer_part || tokenize || cut_at_cursor) && cursor_mode )
|
||||
{
|
||||
if( (buffer_part || tokenize || cut_at_cursor) && (cursor_mode || line_mode || search_mode) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
BUILTIN_ERR_COMBO,
|
||||
argv[0] );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if( (tokenize || cut_at_cursor) && (argc-woptind) )
|
||||
{
|
||||
@@ -470,7 +509,7 @@ static int builtin_commandline( wchar_t **argv )
|
||||
BUILTIN_ERR_COMBO2,
|
||||
argv[0],
|
||||
L"--cut-at-cursor and --tokenize can not be used when setting the commandline" );
|
||||
|
||||
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
@@ -483,7 +522,7 @@ static int builtin_commandline( wchar_t **argv )
|
||||
argv[0],
|
||||
L"insertion mode switches can not be used when not in insertion mode" );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -494,7 +533,7 @@ static int builtin_commandline( wchar_t **argv )
|
||||
{
|
||||
append_mode = REPLACE_MODE;
|
||||
}
|
||||
|
||||
|
||||
if( !buffer_part )
|
||||
{
|
||||
buffer_part = STRING_MODE;
|
||||
@@ -507,17 +546,17 @@ static int builtin_commandline( wchar_t **argv )
|
||||
wchar_t *endptr;
|
||||
int new_pos;
|
||||
errno = 0;
|
||||
|
||||
|
||||
new_pos = wcstol( argv[woptind], &endptr, 10 );
|
||||
if( *endptr || errno )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
BUILTIN_ERR_NOT_NUMBER,
|
||||
argv[0],
|
||||
argv[woptind] );
|
||||
BUILTIN_ERR_NOT_NUMBER,
|
||||
argv[0],
|
||||
argv[woptind] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
}
|
||||
|
||||
|
||||
current_buffer = reader_get_buffer();
|
||||
new_pos = maxi( 0, mini( new_pos, wcslen( current_buffer ) ) );
|
||||
reader_set_buffer( current_buffer, new_pos );
|
||||
@@ -528,84 +567,98 @@ static int builtin_commandline( wchar_t **argv )
|
||||
sb_printf( sb_out, L"%d\n", reader_get_cursor_pos() );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( line_mode )
|
||||
{
|
||||
int pos = reader_get_cursor_pos();
|
||||
wchar_t *buff = reader_get_buffer();
|
||||
sb_printf( sb_out, L"%d\n", parse_util_lineno( buff, pos ) );
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
if( search_mode )
|
||||
{
|
||||
return !reader_search_mode();
|
||||
}
|
||||
|
||||
|
||||
switch( buffer_part )
|
||||
{
|
||||
case STRING_MODE:
|
||||
{
|
||||
{
|
||||
begin = get_buffer();
|
||||
end = begin+wcslen(begin);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
case PROCESS_MODE:
|
||||
{
|
||||
parse_util_process_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&begin,
|
||||
&end );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case JOB_MODE:
|
||||
{
|
||||
parse_util_job_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&end );
|
||||
break;
|
||||
&end );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case TOKEN_MODE:
|
||||
{
|
||||
parse_util_token_extent( get_buffer(),
|
||||
get_cursor_pos(),
|
||||
&begin,
|
||||
&end,
|
||||
&begin,
|
||||
&end,
|
||||
0, 0 );
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
switch(argc-woptind)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
{
|
||||
write_part( begin, end, cut_at_cursor, tokenize );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 1:
|
||||
{
|
||||
replace_part( begin, end, argv[woptind], append_mode );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
string_buffer_t sb;
|
||||
int i;
|
||||
|
||||
|
||||
sb_init( &sb );
|
||||
|
||||
|
||||
sb_append( &sb, argv[woptind] );
|
||||
|
||||
|
||||
for( i=woptind+1; i<argc; i++ )
|
||||
{
|
||||
sb_append( &sb, L"\n" );
|
||||
sb_append( &sb, argv[i] );
|
||||
}
|
||||
|
||||
|
||||
replace_part( begin, end, (wchar_t *)sb.buff, append_mode );
|
||||
sb_destroy( &sb );
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/** \file builtin_complete.c Functions defining the complete builtin
|
||||
|
||||
Functions used for implementing the complete builtin.
|
||||
Functions used for implementing the complete builtin.
|
||||
|
||||
*/
|
||||
#include "config.h"
|
||||
@@ -28,7 +28,7 @@ Functions used for implementing the complete builtin.
|
||||
/**
|
||||
Internal storage for the builtin_get_temporary_buffer() function.
|
||||
*/
|
||||
const static wchar_t *temporary_buffer;
|
||||
static const wchar_t *temporary_buffer;
|
||||
|
||||
/*
|
||||
builtin_complete_* are a set of rather silly looping functions that
|
||||
@@ -46,18 +46,19 @@ static void builtin_complete_add2( const wchar_t *cmd,
|
||||
int cmd_type,
|
||||
const wchar_t *short_opt,
|
||||
array_list_t *gnu_opt,
|
||||
array_list_t *old_opt,
|
||||
int result_mode,
|
||||
array_list_t *old_opt,
|
||||
int result_mode,
|
||||
const wchar_t *condition,
|
||||
const wchar_t *comp,
|
||||
const wchar_t *desc )
|
||||
const wchar_t *desc,
|
||||
int flags )
|
||||
{
|
||||
int i;
|
||||
const wchar_t *s;
|
||||
|
||||
|
||||
for( s=short_opt; *s; s++ )
|
||||
{
|
||||
complete_add( cmd,
|
||||
complete_add( cmd,
|
||||
cmd_type,
|
||||
*s,
|
||||
0,
|
||||
@@ -65,12 +66,13 @@ static void builtin_complete_add2( const wchar_t *cmd,
|
||||
result_mode,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
desc,
|
||||
flags );
|
||||
}
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( gnu_opt ); i++ )
|
||||
{
|
||||
complete_add( cmd,
|
||||
complete_add( cmd,
|
||||
cmd_type,
|
||||
0,
|
||||
(wchar_t *)al_get(gnu_opt, i ),
|
||||
@@ -78,12 +80,13 @@ static void builtin_complete_add2( const wchar_t *cmd,
|
||||
result_mode,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
desc,
|
||||
flags );
|
||||
}
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( old_opt ); i++ )
|
||||
{
|
||||
complete_add( cmd,
|
||||
complete_add( cmd,
|
||||
cmd_type,
|
||||
0,
|
||||
(wchar_t *)al_get(old_opt, i ),
|
||||
@@ -91,12 +94,13 @@ static void builtin_complete_add2( const wchar_t *cmd,
|
||||
result_mode,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
}
|
||||
desc,
|
||||
flags );
|
||||
}
|
||||
|
||||
if( al_get_count( old_opt )+al_get_count( gnu_opt )+wcslen(short_opt) == 0 )
|
||||
{
|
||||
complete_add( cmd,
|
||||
complete_add( cmd,
|
||||
cmd_type,
|
||||
0,
|
||||
0,
|
||||
@@ -104,67 +108,71 @@ static void builtin_complete_add2( const wchar_t *cmd,
|
||||
result_mode,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
}
|
||||
desc,
|
||||
flags );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Silly function
|
||||
*/
|
||||
static void builtin_complete_add( array_list_t *cmd,
|
||||
static void builtin_complete_add( array_list_t *cmd,
|
||||
array_list_t *path,
|
||||
const wchar_t *short_opt,
|
||||
array_list_t *gnu_opt,
|
||||
array_list_t *old_opt,
|
||||
int result_mode,
|
||||
int authorative,
|
||||
array_list_t *old_opt,
|
||||
int result_mode,
|
||||
int authoritative,
|
||||
const wchar_t *condition,
|
||||
const wchar_t *comp,
|
||||
const wchar_t *desc )
|
||||
const wchar_t *desc,
|
||||
int flags )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( cmd ); i++ )
|
||||
{
|
||||
builtin_complete_add2( al_get( cmd, i ),
|
||||
COMMAND,
|
||||
short_opt,
|
||||
short_opt,
|
||||
gnu_opt,
|
||||
old_opt,
|
||||
result_mode,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
old_opt,
|
||||
result_mode,
|
||||
condition,
|
||||
comp,
|
||||
desc,
|
||||
flags );
|
||||
|
||||
if( authorative != -1 )
|
||||
if( authoritative != -1 )
|
||||
{
|
||||
complete_set_authorative( al_get( cmd, i ),
|
||||
complete_set_authoritative( al_get( cmd, i ),
|
||||
COMMAND,
|
||||
authorative );
|
||||
authoritative );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( path ); i++ )
|
||||
{
|
||||
builtin_complete_add2( al_get( path, i ),
|
||||
PATH,
|
||||
short_opt,
|
||||
short_opt,
|
||||
gnu_opt,
|
||||
old_opt,
|
||||
result_mode,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
old_opt,
|
||||
result_mode,
|
||||
condition,
|
||||
comp,
|
||||
desc,
|
||||
flags );
|
||||
|
||||
if( authorative != -1 )
|
||||
if( authoritative != -1 )
|
||||
{
|
||||
complete_set_authorative( al_get( path, i ),
|
||||
complete_set_authoritative( al_get( path, i ),
|
||||
PATH,
|
||||
authorative );
|
||||
authoritative );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,17 +181,17 @@ static void builtin_complete_add( array_list_t *cmd,
|
||||
static void builtin_complete_remove3( wchar_t *cmd,
|
||||
int cmd_type,
|
||||
wchar_t short_opt,
|
||||
array_list_t *long_opt )
|
||||
array_list_t *long_opt )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( long_opt ); i++ )
|
||||
{
|
||||
complete_remove( cmd,
|
||||
cmd_type,
|
||||
short_opt,
|
||||
(wchar_t *)al_get( long_opt, i ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,7 +214,7 @@ static void builtin_complete_remove2( wchar_t *cmd,
|
||||
cmd_type,
|
||||
*s,
|
||||
0 );
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -231,42 +239,42 @@ static void builtin_complete_remove2( wchar_t *cmd,
|
||||
cmd_type,
|
||||
0,
|
||||
old_opt );
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Silly function
|
||||
*/
|
||||
static void builtin_complete_remove( array_list_t *cmd,
|
||||
static void builtin_complete_remove( array_list_t *cmd,
|
||||
array_list_t *path,
|
||||
const wchar_t *short_opt,
|
||||
array_list_t *gnu_opt,
|
||||
array_list_t *old_opt )
|
||||
{
|
||||
|
||||
|
||||
int i;
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( cmd ); i++ )
|
||||
{
|
||||
builtin_complete_remove2( (wchar_t *)al_get( cmd, i ),
|
||||
COMMAND,
|
||||
short_opt,
|
||||
short_opt,
|
||||
gnu_opt,
|
||||
old_opt );
|
||||
}
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( path ); i++ )
|
||||
{
|
||||
builtin_complete_remove2( (wchar_t *)al_get( path, i ),
|
||||
PATH,
|
||||
short_opt,
|
||||
short_opt,
|
||||
gnu_opt,
|
||||
old_opt );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -286,61 +294,57 @@ static int builtin_complete( wchar_t **argv )
|
||||
int argc=0;
|
||||
int result_mode=SHARED;
|
||||
int remove = 0;
|
||||
int authorative = -1;
|
||||
|
||||
int authoritative = -1;
|
||||
int flags = COMPLETE_AUTO_SPACE;
|
||||
|
||||
string_buffer_t short_opt;
|
||||
array_list_t gnu_opt, old_opt;
|
||||
wchar_t *comp=L"", *desc=L"", *condition=L"";
|
||||
|
||||
wchar_t *do_complete = 0;
|
||||
|
||||
|
||||
array_list_t cmd;
|
||||
array_list_t path;
|
||||
|
||||
static int recursion_level=0;
|
||||
|
||||
if( !is_interactive_session )
|
||||
{
|
||||
debug( 1, _(L"%ls: Command only available in interactive sessions"), argv[0] );
|
||||
}
|
||||
|
||||
|
||||
al_init( &cmd );
|
||||
al_init( &path );
|
||||
sb_init( &short_opt );
|
||||
al_init( &gnu_opt );
|
||||
al_init( &old_opt );
|
||||
|
||||
argc = builtin_count_args( argv );
|
||||
|
||||
|
||||
argc = builtin_count_args( argv );
|
||||
|
||||
woptind=0;
|
||||
|
||||
|
||||
while( res == 0 )
|
||||
{
|
||||
const static struct woption
|
||||
static const struct woption
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
L"exclusive", no_argument, 0, 'x'
|
||||
L"exclusive", no_argument, 0, 'x'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"no-files", no_argument, 0, 'f'
|
||||
L"no-files", no_argument, 0, 'f'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"require-parameter", no_argument, 0, 'r'
|
||||
L"require-parameter", no_argument, 0, 'r'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"path", required_argument, 0, 'p'
|
||||
}
|
||||
,
|
||||
,
|
||||
{
|
||||
L"command", required_argument, 0, 'c'
|
||||
L"command", required_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
,
|
||||
{
|
||||
L"short-option", required_argument, 0, 's'
|
||||
L"short-option", required_argument, 0, 's'
|
||||
}
|
||||
,
|
||||
{
|
||||
@@ -348,7 +352,7 @@ static int builtin_complete( wchar_t **argv )
|
||||
}
|
||||
,
|
||||
{
|
||||
L"old-option", required_argument, 0, 'o'
|
||||
L"old-option", required_argument, 0, 'o'
|
||||
}
|
||||
,
|
||||
{
|
||||
@@ -364,11 +368,11 @@ static int builtin_complete( wchar_t **argv )
|
||||
}
|
||||
,
|
||||
{
|
||||
L"unauthorative", no_argument, 0, 'u'
|
||||
L"unauthoritative", no_argument, 0, 'u'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"authorative", no_argument, 0, 'A'
|
||||
L"authoritative", no_argument, 0, 'A'
|
||||
}
|
||||
,
|
||||
{
|
||||
@@ -383,22 +387,22 @@ static int builtin_complete( wchar_t **argv )
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
int opt_index = 0;
|
||||
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"a:c:p:s:l:o:d:frxeuAn:C::h",
|
||||
long_options,
|
||||
argv,
|
||||
L"a:c:p:s:l:o:d:frxeuAn:C::h",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
|
||||
switch( opt )
|
||||
{
|
||||
case 0:
|
||||
@@ -410,23 +414,23 @@ static int builtin_complete( wchar_t **argv )
|
||||
long_options[opt_index].name );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
|
||||
|
||||
res = 1;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
|
||||
case 'x':
|
||||
result_mode |= EXCLUSIVE;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
|
||||
case 'f':
|
||||
result_mode |= NO_FILES;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
|
||||
case 'r':
|
||||
result_mode |= NO_COMMON;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
|
||||
case 'p':
|
||||
case 'c':
|
||||
{
|
||||
wchar_t *a = unescape( woptarg, 1);
|
||||
@@ -437,31 +441,31 @@ static int builtin_complete( wchar_t **argv )
|
||||
else
|
||||
{
|
||||
sb_printf( sb_err, L"%ls: Invalid token '%ls'\n", argv[0], woptarg );
|
||||
res = 1;
|
||||
}
|
||||
res = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'd':
|
||||
desc = woptarg;
|
||||
break;
|
||||
|
||||
|
||||
case 'u':
|
||||
authorative=0;
|
||||
authoritative=0;
|
||||
break;
|
||||
|
||||
|
||||
case 'A':
|
||||
authorative=1;
|
||||
authoritative=1;
|
||||
break;
|
||||
|
||||
|
||||
case 's':
|
||||
sb_append( &short_opt, woptarg );
|
||||
break;
|
||||
|
||||
|
||||
case 'l':
|
||||
al_push( &gnu_opt, woptarg );
|
||||
break;
|
||||
|
||||
|
||||
case 'o':
|
||||
al_push( &old_opt, woptarg );
|
||||
break;
|
||||
@@ -469,7 +473,7 @@ static int builtin_complete( wchar_t **argv )
|
||||
case 'a':
|
||||
comp = woptarg;
|
||||
break;
|
||||
|
||||
|
||||
case 'e':
|
||||
remove = 1;
|
||||
break;
|
||||
@@ -477,22 +481,22 @@ static int builtin_complete( wchar_t **argv )
|
||||
case 'n':
|
||||
condition = woptarg;
|
||||
break;
|
||||
|
||||
|
||||
case 'C':
|
||||
do_complete = woptarg?woptarg:reader_get_buffer();
|
||||
break;
|
||||
|
||||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
||||
|
||||
case '?':
|
||||
builtin_unknown_option( argv[0], argv[woptind-1] );
|
||||
res = 1;
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if( !res )
|
||||
@@ -502,17 +506,17 @@ static int builtin_complete( wchar_t **argv )
|
||||
if( parser_test( condition, 0, 0, 0 ) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
L"%ls: Condition '%ls' contained a syntax error\n",
|
||||
L"%ls: Condition '%ls' contained a syntax error\n",
|
||||
argv[0],
|
||||
condition );
|
||||
|
||||
|
||||
parser_test( condition, 0, sb_err, argv[0] );
|
||||
|
||||
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( !res )
|
||||
{
|
||||
if( comp && wcslen( comp ) )
|
||||
@@ -520,12 +524,12 @@ static int builtin_complete( wchar_t **argv )
|
||||
if( parser_test_args( comp, 0, 0 ) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
L"%ls: Completion '%ls' contained a syntax error\n",
|
||||
L"%ls: Completion '%ls' contained a syntax error\n",
|
||||
argv[0],
|
||||
comp );
|
||||
|
||||
|
||||
parser_test_args( comp, sb_err, argv[0] );
|
||||
|
||||
|
||||
res = 1;
|
||||
}
|
||||
}
|
||||
@@ -535,40 +539,60 @@ static int builtin_complete( wchar_t **argv )
|
||||
{
|
||||
if( do_complete )
|
||||
{
|
||||
array_list_t comp;
|
||||
array_list_t *comp;
|
||||
int i;
|
||||
|
||||
const wchar_t *prev_temporary_buffer = temporary_buffer;
|
||||
temporary_buffer = do_complete;
|
||||
|
||||
wchar_t *token;
|
||||
|
||||
parse_util_token_extent( do_complete, wcslen( do_complete ), &token, 0, 0, 0 );
|
||||
|
||||
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++ )
|
||||
|
||||
comp = al_halloc( 0 );
|
||||
|
||||
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 );
|
||||
completion_t *next = (completion_t *)al_get( comp, i );
|
||||
wchar_t *prepend;
|
||||
|
||||
if( next->flags & COMPLETE_NO_CASE )
|
||||
{
|
||||
prepend = L"";
|
||||
}
|
||||
else
|
||||
{
|
||||
prepend = token;
|
||||
}
|
||||
|
||||
|
||||
if( next->description )
|
||||
{
|
||||
sb_printf( sb_out, L"%ls%ls\t%ls\n", prepend, next->completion, next->description );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_printf( sb_out, L"%ls%ls\n", prepend, next->completion );
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &comp, &free );
|
||||
al_destroy( &comp );
|
||||
|
||||
halloc_free( comp );
|
||||
recursion_level--;
|
||||
}
|
||||
|
||||
temporary_buffer = prev_temporary_buffer;
|
||||
|
||||
|
||||
temporary_buffer = prev_temporary_buffer;
|
||||
|
||||
}
|
||||
else if( woptind != argc )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
sb_printf( sb_err,
|
||||
_( L"%ls: Too many arguments\n" ),
|
||||
argv[0] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
@@ -579,7 +603,7 @@ static int builtin_complete( wchar_t **argv )
|
||||
{
|
||||
/* No arguments specified, meaning we print the definitions of
|
||||
* all specified completions to stdout.*/
|
||||
complete_print( sb_out );
|
||||
complete_print( sb_out );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -589,25 +613,26 @@ static int builtin_complete( wchar_t **argv )
|
||||
&path,
|
||||
(wchar_t *)short_opt.buff,
|
||||
&gnu_opt,
|
||||
&old_opt );
|
||||
&old_opt );
|
||||
}
|
||||
else
|
||||
{
|
||||
builtin_complete_add( &cmd,
|
||||
builtin_complete_add( &cmd,
|
||||
&path,
|
||||
(wchar_t *)short_opt.buff,
|
||||
&gnu_opt,
|
||||
&old_opt,
|
||||
result_mode,
|
||||
authorative,
|
||||
&old_opt,
|
||||
result_mode,
|
||||
authoritative,
|
||||
condition,
|
||||
comp,
|
||||
desc );
|
||||
desc,
|
||||
flags );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
al_foreach( &cmd, &free );
|
||||
al_foreach( &path, &free );
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ static void builtin_jobs_print( job_t *j, int mode, int header )
|
||||
#ifdef HAVE__PROC_SELF_STAT
|
||||
sb_printf( sb_out, L"%d%%\t", cpu_use(j) );
|
||||
#endif
|
||||
sb_append2( sb_out,
|
||||
sb_append( sb_out,
|
||||
job_is_stopped(j)?_(L"stopped"):_(L"running"),
|
||||
L"\t",
|
||||
j->command,
|
||||
@@ -173,7 +173,7 @@ static int builtin_jobs( wchar_t **argv )
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
const static struct woption
|
||||
static const struct woption
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
@@ -248,7 +248,7 @@ static int builtin_jobs( wchar_t **argv )
|
||||
|
||||
case 'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
case '?':
|
||||
builtin_unknown_option( argv[0], argv[woptind-1] );
|
||||
|
||||
321
builtin_set.c
321
builtin_set.c
@@ -1,6 +1,6 @@
|
||||
/** \file builtin_set.c Functions defining the set builtin
|
||||
|
||||
Functions used for implementing the set builtin.
|
||||
Functions used for implementing the set builtin.
|
||||
|
||||
*/
|
||||
#include "config.h"
|
||||
@@ -46,10 +46,9 @@ Functions used for implementing the set builtin.
|
||||
*/
|
||||
static int is_path_variable( const wchar_t *env )
|
||||
{
|
||||
return contains_str( env,
|
||||
return contains( env,
|
||||
L"PATH",
|
||||
L"CDPATH",
|
||||
(void *)0 );
|
||||
L"CDPATH" );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,19 +61,19 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
|
||||
int i;
|
||||
int retcode = 0;
|
||||
wchar_t *val_str=0;
|
||||
|
||||
|
||||
if( is_path_variable( key ) )
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( val ); i++ )
|
||||
{
|
||||
int show_perror = 0;
|
||||
int show_hint = 0;
|
||||
|
||||
|
||||
struct stat buff;
|
||||
wchar_t *dir = (wchar_t *)al_get( val, i );
|
||||
|
||||
|
||||
if( wstat( dir, &buff ) )
|
||||
{
|
||||
error = 1;
|
||||
@@ -84,55 +83,55 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
|
||||
if( !( S_ISDIR(buff.st_mode) ) )
|
||||
{
|
||||
error = 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if( error )
|
||||
{
|
||||
wchar_t *colon;
|
||||
|
||||
sb_printf( sb_err,
|
||||
|
||||
sb_printf( sb_err,
|
||||
_(BUILTIN_SET_PATH_ERROR),
|
||||
L"set",
|
||||
dir,
|
||||
L"set",
|
||||
dir,
|
||||
key );
|
||||
|
||||
|
||||
colon = wcschr( dir, L':' );
|
||||
|
||||
if( colon && *(colon+1) )
|
||||
|
||||
if( colon && *(colon+1) )
|
||||
{
|
||||
show_hint = 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if( show_perror )
|
||||
{
|
||||
builtin_wperror( L"set" );
|
||||
}
|
||||
|
||||
|
||||
if( show_hint )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
sb_printf( sb_err,
|
||||
_(BUILTIN_SET_PATH_HINT),
|
||||
L"set",
|
||||
key,
|
||||
key,
|
||||
wcschr( dir, L':' )+1);
|
||||
}
|
||||
|
||||
|
||||
if( error )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if( error )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
sb_init( &sb );
|
||||
@@ -149,9 +148,9 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
|
||||
}
|
||||
}
|
||||
val_str = (wchar_t *)sb.buff;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
switch( env_set( key, val_str, scope | ENV_USER ) )
|
||||
{
|
||||
case ENV_PERM:
|
||||
@@ -160,7 +159,7 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
|
||||
retcode=1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case ENV_INVALID:
|
||||
{
|
||||
sb_printf( sb_err, _(L"%ls: Unknown error"), L"set" );
|
||||
@@ -174,13 +173,13 @@ static int my_env_set( const wchar_t *key, array_list_t *val, int scope )
|
||||
return retcode;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
Extract indexes from a destination argument of the form name[index1 index2...]
|
||||
|
||||
\param indexes the list to insert the new indexes into
|
||||
\param src the source string to parse
|
||||
\param name the name of the element. Return null if the name in \c src does not match this name
|
||||
\param var_count the number of elements in the array to parse.
|
||||
\param var_count the number of elements in the array to parse.
|
||||
|
||||
\return the total number of indexes parsed, or -1 on error
|
||||
*/
|
||||
@@ -190,57 +189,57 @@ static int parse_index( array_list_t *indexes,
|
||||
int var_count )
|
||||
{
|
||||
int len;
|
||||
|
||||
|
||||
int count = 0;
|
||||
const wchar_t *src_orig = src;
|
||||
|
||||
|
||||
if (src == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
while (*src != L'\0' && (iswalnum(*src) || *src == L'_'))
|
||||
{
|
||||
src++;
|
||||
}
|
||||
|
||||
|
||||
if (*src != L'[')
|
||||
{
|
||||
sb_printf( sb_err, _(BUILTIN_SET_ARG_COUNT), L"set" );
|
||||
sb_printf( sb_err, _(BUILTIN_SET_ARG_COUNT), L"set" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
len = src-src_orig;
|
||||
|
||||
|
||||
if( (wcsncmp( src_orig, name, len )!=0) || (wcslen(name) != (len)) )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Multiple variable names specified in single call (%ls and %.*ls)\n"),
|
||||
L"set",
|
||||
L"set",
|
||||
name,
|
||||
len,
|
||||
src_orig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
src++;
|
||||
src++;
|
||||
|
||||
while (iswspace(*src))
|
||||
while (iswspace(*src))
|
||||
{
|
||||
src++;
|
||||
}
|
||||
|
||||
while (*src != L']')
|
||||
|
||||
while (*src != L']')
|
||||
{
|
||||
wchar_t *end;
|
||||
|
||||
|
||||
long l_ind;
|
||||
|
||||
errno = 0;
|
||||
|
||||
|
||||
l_ind = wcstol(src, &end, 10);
|
||||
|
||||
if( end==src || errno )
|
||||
|
||||
if( end==src || errno )
|
||||
{
|
||||
sb_printf(sb_err, _(L"%ls: Invalid index starting at '%ls'\n"), L"set", src);
|
||||
return 0;
|
||||
@@ -250,7 +249,7 @@ static int parse_index( array_list_t *indexes,
|
||||
{
|
||||
l_ind = var_count+l_ind+1;
|
||||
}
|
||||
|
||||
|
||||
al_push_long(indexes, l_ind);
|
||||
src = end;
|
||||
count++;
|
||||
@@ -269,14 +268,14 @@ static int parse_index( array_list_t *indexes,
|
||||
|
||||
\return 0 if the operation was successfull, non-zero otherwise
|
||||
*/
|
||||
static int update_values( array_list_t *list,
|
||||
static int update_values( array_list_t *list,
|
||||
array_list_t *indexes,
|
||||
array_list_t *values )
|
||||
array_list_t *values )
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Replace values where needed */
|
||||
for( i = 0; i < al_get_count(indexes); i++ )
|
||||
for( i = 0; i < al_get_count(indexes); i++ )
|
||||
{
|
||||
/*
|
||||
The '- 1' below is because the indices in fish are
|
||||
@@ -288,11 +287,11 @@ static int update_values( array_list_t *list,
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
free((void *) al_get(list, ind));
|
||||
al_set(list, ind, new != 0 ? wcsdup(new) : wcsdup(L""));
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -306,42 +305,42 @@ static int al_contains_long( array_list_t *list,
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
{
|
||||
long current = al_get_long(list, i);
|
||||
if( current != 0 && current == val )
|
||||
if( current != 0 && current == val )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Erase from a list values at specified indexes
|
||||
Erase from a list values at specified indexes
|
||||
*/
|
||||
static void erase_values(array_list_t *list, array_list_t *indexes)
|
||||
static void erase_values(array_list_t *list, array_list_t *indexes)
|
||||
{
|
||||
long i;
|
||||
array_list_t result;
|
||||
|
||||
al_init(&result);
|
||||
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
for (i = 0; i < al_get_count(list); i++)
|
||||
{
|
||||
if (!al_contains_long(indexes, i + 1))
|
||||
if (!al_contains_long(indexes, i + 1))
|
||||
{
|
||||
al_push(&result, al_get(list, i));
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
free( (void *)al_get(list, i));
|
||||
}
|
||||
}
|
||||
|
||||
al_truncate(list,0);
|
||||
|
||||
al_truncate(list,0);
|
||||
al_push_all( list, &result );
|
||||
al_destroy(&result);
|
||||
}
|
||||
@@ -351,31 +350,31 @@ static void erase_values(array_list_t *list, array_list_t *indexes)
|
||||
Print the names of all environment variables in the scope, with or without values,
|
||||
with or without escaping
|
||||
*/
|
||||
static void print_variables(int include_values, int esc, int scope)
|
||||
static void print_variables(int include_values, int esc, int scope)
|
||||
{
|
||||
array_list_t names;
|
||||
int i;
|
||||
|
||||
|
||||
al_init( &names );
|
||||
env_get_names( &names, scope );
|
||||
|
||||
|
||||
sort_list( &names );
|
||||
|
||||
|
||||
for( i = 0; i < al_get_count(&names); i++ )
|
||||
{
|
||||
wchar_t *key = (wchar_t *)al_get( &names, i );
|
||||
wchar_t *e_key = esc ? escape(key, 0) : wcsdup(key);
|
||||
|
||||
sb_append(sb_out, e_key);
|
||||
|
||||
if( include_values )
|
||||
|
||||
if( include_values )
|
||||
{
|
||||
wchar_t *value = env_get(key);
|
||||
wchar_t *e_value;
|
||||
if( value )
|
||||
{
|
||||
int shorten = 0;
|
||||
|
||||
|
||||
if( wcslen( value ) > 64 )
|
||||
{
|
||||
shorten = 1;
|
||||
@@ -385,12 +384,12 @@ static void print_variables(int include_values, int esc, int scope)
|
||||
DIE_MEM();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
e_value = esc ? expand_escape_variable(value) : wcsdup(value);
|
||||
|
||||
sb_append2(sb_out, L" ", e_value, (void *)0);
|
||||
|
||||
sb_append(sb_out, L" ", e_value, (void *)0);
|
||||
free(e_value);
|
||||
|
||||
|
||||
if( shorten )
|
||||
{
|
||||
sb_append(sb_out, L"\u2026");
|
||||
@@ -399,7 +398,7 @@ static void print_variables(int include_values, int esc, int scope)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sb_append(sb_out, L"\n");
|
||||
free(e_key);
|
||||
}
|
||||
@@ -412,57 +411,57 @@ static void print_variables(int include_values, int esc, int scope)
|
||||
The set builtin. Creates, updates and erases environment variables
|
||||
and environemnt variable arrays.
|
||||
*/
|
||||
static int builtin_set( wchar_t **argv )
|
||||
static int builtin_set( wchar_t **argv )
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
Variables used for parsing the argument list
|
||||
*/
|
||||
const static struct woption
|
||||
long_options[] =
|
||||
static const struct woption
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
L"export", no_argument, 0, 'x'
|
||||
{
|
||||
L"export", no_argument, 0, 'x'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"global", no_argument, 0, 'g'
|
||||
{
|
||||
L"global", no_argument, 0, 'g'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"local", no_argument, 0, 'l'
|
||||
{
|
||||
L"local", no_argument, 0, 'l'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"erase", no_argument, 0, 'e'
|
||||
{
|
||||
L"erase", no_argument, 0, 'e'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"names", no_argument, 0, 'n'
|
||||
}
|
||||
{
|
||||
L"names", no_argument, 0, 'n'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"unexport", no_argument, 0, 'u'
|
||||
}
|
||||
{
|
||||
L"unexport", no_argument, 0, 'u'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"universal", no_argument, 0, 'U'
|
||||
}
|
||||
{
|
||||
L"universal", no_argument, 0, 'U'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"query", no_argument, 0, 'q'
|
||||
}
|
||||
{
|
||||
L"query", no_argument, 0, 'q'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
const wchar_t *short_options = L"+xglenuUqh";
|
||||
|
||||
int argc = builtin_count_args(argv);
|
||||
@@ -473,7 +472,7 @@ static int builtin_set( wchar_t **argv )
|
||||
int local = 0, global = 0, export = 0;
|
||||
int erase = 0, list = 0, unexport=0;
|
||||
int universal = 0, query=0;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Variables used for performing the actual work
|
||||
@@ -483,22 +482,22 @@ static int builtin_set( wchar_t **argv )
|
||||
int scope;
|
||||
int slice=0;
|
||||
int i;
|
||||
|
||||
|
||||
wchar_t *bad_char;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Parse options to obtain the requested operation and the modifiers */
|
||||
woptind = 0;
|
||||
while (1)
|
||||
while (1)
|
||||
{
|
||||
int c = wgetopt_long(argc, argv, short_options, long_options, 0);
|
||||
|
||||
if (c == -1)
|
||||
if (c == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
switch(c)
|
||||
|
||||
switch(c)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
@@ -562,18 +561,18 @@ static int builtin_set( wchar_t **argv )
|
||||
sb_printf(sb_err,
|
||||
BUILTIN_ERR_COMBO,
|
||||
argv[0] );
|
||||
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* We can't both list and erase varaibles */
|
||||
if( erase && list )
|
||||
if( erase && list )
|
||||
{
|
||||
sb_printf(sb_err,
|
||||
BUILTIN_ERR_COMBO,
|
||||
argv[0] );
|
||||
argv[0] );
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
@@ -582,7 +581,7 @@ static int builtin_set( wchar_t **argv )
|
||||
/*
|
||||
Variables can only have one scope
|
||||
*/
|
||||
if( local + global + universal > 1 )
|
||||
if( local + global + universal > 1 )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
BUILTIN_ERR_GLOCAL,
|
||||
@@ -594,7 +593,7 @@ static int builtin_set( wchar_t **argv )
|
||||
/*
|
||||
Variables can only have one export status
|
||||
*/
|
||||
if( export && unexport )
|
||||
if( export && unexport )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
BUILTIN_ERR_EXPUNEXP,
|
||||
@@ -606,7 +605,7 @@ static int builtin_set( wchar_t **argv )
|
||||
/*
|
||||
Calculate the scope value for variable assignement
|
||||
*/
|
||||
scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (export ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER;
|
||||
scope = (local ? ENV_LOCAL : 0) | (global ? ENV_GLOBAL : 0) | (export ? ENV_EXPORT : 0) | (unexport ? ENV_UNEXPORT : 0) | (universal ? ENV_UNIVERSAL:0) | ENV_USER;
|
||||
|
||||
if( query )
|
||||
{
|
||||
@@ -622,7 +621,7 @@ static int builtin_set( wchar_t **argv )
|
||||
|
||||
if( !(dest = wcsdup(arg)))
|
||||
{
|
||||
DIE_MEM();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
if( wcschr( dest, L'[' ) )
|
||||
@@ -630,18 +629,18 @@ static int builtin_set( wchar_t **argv )
|
||||
slice = 1;
|
||||
*wcschr( dest, L'[' )=0;
|
||||
}
|
||||
|
||||
|
||||
if( slice )
|
||||
{
|
||||
array_list_t indexes;
|
||||
array_list_t result;
|
||||
int j;
|
||||
|
||||
|
||||
al_init( &result );
|
||||
al_init( &indexes );
|
||||
|
||||
tokenize_variable_array( env_get( dest ), &result );
|
||||
|
||||
|
||||
if( !parse_index( &indexes, arg, dest, al_get_count( &result ) ) )
|
||||
{
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
@@ -664,32 +663,32 @@ static int builtin_set( wchar_t **argv )
|
||||
retcode++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free( dest );
|
||||
|
||||
|
||||
}
|
||||
return retcode;
|
||||
}
|
||||
|
||||
if( list )
|
||||
|
||||
if( list )
|
||||
{
|
||||
/* Maybe we should issue an error if there are any other arguments? */
|
||||
print_variables(0, 0, scope);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( woptind == argc )
|
||||
{
|
||||
/*
|
||||
Print values of variables
|
||||
*/
|
||||
|
||||
if( erase )
|
||||
if( erase )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Erase needs a variable name\n%ls\n"),
|
||||
_(L"%ls: Erase needs a variable name\n%ls\n"),
|
||||
argv[0] );
|
||||
|
||||
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
}
|
||||
@@ -697,13 +696,13 @@ static int builtin_set( wchar_t **argv )
|
||||
{
|
||||
print_variables( 1, 1, scope );
|
||||
}
|
||||
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
||||
if( !(dest = wcsdup(argv[woptind])))
|
||||
{
|
||||
DIE_MEM();
|
||||
DIE_MEM();
|
||||
}
|
||||
|
||||
if( wcschr( dest, L'[' ) )
|
||||
@@ -711,7 +710,7 @@ static int builtin_set( wchar_t **argv )
|
||||
slice = 1;
|
||||
*wcschr( dest, L'[' )=0;
|
||||
}
|
||||
|
||||
|
||||
if( !wcslen( dest ) )
|
||||
{
|
||||
free( dest );
|
||||
@@ -719,7 +718,7 @@ static int builtin_set( wchar_t **argv )
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if( (bad_char = wcsvarname( dest ) ) )
|
||||
{
|
||||
sb_printf( sb_err, BUILTIN_ERR_VARCHAR, argv[0], *bad_char );
|
||||
@@ -727,7 +726,7 @@ static int builtin_set( wchar_t **argv )
|
||||
free( dest );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if( slice && erase && (scope != ENV_USER) )
|
||||
{
|
||||
free( dest );
|
||||
@@ -735,12 +734,12 @@ static int builtin_set( wchar_t **argv )
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
set assignment can work in two modes, either using slices or
|
||||
using the whole array. We detect which mode is used here.
|
||||
*/
|
||||
|
||||
|
||||
if( slice )
|
||||
{
|
||||
|
||||
@@ -751,22 +750,22 @@ static int builtin_set( wchar_t **argv )
|
||||
array_list_t values;
|
||||
array_list_t indexes;
|
||||
array_list_t result;
|
||||
|
||||
|
||||
al_init(&values);
|
||||
al_init(&indexes);
|
||||
al_init(&result);
|
||||
|
||||
|
||||
tokenize_variable_array( env_get(dest), &result );
|
||||
|
||||
|
||||
for( ; woptind<argc; woptind++ )
|
||||
{
|
||||
{
|
||||
if( !parse_index( &indexes, argv[woptind], dest, al_get_count( &result ) ) )
|
||||
{
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
retcode = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
val_count = argc-woptind-1;
|
||||
idx_count = al_get_count( &indexes );
|
||||
|
||||
@@ -785,7 +784,7 @@ static int builtin_set( wchar_t **argv )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !retcode )
|
||||
{
|
||||
@@ -803,12 +802,12 @@ static int builtin_set( wchar_t **argv )
|
||||
array_list_t value;
|
||||
al_init(&value);
|
||||
|
||||
while( woptind < argc )
|
||||
while( woptind < argc )
|
||||
{
|
||||
al_push(&value, argv[woptind++]);
|
||||
}
|
||||
|
||||
if( update_values( &result,
|
||||
if( update_values( &result,
|
||||
&indexes,
|
||||
&value ) )
|
||||
{
|
||||
@@ -816,14 +815,14 @@ static int builtin_set( wchar_t **argv )
|
||||
sb_printf( sb_err, ARRAY_BOUNDS_ERR );
|
||||
sb_append( sb_err, L"\n" );
|
||||
}
|
||||
|
||||
|
||||
my_env_set(dest,
|
||||
&result,
|
||||
scope);
|
||||
|
||||
|
||||
al_destroy( &value );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
al_foreach( &result, &free );
|
||||
@@ -831,12 +830,12 @@ static int builtin_set( wchar_t **argv )
|
||||
|
||||
al_destroy(&indexes);
|
||||
al_destroy(&values);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
woptind++;
|
||||
|
||||
|
||||
/*
|
||||
No slicing
|
||||
*/
|
||||
@@ -844,7 +843,7 @@ static int builtin_set( wchar_t **argv )
|
||||
{
|
||||
if( woptind != argc )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
sb_printf( sb_err,
|
||||
_(L"%ls: Values cannot be specfied with erase\n"),
|
||||
argv[0] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
@@ -859,21 +858,21 @@ static int builtin_set( wchar_t **argv )
|
||||
{
|
||||
array_list_t val;
|
||||
al_init( &val );
|
||||
|
||||
|
||||
for( i=woptind; i<argc; i++ )
|
||||
{
|
||||
al_push( &val, argv[i] );
|
||||
}
|
||||
|
||||
retcode = my_env_set( dest, &val, scope );
|
||||
|
||||
al_destroy( &val );
|
||||
|
||||
}
|
||||
|
||||
al_destroy( &val );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free( dest );
|
||||
|
||||
|
||||
return retcode;
|
||||
|
||||
}
|
||||
|
||||
140
builtin_ulimit.c
140
builtin_ulimit.c
@@ -1,6 +1,6 @@
|
||||
/** \file builtin_ulimit.c Functions defining the ulimit builtin
|
||||
|
||||
Functions used for implementing the ulimit builtin.
|
||||
Functions used for implementing the ulimit builtin.
|
||||
|
||||
*/
|
||||
#include "config.h"
|
||||
@@ -38,18 +38,18 @@ struct resource_t
|
||||
/**
|
||||
Switch used on commandline to specify resource
|
||||
*/
|
||||
wchar_t switch_char;
|
||||
wchar_t switch_char;
|
||||
/**
|
||||
The implicit multiplier used when setting getting values
|
||||
*/
|
||||
int multiplier;
|
||||
int multiplier;
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Array of resource_t structs, describing all known resource types.
|
||||
*/
|
||||
const static struct resource_t resource_arr[] =
|
||||
static const struct resource_t resource_arr[] =
|
||||
{
|
||||
{
|
||||
RLIMIT_CORE, L"Maximum size of core files created", L'c', 1024
|
||||
@@ -96,7 +96,7 @@ const static struct resource_t resource_arr[] =
|
||||
#ifdef RLIMIT_AS
|
||||
{
|
||||
RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024
|
||||
}
|
||||
}
|
||||
,
|
||||
#endif
|
||||
{
|
||||
@@ -111,7 +111,7 @@ const static struct resource_t resource_arr[] =
|
||||
static int get_multiplier( int what )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i=0; resource_arr[i].desc; i++ )
|
||||
{
|
||||
if( resource_arr[i].resource == what )
|
||||
@@ -130,9 +130,9 @@ static int get_multiplier( int what )
|
||||
static rlim_t get( int resource, int hard )
|
||||
{
|
||||
struct rlimit ls;
|
||||
|
||||
|
||||
getrlimit( resource, &ls );
|
||||
|
||||
|
||||
return hard ? ls.rlim_max:ls.rlim_cur;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ static void print( int resource, int hard )
|
||||
sb_append( sb_out, L"unlimited\n" );
|
||||
else
|
||||
sb_printf( sb_out, L"%d\n", l / get_multiplier( resource ) );
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,12 +157,12 @@ static void print_all( int hard )
|
||||
{
|
||||
int i;
|
||||
int w=0;
|
||||
|
||||
|
||||
for( i=0; resource_arr[i].desc; i++ )
|
||||
{
|
||||
w=maxi( w, my_wcswidth(resource_arr[i].desc));
|
||||
}
|
||||
|
||||
|
||||
for( i=0; resource_arr[i].desc; i++ )
|
||||
{
|
||||
struct rlimit ls;
|
||||
@@ -171,14 +171,14 @@ static void print_all( int hard )
|
||||
l = hard ? ls.rlim_max:ls.rlim_cur;
|
||||
|
||||
wchar_t *unit = ((resource_arr[i].resource==RLIMIT_CPU)?L"(seconds, ":(get_multiplier(resource_arr[i].resource)==1?L"(":L"(kB, "));
|
||||
|
||||
|
||||
sb_printf( sb_out,
|
||||
L"%-*ls %10ls-%lc) ",
|
||||
w,
|
||||
resource_arr[i].desc,
|
||||
L"%-*ls %10ls-%lc) ",
|
||||
w,
|
||||
resource_arr[i].desc,
|
||||
unit,
|
||||
resource_arr[i].switch_char);
|
||||
|
||||
|
||||
if( l == RLIM_INFINITY )
|
||||
{
|
||||
sb_append( sb_out, L"unlimited\n" );
|
||||
@@ -188,7 +188,7 @@ static void print_all( int hard )
|
||||
sb_printf( sb_out, L"%d\n", l/get_multiplier(resource_arr[i].resource) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,7 +197,7 @@ static void print_all( int hard )
|
||||
static const wchar_t *get_desc( int what )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i=0; resource_arr[i].desc; i++ )
|
||||
{
|
||||
if( resource_arr[i].resource == what )
|
||||
@@ -217,26 +217,26 @@ static int set( int resource, int hard, int soft, rlim_t value )
|
||||
{
|
||||
struct rlimit ls;
|
||||
getrlimit( resource, &ls );
|
||||
|
||||
|
||||
if( hard )
|
||||
{
|
||||
ls.rlim_max = value;
|
||||
}
|
||||
|
||||
|
||||
if( soft )
|
||||
{
|
||||
ls.rlim_cur = value;
|
||||
|
||||
|
||||
/*
|
||||
Do not attempt to set the soft limit higher than the hard limit
|
||||
*/
|
||||
if( ( value == RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY ) ||
|
||||
if( ( value == RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY ) ||
|
||||
( value != RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY && value > ls.rlim_max))
|
||||
{
|
||||
ls.rlim_cur = ls.rlim_max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( setrlimit( resource, &ls ) )
|
||||
{
|
||||
if( errno == EPERM )
|
||||
@@ -244,8 +244,8 @@ static int set( int resource, int hard, int soft, rlim_t value )
|
||||
else
|
||||
builtin_wperror( L"ulimit" );
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,17 +256,17 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
{
|
||||
int hard=0;
|
||||
int soft=0;
|
||||
|
||||
|
||||
int what = RLIMIT_FSIZE;
|
||||
int report_all = 0;
|
||||
|
||||
int argc = builtin_count_args( argv );
|
||||
|
||||
|
||||
woptind=0;
|
||||
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
const static struct woption
|
||||
static const struct woption
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
@@ -321,27 +321,27 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
L"virtual-memory-size", no_argument, 0, 'v'
|
||||
}
|
||||
,
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
{
|
||||
L"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
;
|
||||
|
||||
|
||||
int opt_index = 0;
|
||||
|
||||
|
||||
int opt = wgetopt_long( argc,
|
||||
argv,
|
||||
L"aHScdflmnstuvh",
|
||||
long_options,
|
||||
argv,
|
||||
L"aHScdflmnstuvh",
|
||||
long_options,
|
||||
&opt_index );
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
|
||||
switch( opt )
|
||||
{
|
||||
case 0:
|
||||
@@ -354,7 +354,7 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
case L'a':
|
||||
report_all=1;
|
||||
break;
|
||||
@@ -364,17 +364,17 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
break;
|
||||
|
||||
case L'S':
|
||||
soft=1;
|
||||
soft=1;
|
||||
break;
|
||||
|
||||
case L'c':
|
||||
what=RLIMIT_CORE;
|
||||
break;
|
||||
|
||||
|
||||
case L'd':
|
||||
what=RLIMIT_DATA;
|
||||
break;
|
||||
|
||||
|
||||
case L'f':
|
||||
what=RLIMIT_FSIZE;
|
||||
break;
|
||||
@@ -384,45 +384,45 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_RSS
|
||||
#ifdef RLIMIT_RSS
|
||||
case L'm':
|
||||
what=RLIMIT_RSS;
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
case L'n':
|
||||
what=RLIMIT_NOFILE;
|
||||
break;
|
||||
|
||||
|
||||
case L's':
|
||||
what=RLIMIT_STACK;
|
||||
break;
|
||||
|
||||
|
||||
case L't':
|
||||
what=RLIMIT_CPU;
|
||||
break;
|
||||
|
||||
#ifdef RLIMIT_NPROC
|
||||
|
||||
#ifdef RLIMIT_NPROC
|
||||
case L'u':
|
||||
what=RLIMIT_NPROC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef RLIMIT_AS
|
||||
|
||||
#ifdef RLIMIT_AS
|
||||
case L'v':
|
||||
what=RLIMIT_AS;
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
case L'h':
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
builtin_print_help( argv[0], sb_out );
|
||||
return 0;
|
||||
|
||||
case L'?':
|
||||
builtin_unknown_option( argv[0], argv[woptind-1] );
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( report_all )
|
||||
{
|
||||
@@ -432,7 +432,7 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
}
|
||||
else
|
||||
{
|
||||
sb_append2( sb_err,
|
||||
sb_append( sb_err,
|
||||
argv[0],
|
||||
L": Too many arguments\n",
|
||||
(void *)0 );
|
||||
@@ -442,7 +442,7 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
switch( argc - woptind )
|
||||
{
|
||||
case 0:
|
||||
@@ -453,7 +453,7 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
print( what, hard );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 1:
|
||||
{
|
||||
/*
|
||||
@@ -469,7 +469,7 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
{
|
||||
hard=soft=1;
|
||||
}
|
||||
|
||||
|
||||
if( wcscasecmp( argv[woptind], L"unlimited" )==0)
|
||||
{
|
||||
new_limit = RLIM_INFINITY;
|
||||
@@ -484,33 +484,33 @@ static int builtin_ulimit( wchar_t ** argv )
|
||||
}
|
||||
else
|
||||
{
|
||||
errno=0;
|
||||
errno=0;
|
||||
new_limit = wcstol( argv[woptind], &end, 10 );
|
||||
if( errno || *end )
|
||||
{
|
||||
sb_printf( sb_err,
|
||||
L"%ls: Invalid limit '%ls'\n",
|
||||
argv[0],
|
||||
sb_printf( sb_err,
|
||||
L"%ls: Invalid limit '%ls'\n",
|
||||
argv[0],
|
||||
argv[woptind] );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
new_limit *= get_multiplier( what );
|
||||
}
|
||||
|
||||
|
||||
return set( what, hard, soft, new_limit );
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
sb_append2( sb_err,
|
||||
sb_append( sb_err,
|
||||
argv[0],
|
||||
L": Too many arguments\n",
|
||||
(void *)0 );
|
||||
builtin_print_help( argv[0], sb_err );
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
135
common.h
135
common.h
@@ -40,14 +40,30 @@
|
||||
*/
|
||||
#define BYTE_MAX 0xffu
|
||||
|
||||
/**
|
||||
Escape special fish syntax characters like the semicolon
|
||||
*/
|
||||
#define UNESCAPE_SPECIAL 1
|
||||
|
||||
/**
|
||||
Allow incomplete escape sequences
|
||||
*/
|
||||
#define UNESCAPE_INCOMPLETE 2
|
||||
|
||||
/**
|
||||
Escape all characters, including magic characters like the semicolon
|
||||
*/
|
||||
#define ESCAPE_ALL 1
|
||||
/**
|
||||
Do not try to use 'simplified' quoted escapes, and do not use empty quotes as the empty string
|
||||
*/
|
||||
#define ESCAPE_NO_QUOTED 2
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
Save the shell mode on startup so we can restore them on exit
|
||||
*/
|
||||
extern struct termios shell_modes;
|
||||
extern struct termios shell_modes;
|
||||
|
||||
/**
|
||||
The character to use where the text has been truncated. Is an
|
||||
@@ -93,14 +109,14 @@ extern wchar_t *program_name;
|
||||
/**
|
||||
Pause for input, then exit the program. If supported, print a backtrace first.
|
||||
*/
|
||||
#define FATAL_EXIT() \
|
||||
{ \
|
||||
char c; \
|
||||
show_stackframe(); \
|
||||
read( 0, &c, 1 ); \
|
||||
exit( 1 ); \
|
||||
} \
|
||||
|
||||
#define FATAL_EXIT() \
|
||||
{ \
|
||||
int exit_read_count;char exit_read_buff; \
|
||||
show_stackframe(); \
|
||||
exit_read_count=read( 0, &exit_read_buff, 1 ); \
|
||||
exit( 1 ); \
|
||||
} \
|
||||
|
||||
|
||||
/**
|
||||
Exit program at once, leaving an error message about running out of memory.
|
||||
@@ -128,7 +144,7 @@ extern wchar_t *program_name;
|
||||
show_stackframe(); \
|
||||
return retval; \
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Shorthand for wgettext call
|
||||
*/
|
||||
@@ -136,11 +152,20 @@ extern wchar_t *program_name;
|
||||
|
||||
/**
|
||||
Noop, used to tell xgettext that a string should be translated,
|
||||
even though it is not directly sent to wgettext.
|
||||
even though it is not directly sent to wgettext.
|
||||
*/
|
||||
#define N_(wstr) wstr
|
||||
|
||||
/*
|
||||
/**
|
||||
Check if the specified stringelement is a part of the specified string list
|
||||
*/
|
||||
#define contains( str,... ) contains_internal( str, __VA_ARGS__, (void *)0 )
|
||||
/**
|
||||
Concatenate all the specified strings into a single newly allocated one
|
||||
*/
|
||||
#define wcsdupcat( str,... ) wcsdupcat_internal( str, __VA_ARGS__, (void *)0 )
|
||||
|
||||
/**
|
||||
Print a stack trace to stderr
|
||||
*/
|
||||
void show_stackframe();
|
||||
@@ -156,7 +181,7 @@ 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
|
||||
buff is to small, it will be reallocated, and both buff and len will
|
||||
be updated to reflect this. Returns the number of bytes read or -1
|
||||
on failiure.
|
||||
on failiure.
|
||||
|
||||
If the carriage return character is encountered, it is
|
||||
ignored. fgetws() considers the line to end if reading the file
|
||||
@@ -220,17 +245,12 @@ char **wcsv2strv( const wchar_t **in );
|
||||
*/
|
||||
wchar_t **strv2wcsv( const char **in );
|
||||
|
||||
/**
|
||||
Returns a newly allocated concatenation of the specified wide
|
||||
character strings
|
||||
*/
|
||||
wchar_t *wcsdupcat( const wchar_t *a, const wchar_t *b );
|
||||
|
||||
/**
|
||||
Returns a newly allocated concatenation of the specified wide
|
||||
character strings. The last argument must be a null pointer.
|
||||
*/
|
||||
__sentinel wchar_t *wcsdupcat2( const wchar_t *a, ... );
|
||||
__sentinel wchar_t *wcsdupcat_internal( const wchar_t *a, ... );
|
||||
|
||||
/**
|
||||
Test if the given string is a valid variable name
|
||||
@@ -238,7 +258,7 @@ __sentinel wchar_t *wcsdupcat2( const wchar_t *a, ... );
|
||||
|
||||
|
||||
/**
|
||||
Test if the given string is a valid variable name.
|
||||
Test if the given string is a valid variable name.
|
||||
|
||||
\return null if this is a valid name, and a pointer to the first invalid character otherwise
|
||||
*/
|
||||
@@ -247,7 +267,7 @@ wchar_t *wcsvarname( const wchar_t *str );
|
||||
|
||||
|
||||
/**
|
||||
Test if the given string is a valid function name.
|
||||
Test if the given string is a valid function name.
|
||||
|
||||
\return null if this is a valid name, and a pointer to the first invalid character otherwise
|
||||
*/
|
||||
@@ -255,7 +275,7 @@ wchar_t *wcsvarname( const wchar_t *str );
|
||||
wchar_t *wcsfuncname( const wchar_t *str );
|
||||
|
||||
/**
|
||||
Test if the given string is valid in a variable name
|
||||
Test if the given string is valid in a variable name
|
||||
|
||||
\return 1 if this is a valid name, 0 otherwise
|
||||
*/
|
||||
@@ -291,25 +311,32 @@ void error_reset();
|
||||
This function behaves exactly like a wide character equivalent of
|
||||
the C function setlocale, except that it will also try to detect if
|
||||
the user is using a Unicode character set, and if so, use the
|
||||
unicode ellipsis character as ellipsis, instead of '$'.
|
||||
unicode ellipsis character as ellipsis, instead of '$'.
|
||||
*/
|
||||
const wchar_t *wsetlocale( int category, const wchar_t *locale );
|
||||
|
||||
/**
|
||||
Checks if \c needle is included in the list of strings specified. A warning is printed if needle is zero.
|
||||
|
||||
\param needle the string to search for in the list
|
||||
\param needle the string to search for in the list
|
||||
|
||||
\return zero is needle is not found, of if needle is null, non-zero otherwise
|
||||
\return zero if needle is not found, of if needle is null, non-zero otherwise
|
||||
*/
|
||||
__sentinel int contains_str( const wchar_t *needle, ... );
|
||||
__sentinel int contains_internal( const wchar_t *needle, ... );
|
||||
|
||||
/**
|
||||
Call read while blocking the SIGCHLD signal. Should only be called
|
||||
if you _know_ there is data available for reading.
|
||||
if you _know_ there is data available for reading, or the program
|
||||
will hang until there is data.
|
||||
*/
|
||||
int read_blocked(int fd, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
Loop a write request while failiure is non-critical. Return -1 and set errno
|
||||
in case of critical error.
|
||||
*/
|
||||
ssize_t write_loop(int fd, char *buff, size_t count);
|
||||
|
||||
|
||||
/**
|
||||
Issue a debug message with printf-style string formating and
|
||||
@@ -319,9 +346,9 @@ int read_blocked(int fd, void *buf, size_t count);
|
||||
Because debug is often called to tell the user about an error,
|
||||
before using wperror to give a specific error message, debug will
|
||||
never ever modify the value of errno.
|
||||
|
||||
|
||||
\param level the priority of the message. Lower number means higher priority. Messages with a priority_number higher than \c debug_level will be ignored..
|
||||
\param msg the message format string.
|
||||
\param msg the message format string.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -333,7 +360,7 @@ void debug( int level, const wchar_t *msg, ... );
|
||||
|
||||
/**
|
||||
Replace special characters with backslash escape sequences. Newline is
|
||||
replaced with \n, etc.
|
||||
replaced with \n, etc.
|
||||
|
||||
\param in The string to be escaped
|
||||
\param escape_all Whether all characters wich hold special meaning in fish (Pipe, semicolon, etc,) should be escaped, or only unprintable characters
|
||||
@@ -353,32 +380,32 @@ wchar_t *escape( const wchar_t *in, int escape_all );
|
||||
an invalid sequence is specified, 0 is returned.
|
||||
|
||||
*/
|
||||
wchar_t *unescape( const wchar_t * in,
|
||||
wchar_t *unescape( const wchar_t * in,
|
||||
int escape_special );
|
||||
|
||||
/**
|
||||
Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL
|
||||
milliseconds between polls and timing out after timeout seconds,
|
||||
Attempt to acquire a lock based on a lockfile, waiting LOCKPOLLINTERVAL
|
||||
milliseconds between polls and timing out after timeout seconds,
|
||||
thereafter forcibly attempting to obtain the lock if force is non-zero.
|
||||
Returns 1 on success, 0 on failure.
|
||||
To release the lock the lockfile must be unlinked.
|
||||
A unique temporary file named by appending characters to the lockfile name
|
||||
A unique temporary file named by appending characters to the lockfile name
|
||||
is used; any pre-existing file of the same name is subject to deletion.
|
||||
*/
|
||||
int acquire_lock_file( const char *lockfile, const int timeout, int force );
|
||||
|
||||
/**
|
||||
Returns the width of the terminal window, so that not all
|
||||
functions that use these values continually have to keep track of
|
||||
it.
|
||||
/**
|
||||
Returns the width of the terminal window, so that not all
|
||||
functions that use these values continually have to keep track of
|
||||
it separately.
|
||||
|
||||
Only works if common_handle_winch is registered to handle winch signals.
|
||||
Only works if common_handle_winch is registered to handle winch signals.
|
||||
*/
|
||||
int common_get_width();
|
||||
/**
|
||||
Returns the height of the terminal window, so that not all
|
||||
functions that use these values continually have to keep track of
|
||||
it.
|
||||
it separatly.
|
||||
|
||||
Only works if common_handle_winch is registered to handle winch signals.
|
||||
*/
|
||||
@@ -401,17 +428,17 @@ void write_screen( const wchar_t *msg, string_buffer_t *buff );
|
||||
Tokenize the specified string into the specified array_list_t.
|
||||
Each new element is allocated using malloc and must be freed by the
|
||||
caller.
|
||||
|
||||
|
||||
\param val the input string. The contents of this string is not changed.
|
||||
\param out the list in which to place the elements.
|
||||
\param out the list in which to place the elements.
|
||||
*/
|
||||
void tokenize_variable_array( const wchar_t *val, array_list_t *out );
|
||||
|
||||
|
||||
/**
|
||||
Make sure the specified direcotry exists. If no, try to create it.
|
||||
Make sure the specified direcotry exists. If needed, try to create
|
||||
it and any currently not existing parent directories..
|
||||
|
||||
\return 0 if the directory exists, -1 otherwise.
|
||||
\return 0 if, at the time of function return the directory exists, -1 otherwise.
|
||||
*/
|
||||
int create_directory( wchar_t *d );
|
||||
|
||||
@@ -420,5 +447,21 @@ int create_directory( wchar_t *d );
|
||||
*/
|
||||
void bugreport();
|
||||
|
||||
/**
|
||||
Format the specified size (in bytes, kilobytes, etc.) into the specified stringbuffer.
|
||||
*/
|
||||
void sb_format_size( string_buffer_t *sb,
|
||||
long long sz );
|
||||
|
||||
/**
|
||||
Return the number of seconds from the UNIX epoch, with subsecond
|
||||
precision. This function uses the gettimeofday function, and will
|
||||
have the same precision as that function.
|
||||
|
||||
If an error occurs, NAN is returned.
|
||||
*/
|
||||
double timef();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
1081
complete.c
1081
complete.c
File diff suppressed because it is too large
Load Diff
168
complete.h
168
complete.h
@@ -16,39 +16,39 @@
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
Use all completions
|
||||
/**
|
||||
Use all completions
|
||||
*/
|
||||
#define SHARED 0
|
||||
/**
|
||||
Do not use file completion
|
||||
/**
|
||||
Do not use file completion
|
||||
*/
|
||||
#define NO_FILES 1
|
||||
/**
|
||||
Require a parameter after completion
|
||||
/**
|
||||
Require a parameter after completion
|
||||
*/
|
||||
#define NO_COMMON 2
|
||||
/**
|
||||
/**
|
||||
Only use the argument list specifies with completion after
|
||||
option. This is the same as (NO_FILES & NO_COMMON)
|
||||
*/
|
||||
#define EXCLUSIVE 3
|
||||
|
||||
/**
|
||||
Command is a path
|
||||
/**
|
||||
Command is a path
|
||||
*/
|
||||
#define PATH 1
|
||||
/**
|
||||
Command is not a path
|
||||
/**
|
||||
Command is not a path
|
||||
*/
|
||||
#define COMMAND 0
|
||||
|
||||
/**
|
||||
/**
|
||||
Separator between completion and description
|
||||
*/
|
||||
#define COMPLETE_SEP L'\004'
|
||||
|
||||
/**
|
||||
/**
|
||||
Separator between completion and description
|
||||
*/
|
||||
#define COMPLETE_SEP_STR L"\004"
|
||||
@@ -67,18 +67,82 @@
|
||||
#define PROG_COMPLETE_SEP L'\t'
|
||||
|
||||
/**
|
||||
Do not insert space afterwards if this is the only completion. (The
|
||||
default is to try insert a space)
|
||||
*/
|
||||
#define COMPLETE_NO_SPACE 1
|
||||
|
||||
Add a completion.
|
||||
/**
|
||||
This compeltion is case insensitive.
|
||||
|
||||
Warning: The contents of the completion_t structure is actually
|
||||
different if this flag is set! Specifically, the completion string
|
||||
contains the _entire_ completion token, not only the current
|
||||
*/
|
||||
#define COMPLETE_NO_CASE 2
|
||||
|
||||
/**
|
||||
This compeltion is the whole argument, not just the remainder. This
|
||||
flag must never be set on completions returned from the complete()
|
||||
function. It is strictly for internal use in the completion code.
|
||||
*/
|
||||
#define COMPLETE_WHOLE_ARGUMENT 4
|
||||
|
||||
/**
|
||||
This completion may or may not want a space at the end - guess by
|
||||
checking the last character of the completion.
|
||||
*/
|
||||
#define COMPLETE_AUTO_SPACE 8
|
||||
|
||||
/**
|
||||
This completion should be inserted as-is, without escaping.
|
||||
*/
|
||||
#define COMPLETE_DONT_ESCAPE 16
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
/**
|
||||
The completion string
|
||||
*/
|
||||
const wchar_t *completion;
|
||||
|
||||
/**
|
||||
The description for this completion
|
||||
*/
|
||||
const wchar_t *description;
|
||||
|
||||
/**
|
||||
Flags determining the completion behaviour.
|
||||
|
||||
Determines whether a space should be inserted after this
|
||||
compeltion if it is the only possible completion using the
|
||||
COMPLETE_NO_SPACE flag.
|
||||
|
||||
The COMPLETE_NO_CASE can be used to signal that this completion
|
||||
is case insensitive.
|
||||
*/
|
||||
int flags;
|
||||
|
||||
}
|
||||
completion_t;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Add a completion.
|
||||
|
||||
All supplied values are copied, they should be freed by or otherwise
|
||||
disposed by the caller.
|
||||
|
||||
Examples:
|
||||
|
||||
Examples:
|
||||
|
||||
The command 'gcc -o' requires that a file follows it, so the
|
||||
NO_COMMON option is suitable. This can be done using the following
|
||||
line:
|
||||
|
||||
|
||||
complete -c gcc -s o -r
|
||||
|
||||
The command 'grep -d' required that one of the strings 'read',
|
||||
@@ -95,7 +159,7 @@
|
||||
will be interpreted as the command name.
|
||||
\param short_opt The single character name of an option. (-a is a short option, --all and -funroll are long options)
|
||||
\param long_opt The multi character name of an option. (-a is a short option, --all and -funroll are long options)
|
||||
\param long_mode Whether to use old style, single dash long options.
|
||||
\param long_mode Whether to use old style, single dash long options.
|
||||
\param result_mode Whether to search further completions when this
|
||||
completion has been succesfully matched. If result_mode is SHARED,
|
||||
any other completions may also be used. If result_mode is NO_FILES,
|
||||
@@ -106,33 +170,34 @@
|
||||
\param comp A space separated list of completions which may contain subshells.
|
||||
\param desc A description of the completion.
|
||||
\param condition a command to be run to check it this completion should be used. If \c condition is empty, the completion is always used.
|
||||
|
||||
\param flags A set of completion flags
|
||||
*/
|
||||
void complete_add( const wchar_t *cmd,
|
||||
int cmd_type,
|
||||
wchar_t short_opt,
|
||||
const wchar_t *long_opt,
|
||||
int long_mode,
|
||||
int result_mode,
|
||||
const wchar_t *condition,
|
||||
const wchar_t *comp,
|
||||
const wchar_t *desc );
|
||||
void complete_add( const wchar_t *cmd,
|
||||
int cmd_type,
|
||||
wchar_t short_opt,
|
||||
const wchar_t *long_opt,
|
||||
int long_mode,
|
||||
int result_mode,
|
||||
const wchar_t *condition,
|
||||
const wchar_t *comp,
|
||||
const wchar_t *desc,
|
||||
int flags );
|
||||
/**
|
||||
Sets whether the completion list for this command is complete. If
|
||||
true, any options not matching one of the provided options will be
|
||||
flagged as an error by syntax highlighting.
|
||||
*/
|
||||
void complete_set_authorative( const wchar_t *cmd,
|
||||
int cmd_type,
|
||||
int authorative );
|
||||
void complete_set_authoritative( const wchar_t *cmd,
|
||||
int cmd_type,
|
||||
int authoritative );
|
||||
|
||||
/**
|
||||
Remove a previously defined completion
|
||||
*/
|
||||
void complete_remove( const wchar_t *cmd,
|
||||
int cmd_type,
|
||||
wchar_t short_opt,
|
||||
const wchar_t *long_opt );
|
||||
void complete_remove( const wchar_t *cmd,
|
||||
int cmd_type,
|
||||
wchar_t short_opt,
|
||||
const wchar_t *long_opt );
|
||||
|
||||
/**
|
||||
Find all completions of the command cmd, insert them into out. The
|
||||
@@ -147,34 +212,25 @@ void complete_remove( const wchar_t *cmd,
|
||||
void complete( const wchar_t *cmd, array_list_t *out );
|
||||
|
||||
/**
|
||||
Print a list of all current completions into the string_buffer_t.
|
||||
Print a list of all current completions into the string_buffer_t.
|
||||
|
||||
\param out The string_buffer_t to write completions to
|
||||
*/
|
||||
void complete_print( string_buffer_t *out );
|
||||
|
||||
/**
|
||||
Obtain a description string for the file specified by the filename.
|
||||
|
||||
The returned value is a string constant and should not be freed.
|
||||
|
||||
\param filename The file for which to find a description string
|
||||
*/
|
||||
const wchar_t *complete_get_desc( const wchar_t *filename );
|
||||
|
||||
/**
|
||||
Tests if the specified option is defined for the specified command
|
||||
*/
|
||||
int complete_is_valid_option( const wchar_t *str,
|
||||
const wchar_t *opt,
|
||||
int complete_is_valid_option( const wchar_t *str,
|
||||
const wchar_t *opt,
|
||||
array_list_t *errors );
|
||||
|
||||
/**
|
||||
Tests if the specified argument is valid for the specified option
|
||||
and command
|
||||
*/
|
||||
int complete_is_valid_argument( const wchar_t *str,
|
||||
const wchar_t *opt,
|
||||
int complete_is_valid_argument( const wchar_t *str,
|
||||
const wchar_t *opt,
|
||||
const wchar_t *arg );
|
||||
|
||||
|
||||
@@ -189,4 +245,18 @@ int complete_is_valid_argument( const wchar_t *str,
|
||||
*/
|
||||
void complete_load( const wchar_t *cmd, int reload );
|
||||
|
||||
/**
|
||||
Create a new completion entry
|
||||
|
||||
\param context The halloc context to use for allocating new memory
|
||||
\param comp The completion string
|
||||
\param desc The description of the completion
|
||||
\param flags completion flags
|
||||
*/
|
||||
void completion_allocate( array_list_t *context,
|
||||
const wchar_t *comp,
|
||||
const wchar_t *desc,
|
||||
int flags );
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
364
configure.ac
364
configure.ac
@@ -9,8 +9,35 @@
|
||||
# configure the build process.
|
||||
#
|
||||
|
||||
AC_INIT(fish,1.22.3,fish-users@lists.sf.net)
|
||||
AC_INIT(fish,1.23.1,fish-users@lists.sf.net)
|
||||
|
||||
#
|
||||
# preserve configure arguments for xsel
|
||||
#
|
||||
|
||||
conf_arg=$@
|
||||
|
||||
#
|
||||
# List of output variables produced by this configure script
|
||||
#
|
||||
|
||||
AC_SUBST(docdir)
|
||||
AC_SUBST(HAVE_GETTEXT)
|
||||
AC_SUBST(LDFLAGS_FISH)
|
||||
AC_SUBST(LIBS_FISH)
|
||||
AC_SUBST(LIBS_FISH_INDENT)
|
||||
AC_SUBST(LIBS_FISH_PAGER)
|
||||
AC_SUBST(LIBS_FISHD)
|
||||
AC_SUBST(LIBS_MIMEDB)
|
||||
AC_SUBST(LIBS_SET_COLOR)
|
||||
AC_SUBST(localedir)
|
||||
AC_SUBST(optbindirs)
|
||||
AC_SUBST(prefix)
|
||||
AC_SUBST(SEQ_FALLBACK)
|
||||
AC_SUBST(XSEL)
|
||||
AC_SUBST(XSEL_MAN)
|
||||
AC_SUBST(XSEL_BIN)
|
||||
AC_SUBST(XSEL_MAN_PATH)
|
||||
|
||||
#
|
||||
# If needed, run autoconf to regenerate the configure file
|
||||
@@ -33,7 +60,7 @@ if test configure -ot configure.ac; then
|
||||
fi
|
||||
exit 1
|
||||
else
|
||||
AC_MSG_ERROR(
|
||||
AC_MSG_ERROR(
|
||||
[cannot find the autoconf program in your path.
|
||||
This program needs to be run whenever the configure.ac file is modified.
|
||||
Please install it and try again.]
|
||||
@@ -58,7 +85,7 @@ if test ! -f ./config.h.in -o config.h.in -ot configure.ac; then
|
||||
AC_MSG_NOTICE([running autoheader])
|
||||
autoheader || exit 1
|
||||
else
|
||||
AC_MSG_ERROR(
|
||||
AC_MSG_ERROR(
|
||||
[cannot find the autoheader program in your path.
|
||||
This program needs to be run whenever the configure.ac file is modified.
|
||||
Please install it and try again.]
|
||||
@@ -107,11 +134,9 @@ for i in /usr/pkg /sw /opt /opt/local; do
|
||||
|
||||
done
|
||||
|
||||
AC_SUBST( optbindirs, $optbindirs )
|
||||
|
||||
|
||||
#
|
||||
# Tell autoconf to create config.h header
|
||||
# Tell autoconf to create config.h header
|
||||
#
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
||||
@@ -125,8 +150,8 @@ AH_BOTTOM([#if __GNUC__ >= 3
|
||||
#define __warn_unused __attribute__ ((warn_unused_result))
|
||||
#define __sentinel __attribute__ ((sentinel))
|
||||
#else
|
||||
#define __warn_unused
|
||||
#define __sentinel
|
||||
#define __warn_unused
|
||||
#define __sentinel
|
||||
#endif])
|
||||
|
||||
|
||||
@@ -134,11 +159,13 @@ AH_BOTTOM([#if __GNUC__ >= 3
|
||||
# Set up various programs needed for install
|
||||
#
|
||||
|
||||
AC_PROG_CC
|
||||
# Here we look for c99 before cc as Sun Studio compiler supports c99
|
||||
# through the c99 binary.
|
||||
|
||||
AC_PROG_CC([gcc c99 cc])
|
||||
AC_PROG_CPP
|
||||
AC_PROG_INSTALL
|
||||
|
||||
|
||||
#
|
||||
# Check for seq command. If missing, make sure fallback shellscript
|
||||
# implementation is installed.
|
||||
@@ -161,7 +188,7 @@ if test "$SEQ_FALLBACK"; then
|
||||
shebang=`grep "\(^#!/.*/fish\|^#!/usr/bin/env fish\)" $file`
|
||||
|
||||
if test "$shebang"; then
|
||||
AC_SUBST( SEQ_FALLBACK, seq )
|
||||
SEQ_FALLBACK=seq
|
||||
AC_MSG_RESULT(yes, replace it)
|
||||
else
|
||||
AC_MSG_RESULT(no, keep it)
|
||||
@@ -174,24 +201,22 @@ fi
|
||||
# Optionally drop xsel command
|
||||
#
|
||||
|
||||
AC_ARG_WITH(
|
||||
xsel,
|
||||
AC_ARG_WITH(
|
||||
xsel,
|
||||
AC_HELP_STRING(
|
||||
[--without-xsel],
|
||||
[do not build the xsel program needed for X clipboard integration]
|
||||
[do not build the xsel program needed for X clipboard integration.
|
||||
If build xsel, it will be configured with the same options as fish.]
|
||||
),
|
||||
[xsel=$withval],
|
||||
[xsel=with_xsel]
|
||||
[xsel=with_xsel]
|
||||
)
|
||||
|
||||
if [[ "$xsel" = "with_xsel" ]]; then
|
||||
AC_SUBST( XSEL,[xsel-0.9.6/xsel])
|
||||
AC_SUBST( XSEL_MAN,[xsel.1x])
|
||||
AC_SUBST( XSEL_MAN_PATH,[xsel-0.9.6/xsel.1x])
|
||||
else
|
||||
AC_SUBST( XSEL,[ ])
|
||||
AC_SUBST( XSEL_MAN,[ ])
|
||||
AC_SUBST( XSEL_MAN_PATH,[ ])
|
||||
XSEL=xsel-1.2.0
|
||||
XSEL_BIN=$XSEL/xsel
|
||||
XSEL_MAN=xsel.1x
|
||||
XSEL_MAN_PATH=$XSEL/xsel.1x
|
||||
fi
|
||||
|
||||
|
||||
@@ -209,7 +234,7 @@ AC_ARG_WITH(
|
||||
[local_gettext=yes]
|
||||
)
|
||||
|
||||
if test x$local_gettext != xno; then
|
||||
if test x$local_gettext != xno; then
|
||||
AC_DEFINE([USE_GETTEXT],[1],[Perform string translations with gettext])
|
||||
fi
|
||||
|
||||
@@ -217,56 +242,59 @@ fi
|
||||
#
|
||||
# Test if the compiler accepts the -std=c99 flag. If so, using it
|
||||
# increases the odds of correct compilation, since we want to use the
|
||||
# *wprintf functions, which where defined in C99.
|
||||
# *wprintf functions, which where defined in C99.
|
||||
#
|
||||
# NOTE: Never versions of autoconf has AC_CHECK_PROG_CC_C99
|
||||
#
|
||||
|
||||
XCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -std=c99"
|
||||
XCPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS -std=c99"
|
||||
AC_MSG_CHECKING(if -std=c99 works)
|
||||
if test "$CC" != "c99"; then
|
||||
XCFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -std=c99"
|
||||
XCPPFLAGS="$CPPFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS -std=c99"
|
||||
AC_MSG_CHECKING(if -std=c99 works)
|
||||
|
||||
AC_CACHE_VAL(
|
||||
local_cv_has__std_c99,
|
||||
[
|
||||
AC_TRY_RUN(
|
||||
[
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
AC_CACHE_VAL(
|
||||
local_cv_has__std_c99,
|
||||
[
|
||||
AC_TRY_RUN(
|
||||
[
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
],
|
||||
local_cv_has__std_c99=yes,
|
||||
local_cv_has__std_c99=no,
|
||||
)
|
||||
]
|
||||
)
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
],
|
||||
local_cv_has__std_c99=yes,
|
||||
local_cv_has__std_c99=no,
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
AC_MSG_RESULT($local_cv_has__std_c99)
|
||||
case x$local_cv_has__std_c99 in
|
||||
xno)
|
||||
CFLAGS="$XCFLAGS"
|
||||
CPPFLAGS="$XCPPFLAGS" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
#
|
||||
# Try to enale large file support. This will make sure that on systems
|
||||
# Try to enable large file support. This will make sure that on systems
|
||||
# where off_t can be either 32 or 64 bit, the latter size is used. On
|
||||
# other systems, this should do nothing. (Hopefully)
|
||||
#
|
||||
|
||||
CFLAGS="$CFLAGS -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64"
|
||||
|
||||
AC_MSG_RESULT($local_cv_has__std_c99)
|
||||
case x$local_cv_has__std_c99 in
|
||||
xno)
|
||||
CFLAGS="$XCFLAGS"
|
||||
CPPFLAGS="$XCPPFLAGS" ;;
|
||||
esac
|
||||
|
||||
|
||||
#
|
||||
# If we are using gcc, set some flags that increase the odds of the
|
||||
# compiler producing a working binary...
|
||||
#
|
||||
|
||||
if test "$CC" = gcc; then
|
||||
if test "$GCC" = yes; then
|
||||
|
||||
#
|
||||
# -fno-optimize-sibling-calls seems to work around a bug where
|
||||
@@ -291,7 +319,7 @@ if test "$CC" = gcc; then
|
||||
# This is needed in order to get the really cool backtraces
|
||||
#
|
||||
|
||||
LDFLAGS="$LDFLAGS -rdynamic"
|
||||
LDFLAGS_FISH="$LDFLAGS_FISH -rdynamic"
|
||||
|
||||
fi
|
||||
|
||||
@@ -318,9 +346,9 @@ AC_RUN_IFELSE(
|
||||
return STATUS;
|
||||
]
|
||||
)
|
||||
],
|
||||
[glibc=yes],
|
||||
[glibc=no]
|
||||
],
|
||||
[glibc=yes],
|
||||
[glibc=no]
|
||||
)
|
||||
|
||||
if test "$glibc" = yes; then
|
||||
@@ -363,7 +391,7 @@ fi
|
||||
|
||||
AC_MSG_CHECKING([if we are under Solaris])
|
||||
case $target_os in
|
||||
solaris*)
|
||||
solaris*)
|
||||
AC_DEFINE( __EXTENSIONS__, 1, [Macro to enable additional prototypes under Solaris])
|
||||
AC_MSG_RESULT(yes)
|
||||
;;
|
||||
@@ -372,6 +400,34 @@ case $target_os in
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check for Solaris curses tputs having fixed length parameter list.
|
||||
AC_MSG_CHECKING([if we are using non varargs tparm.])
|
||||
AC_COMPILE_IFELSE(
|
||||
[
|
||||
AC_LANG_PROGRAM(
|
||||
[
|
||||
#include <curses.h>
|
||||
#include <term.h>
|
||||
],
|
||||
[
|
||||
tparm( "" );
|
||||
]
|
||||
)
|
||||
],
|
||||
[tparm_solaris_kludge=no],
|
||||
[tparm_solaris_kludge=yes]
|
||||
)
|
||||
if test "x$tparm_solaris_kludge" = "xyes"; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(
|
||||
[TPARM_SOLARIS_KLUDGE],
|
||||
[1],
|
||||
[Define to 1 if tparm accepts a fixed amount of paramters.]
|
||||
)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
|
||||
#
|
||||
# BSD-specific flags go here
|
||||
@@ -379,7 +435,7 @@ esac
|
||||
|
||||
AC_MSG_CHECKING([if we are under BSD])
|
||||
case $target_os in
|
||||
*bsd*)
|
||||
*bsd*)
|
||||
AC_DEFINE( __BSD_VISIBLE, 1, [Macro to enable additional prototypes under BSD])
|
||||
AC_DEFINE( _NETBSD_SOURCE, 1, [Macro to enable additional prototypes under BSD])
|
||||
AC_MSG_RESULT(yes)
|
||||
@@ -398,10 +454,7 @@ esac
|
||||
#
|
||||
|
||||
if [[ "$prefix" = NONE ]]; then
|
||||
export prefix=/usr/local
|
||||
AC_SUBST( prefix, /usr/local)
|
||||
else
|
||||
AC_SUBST( prefix, [$prefix])
|
||||
prefix=/usr/local
|
||||
fi
|
||||
|
||||
|
||||
@@ -413,9 +466,9 @@ fi
|
||||
AC_ARG_VAR( [docdir], [Documentation direcotry] )
|
||||
|
||||
if test -z $docdir; then
|
||||
AC_SUBST(docdir, [$datadir/doc/fish] )
|
||||
docdir=$datadir/doc/fish
|
||||
else
|
||||
AC_SUBST(docdir, [$docdir])
|
||||
docdir=$docdir
|
||||
fi
|
||||
|
||||
|
||||
@@ -424,7 +477,7 @@ fi
|
||||
# installed.
|
||||
#
|
||||
|
||||
AC_SUBST( [localedir], [$datadir/locale])
|
||||
localedir=$datadir/locale
|
||||
|
||||
|
||||
#
|
||||
@@ -441,25 +494,108 @@ AC_CHECK_FILES([/proc/self/stat])
|
||||
#
|
||||
|
||||
AC_DEFINE(
|
||||
[HAVE_TRANSLATE_H],
|
||||
[HAVE_TRANSLATE_H],
|
||||
[1],
|
||||
[Define to 1 if the wgettext function should be used for translating strings.]
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Check presense of various libraries
|
||||
# Check presense of various libraries. This is done on a per-binary
|
||||
# level, since including various extra libraries in all binaries only
|
||||
# because thay are used by some of them can cause extra bloat and
|
||||
# slower compiles when developing fish.
|
||||
#
|
||||
|
||||
# Only link with gettext if we are using it
|
||||
if test x$local_gettext != xno; then
|
||||
AC_SEARCH_LIBS( gettext, intl,,)
|
||||
fi
|
||||
# Check for os dependant libraries for all binaries.
|
||||
LIBS_COMMON=$LIBS
|
||||
LIBS=""
|
||||
AC_SEARCH_LIBS( connect, socket, , [AC_MSG_ERROR([Cannot find the socket library, needed to build this package.] )] )
|
||||
AC_SEARCH_LIBS( nanosleep, rt, , [AC_MSG_ERROR([Cannot find the rt library, needed to build this package.] )] )
|
||||
AC_SEARCH_LIBS( setupterm, [ncurses curses], , [AC_MSG_ERROR([Could not find a curses implementation, needed to build fish])] )
|
||||
AC_SEARCH_LIBS( iconv_open, iconv, , [AC_MSG_ERROR([Could not find an iconv implementation, needed to build fish])] )
|
||||
AC_SEARCH_LIBS( [nan], [m], [AC_DEFINE( [HAVE_NAN], [1], [Define to 1 if you have the nan function])] )
|
||||
LIBS_SHARED=$LIBS
|
||||
LIBS=$LIBS_COMMON
|
||||
|
||||
#
|
||||
# Check for libraries needed by fish.
|
||||
#
|
||||
|
||||
LIBS_COMMON=$LIBS
|
||||
LIBS="$LIBS_SHARED"
|
||||
if test x$local_gettext != xno; then
|
||||
AC_SEARCH_LIBS( gettext, intl,,)
|
||||
fi
|
||||
|
||||
# Check for libiconv_open if we can't find iconv_open. Silly OS X does
|
||||
# weird macro magic for the sole purpose of amusing me.
|
||||
AC_SEARCH_LIBS( iconv_open, iconv, , [AC_SEARCH_LIBS( libiconv_open, iconv, , [AC_MSG_ERROR([Could not find an iconv implementation, needed to build fish])] )] )
|
||||
|
||||
LIBS_FISH=$LIBS
|
||||
LIBS=$LIBS_COMMON
|
||||
|
||||
#
|
||||
# Check for libraries needed by fish_indent.
|
||||
#
|
||||
|
||||
LIBS_COMMON=$LIBS
|
||||
LIBS="$LIBS_SHARED"
|
||||
if test x$local_gettext != xno; then
|
||||
AC_SEARCH_LIBS( gettext, intl,,)
|
||||
fi
|
||||
LIBS_FISH_INDENT=$LIBS
|
||||
LIBS=$LIBS_COMMON
|
||||
|
||||
#
|
||||
# Check for libraries needed by fish_pager.
|
||||
#
|
||||
|
||||
LIBS_COMMON=$LIBS
|
||||
LIBS="$LIBS_SHARED"
|
||||
if test x$local_gettext != xno; then
|
||||
AC_SEARCH_LIBS( gettext, intl,,)
|
||||
fi
|
||||
AC_SEARCH_LIBS( iconv_open, iconv, , [AC_MSG_ERROR([Could not find an iconv implementation, needed to build fish])] )
|
||||
LIBS_FISH_PAGER=$LIBS
|
||||
LIBS=$LIBS_COMMON
|
||||
|
||||
#
|
||||
# Check for libraries needed by fishd.
|
||||
#
|
||||
|
||||
LIBS_COMMON=$LIBS
|
||||
LIBS="$LIBS_SHARED"
|
||||
if test x$local_gettext != xno; then
|
||||
AC_SEARCH_LIBS( gettext, intl,,)
|
||||
fi
|
||||
AC_SEARCH_LIBS( iconv_open, iconv, , [AC_MSG_ERROR([Could not find an iconv implementation, needed to build fish])] )
|
||||
LIBS_FISHD=$LIBS
|
||||
LIBS=$LIBS_COMMON
|
||||
|
||||
#
|
||||
# Check for libraries needed by mimedb.
|
||||
#
|
||||
|
||||
LIBS_COMMON=$LIBS
|
||||
LIBS="$LIBS_SHARED"
|
||||
if test x$local_gettext != xno; then
|
||||
AC_SEARCH_LIBS( gettext, intl,,)
|
||||
fi
|
||||
LIBS_MIMEDB=$LIBS
|
||||
LIBS=$LIBS_COMMON
|
||||
|
||||
|
||||
#
|
||||
# Check for libraries needed by set_color
|
||||
#
|
||||
|
||||
LIBS_COMMON=$LIBS
|
||||
LIBS="$LIBS_SHARED"
|
||||
if test x$local_gettext != xno; then
|
||||
AC_SEARCH_LIBS( gettext, intl,,)
|
||||
fi
|
||||
LIBS_SET_COLOR=$LIBS
|
||||
LIBS=$LIBS_COMMON
|
||||
|
||||
#
|
||||
# Check presense of various header files
|
||||
@@ -471,8 +607,8 @@ AC_CHECK_HEADER(
|
||||
[regex.h],
|
||||
[
|
||||
AC_DEFINE(
|
||||
[HAVE_REGEX_H],
|
||||
[1],
|
||||
[HAVE_REGEX_H],
|
||||
[1],
|
||||
[Define to 1 if you have the <regex.h> header file.]
|
||||
)
|
||||
],
|
||||
@@ -569,10 +705,10 @@ for i in "" "-D_POSIX_C_SOURCE=200112L" "-D_XOPEN_SOURCE=600 -D_POSIX_C_SOURCE=2
|
||||
/* Extended-POSIX: might be unhidden by _XOPEN_SOURCE. */
|
||||
ret += killpg( 0, 0 );
|
||||
/* Non-standard: might be hidden by the macros. */
|
||||
{
|
||||
{
|
||||
struct winsize termsize;
|
||||
ret += (int)(void *)&termsize;
|
||||
ret += SIGWINCH + TIOCGWINSZ + SIGIO;
|
||||
ret += SIGWINCH + TIOCGWINSZ + SIGIO;
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -609,15 +745,15 @@ fi
|
||||
AC_CHECK_FUNCS( wcsdup wcsndup wcslen wcscasecmp wcsncasecmp fwprintf )
|
||||
AC_CHECK_FUNCS( futimes wcwidth wcswidth wcstok fputwc fgetwc )
|
||||
AC_CHECK_FUNCS( wcstol wcslcat wcslcpy lrand48_r killpg gettext )
|
||||
AC_CHECK_FUNCS( dcgettext backtrace backtrace_symbols)
|
||||
AC_CHECK_FUNCS( dcgettext backtrace backtrace_symbols sysconf )
|
||||
|
||||
#
|
||||
# The Makefile also needs to know if we have gettext, so it knows if
|
||||
# the translations should be installed.
|
||||
#
|
||||
|
||||
if test x$local_gettext != xno; then
|
||||
AC_CHECK_FUNC( gettext, AC_SUBST( HAVE_GETTEXT, 1 ), AC_SUBST( HAVE_GETTEXT, 0 ) )
|
||||
if test x$local_gettext != xno; then
|
||||
AC_CHECK_FUNC( gettext, HAVE_GETTEXT=1, HAVE_GETTEXT=0 )
|
||||
fi
|
||||
|
||||
#
|
||||
@@ -640,22 +776,22 @@ AC_RUN_IFELSE(
|
||||
#include <stdlib.h>
|
||||
],
|
||||
[
|
||||
int status;
|
||||
char *res;
|
||||
res = realpath( "somefile", 0 );
|
||||
status = !(res != 0 || errno == ENOENT);
|
||||
int status;
|
||||
char *res;
|
||||
res = realpath( "somefile", 0 );
|
||||
status = !(res != 0 || errno == ENOENT);
|
||||
exit( status );
|
||||
]
|
||||
)
|
||||
],
|
||||
[have_realpath_null=yes],
|
||||
[have_realpath_null=no]
|
||||
],
|
||||
[have_realpath_null=yes],
|
||||
[have_realpath_null=no]
|
||||
)
|
||||
|
||||
if test "$have_realpath_null" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(
|
||||
[HAVE_REALPATH_NULL],
|
||||
[HAVE_REALPATH_NULL],
|
||||
[1],
|
||||
[Define to 1 if realpath accepts null for its second argument.]
|
||||
)
|
||||
@@ -682,15 +818,15 @@ AC_LINK_IFELSE(
|
||||
#endif
|
||||
],
|
||||
[
|
||||
struct winsize termsize = {0};
|
||||
struct winsize termsize = {0};
|
||||
TIOCGWINSZ;
|
||||
]
|
||||
)
|
||||
],
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT(yes);
|
||||
AC_MSG_RESULT(yes);
|
||||
AC_DEFINE([HAVE_WINSIZE], [1], [Define to 1 if the winsize struct and TIOCGWINSZ macro exist])
|
||||
],
|
||||
],
|
||||
[
|
||||
AC_MSG_RESULT(no)
|
||||
]
|
||||
@@ -726,7 +862,7 @@ if test "$ac_cv_func_fwprintf" = yes; then
|
||||
[
|
||||
AC_MSG_RESULT([yes])
|
||||
AC_DEFINE([HAVE_BROKEN_FWPRINTF], [1], [Define to 1 one if the implemented fwprintf is broken])
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
fi
|
||||
@@ -742,19 +878,19 @@ AC_TRY_LINK(
|
||||
],
|
||||
[
|
||||
extern int _nl_msg_cat_cntr;
|
||||
int tmp = _nl_msg_cat_cntr;
|
||||
int tmp = _nl_msg_cat_cntr;
|
||||
exit(tmp);
|
||||
],
|
||||
have__nl_msg_cat_cntr=yes,
|
||||
have__nl_msg_cat_cntr=yes,
|
||||
have__nl_msg_cat_cntr=no
|
||||
)
|
||||
if test "$have__nl_msg_cat_cntr" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(
|
||||
[HAVE__NL_MSG_CAT_CNTR],
|
||||
[HAVE__NL_MSG_CAT_CNTR],
|
||||
[1],
|
||||
[Define to 1 if the _nl_msg_cat_cntr symbol is exported.]
|
||||
)
|
||||
)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
@@ -767,19 +903,19 @@ AC_TRY_LINK(
|
||||
],
|
||||
[
|
||||
extern char **__environ;
|
||||
char **tmp = __environ;
|
||||
char **tmp = __environ;
|
||||
exit(tmp!=0);
|
||||
],
|
||||
have___environ=yes,
|
||||
have___environ=yes,
|
||||
have___environ=no
|
||||
)
|
||||
if test "$have___environ" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(
|
||||
[HAVE___ENVIRON],
|
||||
[HAVE___ENVIRON],
|
||||
[1],
|
||||
[Define to 1 if the __environ symbol is exported.]
|
||||
)
|
||||
)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
@@ -796,26 +932,26 @@ AC_TRY_LINK(
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
0, 0, 0, 0
|
||||
0, 0, 0, 0
|
||||
}
|
||||
;
|
||||
int opt = getopt_long( 0,
|
||||
0,
|
||||
0,
|
||||
long_options,
|
||||
0,
|
||||
long_options,
|
||||
0 );
|
||||
|
||||
|
||||
],
|
||||
have_working_getopt_long=yes,
|
||||
have_working_getopt_long=yes,
|
||||
have_working_getopt_long=no
|
||||
)
|
||||
if test "$have_working_getopt_long" = yes; then
|
||||
AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(
|
||||
[HAVE_WORKING_GETOPT_LONG],
|
||||
[HAVE_WORKING_GETOPT_LONG],
|
||||
[1],
|
||||
[Define to 1 if getopt_long exists and works.]
|
||||
)
|
||||
)
|
||||
else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
@@ -847,6 +983,12 @@ if test ! x$local_found_posix_switch = xyes; then
|
||||
echo "Some fish features may be disabled."
|
||||
fi
|
||||
|
||||
if [[ "$xsel" = "with_xsel" ]]; then
|
||||
echo "Now configure xsel with $conf_arg"
|
||||
rm -rf $XSEL
|
||||
tar xf $XSEL.tar.gz
|
||||
cd $XSEL && ./configure $conf_arg
|
||||
fi
|
||||
echo "fish is now configured."
|
||||
echo "Use 'make' and 'make install' to build and install fish."
|
||||
|
||||
|
||||
24
count.c
24
count.c
@@ -1,24 +0,0 @@
|
||||
/** \file count.c
|
||||
The length command, used for determining the number of items in an
|
||||
environment variable array.
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
The main function. Does nothing but return the number of arguments.
|
||||
|
||||
This command, unlike all other fish commands, does not feature a -h
|
||||
or --help option. This is because we want to avoid errors on arrays
|
||||
that have -h or --help as entries, which is very common when
|
||||
parsing options, etc. For this reason, the main fish binary does a
|
||||
check and prints help usage if -h or --help is explicitly given to
|
||||
the command, but not if it is the contents of a variable.
|
||||
*/
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
printf( "%d\n", argc-1 );
|
||||
return argc==1;
|
||||
}
|
||||
@@ -12,7 +12,7 @@ shells. For other uses, it is recommended to define a <a
|
||||
href='#function'>function</a>.
|
||||
|
||||
Alias does not keep track of which functions have been defined using
|
||||
alias, nor does it allow erasing of aliases.
|
||||
alias, nor does it allow erasing of aliases.
|
||||
|
||||
- NAME is the name of the function to define
|
||||
- DEFINITION is the body of the function. The string " $argv" will be appended to the body.
|
||||
|
||||
@@ -17,7 +17,7 @@ variable.
|
||||
\subsection and-example Example
|
||||
|
||||
The following code runs the \c make command to build a program, if the
|
||||
build succceds, the program is installed. If either step fails,
|
||||
build succeeds, the program is installed. If either step fails,
|
||||
<tt>make clean</tt> is run, which removes the files created by the
|
||||
build process
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ In the following code, all output is redirected to the file out.html.
|
||||
begin
|
||||
echo $xml_header
|
||||
echo $html_header
|
||||
if test -e $file
|
||||
if test -e $file
|
||||
...
|
||||
end
|
||||
...
|
||||
|
||||
@@ -8,7 +8,7 @@ Sends the specified jobs to the background. A background job is
|
||||
executed simultaneously with fish, and does not have access to the
|
||||
keyboard. If no job is specified, the last job to be used is put in the background. If PID is specified, the jobs with the specified group ids are put in the background.
|
||||
|
||||
The PID of the desired process is usually found by using process globbing.
|
||||
The PID of the desired process is usually found by using <a href="index.html#expand-process">process expansion</a>.
|
||||
|
||||
\subsection bg-example Example
|
||||
|
||||
|
||||
@@ -1,23 +1,60 @@
|
||||
\section bind bind - handle key bindings
|
||||
\section bind bind - handle fish key bindings
|
||||
|
||||
\subsection bind-synopsis Synopsis
|
||||
<tt>bind [OPTIONS] [BINDINGS...]</tt>
|
||||
|
||||
The <tt>bind</tt> builtin causes fish to add the readline style bindings specified by BINDINGS to the list of key bindings, as if they appeared in your <tt>~/.fish_inputrc</tt> file.
|
||||
|
||||
For more information on the syntax keyboard bindings, use <tt>man
|
||||
readline</tt> to access the readline documentation. The availiable commands
|
||||
are listed in the <a href="index.html#editor">Command Line Editor</a> section
|
||||
of the fish manual - but you may also use any fish command! To write such
|
||||
commands, see the <a href="#commandline">commandline</a> builtin. It's good
|
||||
practice to put the code into a <tt><a href="#function">function</a> -b</tt>
|
||||
and bind to the function name.
|
||||
<tt>bind [OPTIONS] SEQUENCE COMMAND</tt>
|
||||
|
||||
\subsection bind-description Description
|
||||
- <tt>-M MODE</tt> or <tt>--set-mode=MODE</tt> sets the current input mode to MODE.
|
||||
|
||||
The <tt>bind</tt> builtin causes fish to add a key binding from the specified sequence.
|
||||
|
||||
SEQUENCE is the character sequence to bind to. Usually, one would use
|
||||
fish escape sequences to express them. For example, because pressing
|
||||
the Alt key and another character sends that character prefixed with
|
||||
an escape character, Alt-based key bindings can be written using the
|
||||
\c \\e escape. For example, Alt-w can be written as
|
||||
<tt>\\ew</tt>. Control character can be written in much the same way
|
||||
using the \c \\c escape, for example Control-x can be written as
|
||||
<tt>\\cx</tt>. Note that Alt-based key bindings are case sensitive and
|
||||
Control base key bindings are not. This is not a design choice in
|
||||
fish, it is simply how terminals work.
|
||||
|
||||
If SEQUENCE is the empty string, i.e. an empty set of quotes, this is
|
||||
interpreted as the default keybinding. It will be used whenever no
|
||||
other binding matches. For most key bindings, it makes sense to use
|
||||
the \c self-insert function (i.e. <tt>bind '' self-insert</tt> as the
|
||||
default keybining. This will insert any keystrokes not specifically
|
||||
bound to into the editor. Non-printable characters are ignored by the
|
||||
editor, so this will not result in e.g. control sequences being
|
||||
printable.
|
||||
|
||||
If the -k switch is used, the name of the key (such as down, up or
|
||||
backspace) is used instead of a sequence. The names used are the same
|
||||
as the corresponding curses variables, but without the 'key_'
|
||||
prefix. (See man 5 terminfo for more information, or use <tt>bind
|
||||
--key-names</tt> for a list of all available named keys)
|
||||
|
||||
COMMAND can be any fish command, but it can also be one of a set of
|
||||
special input functions. These include functions for moving the
|
||||
cursor, operating on the kill-ring, performing tab completion,
|
||||
etc. Use 'bind --function-names' for a complete list of these input
|
||||
functions.
|
||||
|
||||
When COMMAND is a shellscript command, it is a good practice to put
|
||||
the actual code into a <a href="#function">function</a> and simply
|
||||
bind to the function name. This way it becomes significantly easier to
|
||||
test the function while editing, and the result is usually more
|
||||
readable as well.
|
||||
|
||||
- <tt>-a</tt> or <tt>--all</tt> If --key-names is specified, show all key names, not only the ones that actually are defined for the current terminal. If erase mode is specified, this switch will cause all current bindings to be erased.
|
||||
- <tt>-e</tt> or <tt>--erase</tt> Erase mode. All non-switch arguments are interpreted as character sequences and any commands associated with those sequences are erased.
|
||||
- <tt>-h</tt> or <tt>--help</tt> Display help and exit
|
||||
- <tt>-k</tt> or <tt>--key</tt> Specify a key name, such as 'left' or 'backspace' instead of a character sequence
|
||||
- <tt>-K</tt> or <tt>--key-names</tt> Display a list of available key names
|
||||
- <tt>-f</tt> or <tt>--function-names</tt> Display a list of available input functions
|
||||
|
||||
\subsection bind-example Example
|
||||
|
||||
<tt>bind -M vi</tt> changes to the vi input mode
|
||||
<tt>bind \\cd 'exit'</tt> causes fish to exit on Control-d
|
||||
|
||||
<tt>bind -k ppage history-search-backward</tt> Causes fish to perform a history search when the page up key is pressed
|
||||
|
||||
<tt>bind '"\\M-j": jobs'</tt> Binds the jobs command to the Alt-j keyboard shortcut
|
||||
|
||||
10
doc_src/breakpoint.txt
Normal file
10
doc_src/breakpoint.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
\section breakpoint breakpoint - Launch debug mode
|
||||
|
||||
\subsection breakpoint-synopsis Synopsis
|
||||
<tt>breakpoint</tt>
|
||||
|
||||
\subsection breakpoint-description Description
|
||||
|
||||
The \c breakpoint builtin is used to halt a running script and launch
|
||||
an interactive debug prompt.
|
||||
|
||||
@@ -19,7 +19,7 @@ regular wildcard expansion using filenames.
|
||||
|
||||
Note that fish does not fall through on case statements. Though the
|
||||
syntax may look a bit like C switch statements, it behaves more like
|
||||
the case stamantes of traditional shells.
|
||||
the case statements of traditional shells.
|
||||
|
||||
Also note that command substitutions in a case statement will be
|
||||
evaluated even if it's body is not taken. This may seem
|
||||
|
||||
@@ -7,13 +7,15 @@
|
||||
|
||||
|
||||
- \c CMD is the new value of the commandline. If unspecified, the
|
||||
current value of the commandline is written to standard output.
|
||||
current value of the commandline is written to standard output. All
|
||||
output from the commandline builtin is escaped, i.e. quotes are
|
||||
removed, backslash escapes are expanded, etc..
|
||||
|
||||
The following switches change what the commandline builtin does
|
||||
|
||||
- \c -C or \c --cursor set or get the current cursor position, not
|
||||
- \c -C or \c --cursor set or get the current cursor position, not
|
||||
the contents of the buffer. If no argument is given, the current
|
||||
cursor position is printed, otherwise the argument is interpreted
|
||||
cursor position is printed, otherwise the argument is interpreted
|
||||
as the new cursor position.
|
||||
- \c -f or \c --function inject readline functions into the
|
||||
reader. This option can not be combined with any other option. It
|
||||
@@ -42,7 +44,7 @@ or updated
|
||||
- \c -t or \c --current-token select the current token.
|
||||
|
||||
The following switch changes the way \c commandline prints the current
|
||||
commandline buffer
|
||||
commandline buffer
|
||||
|
||||
- \c -c or \c --cut-at-cursor only print selection up until the
|
||||
current cursor position
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** \page commands Commands, functions and builtins bundled with fish
|
||||
Fish ships with a large number of builtin commands, shellscript functions and external commands. These are all described below.
|
||||
Fish ships with a large number of builtin commands, shellscript functions and external commands. These are all described below.
|
||||
|
||||
@command_list@
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
\subsection complete-description Description
|
||||
|
||||
For an introduction to how to specify completions, see the section <a
|
||||
href='index.html#completions-own'>Writing your own completions</a> of
|
||||
href='index.html#completion-own'>Writing your own completions</a> of
|
||||
the fish manual.
|
||||
|
||||
- <tt>COMMAND</tt> is the name of the command for which to add a completion
|
||||
@@ -21,8 +21,8 @@ the fish manual.
|
||||
- <tt>-o</tt> or <tt>--old-option</tt> implies that the command uses old long style options with only one dash
|
||||
- <tt>-p</tt> or <tt>--path</tt> implies that the string COMMAND is the full path of the command
|
||||
- <tt>-r</tt> or <tt>--require-parameter</tt> specifies that the option specified by this completion always must have an option argument, i.e. may not be followed by another option
|
||||
- <tt>-u</tt> or <tt>--unauthorative</tt> implies that there may be more options than the ones specified, and that fish should not assume that options not listed are spelling errors
|
||||
- <tt>-A</tt> or <tt>--authorative</tt> implies that there may be no more options than the ones specified, and that fish should assume that options not listed are spelling errors
|
||||
- <tt>-u</tt> or <tt>--unauthoritative</tt> implies that there may be more options than the ones specified, and that fish should not assume that options not listed are spelling errors
|
||||
- <tt>-A</tt> or <tt>--authoritative</tt> implies that there may be no more options than the ones specified, and that fish should assume that options not listed are spelling errors
|
||||
- <tt>-x</tt> or <tt>--exclusive</tt> implies both <tt>-r</tt> and <tt>-f</tt>
|
||||
|
||||
Command specific tab-completions in \c fish are based on the notion
|
||||
|
||||
@@ -5,17 +5,18 @@
|
||||
|
||||
\subsection count-description Description
|
||||
|
||||
<tt>count</tt> prints the number of arguments that were passed to
|
||||
it. This is usually used to find out how many elements an environment
|
||||
variable array contains, but this is not the only potential usage for
|
||||
the count command.
|
||||
The <tt>count</tt> builtin prints the number of arguments that were
|
||||
passed to it. This is usually used to find out how many elements an
|
||||
environment variable array contains, but this is not the only
|
||||
potential usage for the count command.
|
||||
|
||||
The count command does not accept any options, not even '-h'. This way
|
||||
the user does not have to worry about an array containing elements
|
||||
such as dashes. \c fish performs a special check when invoking the
|
||||
count program, and if the user uses a help option, this help page is
|
||||
count command, and if the user uses a help option, this help page is
|
||||
displayed, but if a help option is contained inside of a variable or
|
||||
is the result of expansion, it will be passed on to the count program.
|
||||
is the result of expansion, it will simply be counted like any other
|
||||
argument.
|
||||
|
||||
Count exits with a non-zero exit status if no arguments where passed
|
||||
to it, with zero otherwise.
|
||||
|
||||
@@ -7,8 +7,8 @@ design fish. The fish design has three high level goals. These are:
|
||||
|
||||
-# Everything that can be done in other shell languages should be
|
||||
possible to do in fish, though fish may rely on external commands in
|
||||
doing so.
|
||||
-# Fish should be user friendly, but not at the expense of expressiveness.
|
||||
doing so.
|
||||
-# Fish should be user friendly, but not at the expense of expressiveness.
|
||||
Most tradeoffs between power and ease of use can be avoided with careful design.
|
||||
-# Whenever possible without breaking the above goals, fish should
|
||||
follow the Posix syntax.
|
||||
@@ -33,7 +33,7 @@ program harder to maintain and update.
|
||||
Examples:
|
||||
|
||||
- Here documents are too similar to using echo inside of a pipeline.
|
||||
- Subshells, command substitution and process substitution are strongly related. \c fish only supports command substitution, the others can be achived either using a block or the psub shellscript function.
|
||||
- Subshells, command substitution and process substitution are strongly related. \c fish only supports command substitution, the others can be achived either using a block or the psub shellscript function.
|
||||
- Having both aliases and functions is confusing, especially since both of them have limitations and problems. \c fish functions have none of the drawbacks of either syntax.
|
||||
- The many Posix quoting styles are silly, especially \$''.
|
||||
|
||||
@@ -57,14 +57,14 @@ take the whole system down.
|
||||
Examples:
|
||||
|
||||
- Builtin commands should only be created when it cannot be
|
||||
avoided. \c echo, \c kill, \c printf and \c time are among the commands
|
||||
that fish does not implement internally since they can be provided as
|
||||
external commands. Several other commands that are commonly implemented
|
||||
avoided. \c echo, \c kill, \c printf and \c time are among the commands
|
||||
that fish does not implement internally since they can be provided as
|
||||
external commands. Several other commands that are commonly implemented
|
||||
as builtins and can not be implemented as external commands,
|
||||
including \c type, \c vared, \c pushd and \c popd are implemented as shellscript
|
||||
functions in fish.
|
||||
- Mathematical calculations, regex matching, generating lists of numbers
|
||||
and many other funtions can easily be done in external programs. They
|
||||
and many other funtions can easily be done in external programs. They
|
||||
should not be supported internally by the shell.
|
||||
|
||||
The law of minimalism does not imply that a large feature set is
|
||||
@@ -122,8 +122,8 @@ Examples:
|
||||
|
||||
- There should only be one type of input to the shell, lists of commands. Loops, conditionals and variable assignments are all performed through regular commands.
|
||||
- The differences between builtin commands, shellscript functions and builtin commands should be made as small as possible. Builtins and shellscript functions should have exactly the same types of argument expansion as other commands, should be possible to use in any position in a pipeline, and should support any io redirection.
|
||||
- Instead of forking when performing command substitution to provide a fake variable scope, all fish commands are performed from the same process, and fish instead supports true scoping
|
||||
- All blocks end with the \c end builtin
|
||||
- Instead of forking when performing command substitution to provide a fake variable scope, all fish commands are performed from the same process, and fish instead supports true scoping.
|
||||
- All blocks end with the \c end builtin.
|
||||
|
||||
\section disc The law of discoverability
|
||||
|
||||
@@ -147,7 +147,7 @@ until the next time she/he uses the same program.
|
||||
|
||||
Examples:
|
||||
|
||||
- Everything should be tab-completable, and every tab completion should have a description
|
||||
- Everything should be tab-completable, and every tab completion should have a description.
|
||||
- Every syntax error and error in a builtin command should contain an error message describing what went wrong and a relevant help page. Whenever possible, errors should be flagged red by the syntax highlighter.
|
||||
- The help manual should be easy to read, easily available from the shell, complete and contain many examples
|
||||
- The language should be uniform, so that once the user understands the command/argument syntax, he will know the whole language, and be able to use tab-completion to discover new featues.
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
\subsection dirh-synopsis Synopsis
|
||||
<tt>dirh</tt>
|
||||
|
||||
\subsection dirh-description Description
|
||||
\subsection dirh-description Description
|
||||
<tt>dirh</tt> prints the current directory history. The current position in the
|
||||
history is highlighted using <tt>$fish_color_history_current</tt>.
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
\subsection dirs-synopsis Synopsis
|
||||
<tt>dirs</tt>
|
||||
|
||||
\subsection dirs-description Description
|
||||
\subsection dirs-description Description
|
||||
<tt>dirs</tt> prints the current directory stack.
|
||||
|
||||
@@ -13,5 +13,5 @@ status is 0, the commands COMMANDS_TRUE will execute. If it is not 0 and
|
||||
|
||||
The command <tt>if test -f foo.txt; echo foo.txt exists; else; echo foo.txt does not exist; end</tt>
|
||||
will print <tt>foo.txt exists</tt> if the file foo.txt
|
||||
exists and is a regular file, otherwise it will print
|
||||
exists and is a regular file, otherwise it will print
|
||||
<tt>foo.txt does not exist</tt>.
|
||||
|
||||
19
doc_src/emit.txt
Normal file
19
doc_src/emit.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
\section emit emit - Emit a generic event
|
||||
|
||||
\subsection block-synopsis Synopsis
|
||||
<tt>emit EVENT_NAME</tt>
|
||||
|
||||
\subsection emit-description Description
|
||||
|
||||
The emit builtin fires a generic fish event. Such events can be caught by special functions called event handlers.
|
||||
|
||||
\subsection emit-example Example
|
||||
|
||||
The following code first defines an event handler for the generic
|
||||
event named 'test_event', and then emits an event of that type.
|
||||
|
||||
<pre>function event_test --on-event test_event
|
||||
echo event test!!!
|
||||
end
|
||||
|
||||
emit test_event</pre>
|
||||
@@ -1,10 +1,10 @@
|
||||
\section eval eval - eval the specified commands
|
||||
\section eval eval - evaluate the specified commands
|
||||
|
||||
\subsection eval-synopsis Synopsis
|
||||
<tt>eval [COMMANDS...]</tt>
|
||||
|
||||
\subsection eval-description Description
|
||||
The <tt>eval</tt> builtin causes fish to evaluate the specified parameters as a command. If more than one parameter is specified, all parameters will be joined using a space character as a separator.
|
||||
The <tt>eval</tt> function causes fish to evaluate the specified parameters as a command. If more than one parameter is specified, all parameters will be joined using a space character as a separator.
|
||||
|
||||
\subsection eval-example Example
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
- <a href='#faq-default'>How do I make fish my default shell?</a>
|
||||
- <a href='#faq-titlebar'>I'm seeing weird output before each prompt when using screen. What's wrong?</a>
|
||||
- <a href='#faq-greeting'>How do I change the greeting message?</a>
|
||||
- <a href='#faq-history'>Why doesn't history substitution ("!$" etc.) work?</a>
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -32,7 +33,7 @@ parent is ~. This issue is not possible to fix without either making
|
||||
every single command into a builtin, breaking Unix semantics or
|
||||
implementing kludges in every single command.
|
||||
|
||||
This issue can also be seen when doing IO redirection.
|
||||
This issue can also be seen when doing IO redirection.
|
||||
|
||||
Another related issue is that many programs that operate on recursive
|
||||
directory trees, like the find command, silently ignore symlinked
|
||||
@@ -55,9 +56,9 @@ feature, write <code>set CDPATH .</code> on the commandline.
|
||||
|
||||
If fish is unable to locate a command with a given name, fish will
|
||||
test if a directory of that name exists. If it does, it is implicitly
|
||||
assumed that you want to change working directory. For example, the
|
||||
fastest way to switch to your home directory is to simply type
|
||||
<code>~</code>.
|
||||
assumed that you want to change working directory. For example, the
|
||||
fastest way to switch to your home directory is to simply press
|
||||
<code>~</code> and enter.
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -92,8 +93,8 @@ In order to change your default shell, type:
|
||||
|
||||
You may need to adjust the above path to e.g. /usr/bin/fish. Use the command <code>which fish</code> if you are unsure of where fish is installed.
|
||||
|
||||
You will need to log out and back in again for the change to take
|
||||
effect.
|
||||
Unfortunatly, there is no way to make the changes take effect at once,
|
||||
you will need to log out and back in again.
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -104,7 +105,7 @@ Quick answer:
|
||||
Run the following command in fish:
|
||||
|
||||
<pre>
|
||||
echo function fish_title;end ~/.config/fish/config.fish
|
||||
echo 'function fish_title;end' > ~/.config/fish/config.fish
|
||||
</pre>
|
||||
|
||||
Problem solved!
|
||||
@@ -136,5 +137,25 @@ the greeting use:
|
||||
set fish_greeting
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
|
||||
\section faq-history Why doesn't history substitution ("!$" etc.) work?
|
||||
|
||||
Because history substitution is an awkward interface that was invented before
|
||||
interactive line editing was even possible. Fish drops it in favor of
|
||||
perfecting the interactive history recall interface. Switching requires a
|
||||
small change of habits: if you want to modify an old line/word, first recall
|
||||
it, then edit. E.g. don't type "sudo !!" - first press Up, then Home, then
|
||||
type "sudo ".
|
||||
|
||||
Fish history recall is very simple yet effective:
|
||||
|
||||
- As in any modern shell, the Up arrow recalls whole lines, starting from the last line executed. A single press replaces "!!", later presses replace "!-3" and the like.
|
||||
- If the line you want is far back in the history, type any part of the line and then press Up one or more times. This will constrain the recall to lines that include this text, and you will get to the line you want much faster. This replaces "!vi", "!?bar.c" and the like.
|
||||
- Alt+Up recalls individual arguments, starting from the last argument in the last line executed. A single press replaces "!$", later presses replace "!!:4" and the like.
|
||||
- If the argument you want is far back in history (e.g. 2 lines back - that's a lot of words!), type any part of it and then press Alt+Up. This will show only arguments containing that part and you will get what you want much faster. Try it out, this is very convenient!
|
||||
- If you want to reuse several arguments from the same line ("!!:3*" and the like), consider recalling the whole line and removing what you don't need (Alt+D and Alt+Backspace are your friends).
|
||||
|
||||
See <a href='index.html#editor'>documentation</a> for more details about line editing in fish.
|
||||
|
||||
*/
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
Sends the specified job to the foreground. While a foreground job is
|
||||
executed, fish is suspended. If no job is specified, the last job to be used is put in the foreground. If PID is specified, the job with the specified group id is put in the foreground.
|
||||
|
||||
The PID of the desired process is usually found by using process globbing.
|
||||
The PID of the desired process is usually found by using <a href="index.html#expand-process">process expansion</a>.
|
||||
|
||||
\subsection fg-example Example
|
||||
|
||||
|
||||
17
doc_src/fish_indent.txt
Normal file
17
doc_src/fish_indent.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
\section fish_indent fish_indent - indenter and prettifier
|
||||
|
||||
\subsection fish_indent-synopsis Synopsis
|
||||
<tt>fish_indent [options]</tt>
|
||||
|
||||
\subsection fish_indent-description Description
|
||||
|
||||
\c fish_indent is used to indent or otherwise prettify a piece of fish
|
||||
code. \c fish_indent reads commands from standard input and outputs
|
||||
them to standard output.
|
||||
|
||||
\c fish_indent understands the following options:
|
||||
|
||||
- <tt>-h</tt> or <tt>--help</tt> displays this help message and then exits
|
||||
- <tt>-i</tt> or <tt>--no-indent</tt> do not indent commands
|
||||
- <tt>-v</tt> or <tt>--version</tt> displays the current fish version and then exits
|
||||
|
||||
23
doc_src/fish_prompt.txt
Normal file
23
doc_src/fish_prompt.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
\section fish_prompt fish_prompt - define the apperance of the command line prompt
|
||||
|
||||
\subsection fish_promt-synopsis Synopsis
|
||||
<pre>function fish_prompt
|
||||
...
|
||||
end</pre>
|
||||
|
||||
\subsection fish_prompt-description Description
|
||||
|
||||
By defining the \c fish_prompt function, the user can choose a custom
|
||||
prompt. The \c fish_prompt function is executed when the prompt is to
|
||||
be shown, and the output is used as a prompt.
|
||||
|
||||
\subsection fish_prompt-example Example
|
||||
|
||||
A simple prompt:
|
||||
|
||||
<pre>
|
||||
function fish_prompt -d "Write out the prompt"
|
||||
printf '\%s\@\%s\%s\%s\%s> ' (whoami) (hostname|cut -d . -f 1) (set_color \$fish_color_cwd) (prompt_pwd) (set_color normal)
|
||||
end
|
||||
</pre>
|
||||
|
||||
@@ -11,7 +11,7 @@ not be executed at all.
|
||||
|
||||
\subsection for-example Example
|
||||
|
||||
The command
|
||||
The command
|
||||
|
||||
<tt>for i in foo bar baz; echo $i; end</tt>
|
||||
|
||||
@@ -21,5 +21,5 @@ would output:
|
||||
foo
|
||||
bar
|
||||
baz
|
||||
</pre>
|
||||
</pre>
|
||||
|
||||
|
||||
9
doc_src/funced.txt
Normal file
9
doc_src/funced.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
\section funced funced - edit a function interactively
|
||||
|
||||
\subsection funced-synopsis Synopsis
|
||||
<code>funced NAME</code>
|
||||
|
||||
\subsection funced-description Description
|
||||
|
||||
Use the funced command to interactively edit the definition of a
|
||||
function. If there is no function with the name specified, a skeleton function is inserted, if a function exist, the definion will be shown on the command line.
|
||||
12
doc_src/funcsave.txt
Normal file
12
doc_src/funcsave.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
\section funcsave funcsave - save the definition of a function to the users autoload directory
|
||||
|
||||
\subsection funcsave-synopsis Synopsis
|
||||
<tt>funcsave FUNCTION_NAME</tt>
|
||||
|
||||
\subsection funcsave-description Description
|
||||
|
||||
funcsave is used to save the current definition of a function to
|
||||
a file which will be autoloaded by current and future fish
|
||||
sessions. This can be useful if you have interactively created a new
|
||||
function and wish to save it for later use.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
\subsection function-description Description
|
||||
|
||||
- <code>-d DESCRIPTION</code> or \c --description=DESCRIPTION is a description of what the function does, suitable as a completion description
|
||||
- <code>-e</code> or <code>--on-event EVENT_NAME</code> tells fish to run this function when the specified named event is emitted. Fish internally generates named events e.g. when showing the prompt.
|
||||
- <code>-j PID</code> or <code> --on-job-exit PID</code> tells fish to run this function when the job with group id PID exits. Instead of PID, the string 'caller' can be specified. This is only legal when in a command substitution, and will result in the handler being triggered by the exit of the job which created this command substitution.
|
||||
- <code>-p PID</code> or <code> --on-process-exit PID</code> tells fish to run this function when the fish child process with process id PID exits
|
||||
- <code>-s</code> or <code>--on-signal SIGSPEC</code> tells fish to run this function when the signal SIGSPEC is delivered. SIGSPEC can be a signal number, or the signal name, such as SIGHUP (or just HUP)
|
||||
@@ -26,6 +27,11 @@ will write <code>hello</code> whenever the user enters \c hi.
|
||||
If the user enters any additional arguments after the function, they
|
||||
are inserted into the environment <a href="index.html#variables-arrays">variable array</a> argv.
|
||||
|
||||
By using one of the event handler switches, a function can be made to run automatically at specific events. The user may generate new events using the <a href='#emit">emit</a> builtin. Fish generates the following named events:
|
||||
|
||||
- \c fish_prompt, which is emitted whenever a new fish prompt is about to be displayed
|
||||
- \c fish_command_not_found, which is emitted whenever a command lookup failed
|
||||
|
||||
\subsection function-example Example
|
||||
|
||||
<pre>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
This builtin command is used to print or erase functions.
|
||||
|
||||
- <code>-a</code> or <code>--all</code> list all functions, even those whose name start with an underscore.
|
||||
- <code>-c OLDNAME NEWNAME</code> or <code>--copy OLDNAME NEWNAME</code> creates a new function named NEWNAME, using the definition of the OLDNAME function.
|
||||
- <code>-d DESCRIPTION</code> or <code>--description=DESCRIPTION</code> change the description of this function
|
||||
- <code>-e</code> or <code>--erase</code> causes the specified functions to be erased.
|
||||
- <code>-h</code> or <code>--help</code> display a help message and exit
|
||||
@@ -17,11 +18,14 @@ This builtin command is used to print or erase functions.
|
||||
The default behavior of \c functions when called with no arguments,
|
||||
is to print the names and definitions of all defined functions. If any
|
||||
non-switch parameters are given, only the definition of the specified
|
||||
functions are printed.
|
||||
functions are printed.
|
||||
|
||||
Automatically loaded functions can not be removed using functions
|
||||
-e. Either remove the definition file or change the
|
||||
$fish_function_path variable to remove autoloaded functions.
|
||||
|
||||
Function copies, created with -c, will not have any event/signal/on-exit
|
||||
notifications that the original may have had.
|
||||
|
||||
The exit status of the functions builtin is the number functions
|
||||
specified in the argument list that do not exist.
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
<tt>if</tt> will execute the command CONDITION. If the condition's
|
||||
exit status is 0, the commands COMMANDS_TRUE will execute. If the
|
||||
exit status is not 0 and <tt>else</tt> is given, COMMANDS_FALSE will
|
||||
be executed.
|
||||
be executed.
|
||||
|
||||
In order to use the exit status of mutiple commands as the condition
|
||||
In order to use the exit status of multiple commands as the condition
|
||||
of an if block, use <a href="#begin"><tt>begin; ...; end</tt></a> and
|
||||
the short circut commands <a href="commands.html#and">and</a> and <a
|
||||
the short circuit commands <a href="commands.html#and">and</a> and <a
|
||||
href="commands.html#or">or</a>.
|
||||
|
||||
The exit status of the last foreground command to exit can always be
|
||||
@@ -29,5 +29,5 @@ else
|
||||
end
|
||||
</pre>
|
||||
will print <tt>foo.txt exists</tt> if the file foo.txt
|
||||
exists and is a regular file, otherwise it will print
|
||||
exists and is a regular file, otherwise it will print
|
||||
<tt>foo.txt does not exist</tt>.
|
||||
|
||||
@@ -59,7 +59,7 @@ Here is a list of some useful commands:
|
||||
- \c mv, move (rename) files
|
||||
- \c cp, copy files
|
||||
- \c open, open files with the default application associated with each filetype
|
||||
- \c less, list the contents of files
|
||||
- \c less, list the contents of files
|
||||
|
||||
Commands and parameters are separated by the space character
|
||||
( ). Every command ends with either a newline (i.e. by pressing
|
||||
@@ -135,11 +135,15 @@ these characters, so called escape sequences are provided. These are:
|
||||
- <code>'\\\<'</code>, escapes the less than character
|
||||
- <code>'\\\>'</code>, escapes the more than character
|
||||
- <code>'\\^'</code>, escapes the circumflex character
|
||||
- <code>'\\&'</code>, escapes the ampersand character
|
||||
- <code>'\\;'</code>, escapes the semicolon character
|
||||
- <code>'\\"'</code>, escapes the quote character
|
||||
- <code>'\\''</code>, escapes the apostrophe character
|
||||
- <code>'\\x<i>xx</i>'</code>, where <code><i>xx</i></code> is a hexadecimal number, escapes the ascii character with the specified value. For example, \\x9 is the tab character.
|
||||
- <code>'\\X<i>xx</i>'</code>, where <code><i>xx</i></code> is a hexadecimal number, escapes a byte of data with the specified value. If you are using a mutibyte encoding, this can be used to enter invalid strings. Only use this if you know what you are doing.
|
||||
- <code>'\\<i>ooo</i>'</code>, where <code><i>ooo</i></code> is an octal number, escapes the ascii character with the specified value. For example, \\011 is the tab character.
|
||||
- <code>'\\u<i>xxxx</i>'</code>, where <code><i>xxxx</i></code> is a hexadecimal number, escapes the 16-bit unicode character with the specified value. For example, \\u9 is the tab character.
|
||||
- <code>'\\U<i>xxxxxxxx</i>'</code>, where <code><i>xxxxxxxx</i></code> is a hexadecimal number, escapes the 32-bit unicode character with the specified value. For example, \\U9 is the tab character.
|
||||
- <code>'\\u<i>xxxx</i>'</code>, where <code><i>xxxx</i></code> is a hexadecimal number, escapes the 16-bit Unicode character with the specified value. For example, \\u9 is the tab character.
|
||||
- <code>'\\U<i>xxxxxxxx</i>'</code>, where <code><i>xxxxxxxx</i></code> is a hexadecimal number, escapes the 32-bit Unicode character with the specified value. For example, \\U9 is the tab character.
|
||||
- <code>'\\c<i>x</i>'</code>, where <code><i>x</i></code> is a letter of the alphabet, escapes the control sequence generated by pressing the control key and the specified letter. For example, \\ci is the tab character
|
||||
|
||||
\subsection redirects IO redirection
|
||||
@@ -147,7 +151,7 @@ these characters, so called escape sequences are provided. These are:
|
||||
Most program use three types of input/output (IO), each represented by
|
||||
a number called a file descriptor (FD). These are:
|
||||
|
||||
- Standard input, FD 0, for reading, defaults to reading from the keyboard.
|
||||
- Standard input, FD 0, for reading, defaults to reading from the keyboard.
|
||||
- Standard output, FD 1, for writing, defaults to writing to the screen.
|
||||
- Standard error, FD 2, for writing errors and warnings, defaults to writing to the screen.
|
||||
|
||||
@@ -160,13 +164,13 @@ default through a simple mechanism called a redirection.
|
||||
An example of a file redirection is <code> echo hello \>output.txt</code>,
|
||||
which directs the output of the echo command to the file error.txt.
|
||||
|
||||
- To redirect standard input, write <code>\<SOURCE_FILE</code>
|
||||
- To redirect standard output, write <code>\>DESTINATION</code>
|
||||
- To redirect standard error, write <code>^DESTINATION</code>
|
||||
- To redirect standard input, write <code>\<SOURCE_FILE</code>
|
||||
- To redirect standard output, write <code>\>DESTINATION</code>
|
||||
- To redirect standard error, write <code>^DESTINATION</code>
|
||||
- To redirect standard output to a file which will be appended, write <code>\>\>DESTINATION_FILE</code>
|
||||
- To redirect standard error to a file which will be appended, write <code>^^DESTINATION_FILE</code>
|
||||
- To redirect standard error to a file which will be appended, write <code>^^DESTINATION_FILE</code>
|
||||
|
||||
<code>DESTINATION</code> can be one of the following:
|
||||
<code>DESTINATION</code> can be one of the following:
|
||||
|
||||
- A filename. The output will be written to the specified file.
|
||||
- An ampersand (\&) followed by the number of another file descriptor. The file descriptor will be a duplicate of the specified file descriptor.
|
||||
@@ -182,7 +186,7 @@ Any FD can be redirected in an arbitrary way by prefixing the
|
||||
redirection with the number of the FD.
|
||||
|
||||
- To redirect input of FD number N, write <code>N\<DESTINATION</code>
|
||||
- To redirect output of FD number N, write <code>N\>DESTINATION</code>
|
||||
- To redirect output of FD number N, write <code>N\>DESTINATION</code>
|
||||
- To redirect output of FD number N to a file which will be appended, write <code>N\>\>DESTINATION_FILE</code>
|
||||
|
||||
Example: <code>echo Hello 2\>-</code> and <code>echo Hello ^-</code> are
|
||||
@@ -230,7 +234,7 @@ Example:
|
||||
|
||||
<code>emacs \&</code>
|
||||
|
||||
will start the emacs text editor in the background.
|
||||
will start the emacs text editor in the background.
|
||||
|
||||
\subsection syntax-job-control Job control
|
||||
|
||||
@@ -306,7 +310,7 @@ a filename consisting of the name of the function plus the suffix
|
||||
|
||||
The default value for \$fish_function_path is \c ~/.config/fish/functions
|
||||
\c /etc/fish/functions \c /usr/share/fish/functions. The exact path
|
||||
to the last two of these may be slighly different depending on what
|
||||
to the last two of these may be slightly different depending on what
|
||||
install path prefix was chosen at configuration time. The rationale
|
||||
behind having three different directories is that the first one is for
|
||||
user specific functions, the second one is for system-wide additional
|
||||
@@ -323,10 +327,10 @@ function already be loaded, i.e. a circular dependency.
|
||||
\subsection syntax-conditional Conditional execution of code
|
||||
|
||||
There are four fish builtins that let you execute commands only if a
|
||||
specific criterion is met. These builtins are
|
||||
<a href="commands.html#if">if</a>,
|
||||
<a href="commands.html#switch">switch</a>,
|
||||
<a href="commands.html#and">and</a> and
|
||||
specific criterion is met. These builtins are
|
||||
<a href="commands.html#if">if</a>,
|
||||
<a href="commands.html#switch">switch</a>,
|
||||
<a href="commands.html#and">and</a> and
|
||||
<a href="commands.html#or">or</a>.
|
||||
|
||||
The \c switch command is used to execute one of possibly many blocks
|
||||
@@ -335,7 +339,7 @@ for <a href="commands.html#switch">switch</a> for more information.
|
||||
|
||||
The other conditionals use the <a href='#variables-status'>exit
|
||||
status</a> of a command to decide if a command or a block of commands
|
||||
should be executed. See the documentation for
|
||||
should be executed. See the documentation for
|
||||
<a href="commands.html#if">if</a>, <a href="commands.html#and">and</a>
|
||||
and <a href="commands.html#or">or</a> for more information.
|
||||
|
||||
@@ -392,13 +396,13 @@ These are the general purpose tab completions that \c fish provides:
|
||||
of these completions are simple options like the \c -l option for \c
|
||||
ls, but some are more advanced. The latter include:
|
||||
|
||||
- The programs 'man' and 'whatis' show all installed
|
||||
- The programs 'man' and 'whatis' show all installed
|
||||
manual pages as completions.
|
||||
- The 'make' program uses all targets in the Makefile in
|
||||
- The 'make' program uses all targets in the Makefile in
|
||||
the current directory as completions.
|
||||
- The 'mount' command uses all mount points specified in fstab as completions.
|
||||
- The 'ssh' command uses all hosts that are stored
|
||||
in the known_hosts file as completions. (see the ssh documentation for more information)
|
||||
- The 'ssh' command uses all hosts that are stored
|
||||
in the known_hosts file as completions. (see the ssh documentation for more information)
|
||||
- The 'su' command uses all users on the system as completions.
|
||||
- The \c apt-get, \c rpm and \c yum commands use all installed packages as completions.
|
||||
|
||||
@@ -415,7 +419,7 @@ this can be specified as <code>complete -c myprog -a 'start
|
||||
stop'</code>. The argument to the \c -a switch is always a single
|
||||
string. At completion time, it will be tokenized on spaces and tabs,
|
||||
and variable expansion, command substitution and other forms of
|
||||
parameter expansion will take place.
|
||||
parameter expansion will take place.
|
||||
|
||||
Fish has a special syntax to support specifying switches accepted by a
|
||||
command. The switches \c -s, \c -l and \c -o are used to specify a
|
||||
@@ -466,11 +470,11 @@ prints a list of all user groups with the groups members as description.
|
||||
|
||||
<pre>__fish_complete_pids</pre>
|
||||
|
||||
prints a list of all procceses IDs with the command name as description.
|
||||
prints a list of all processes IDs with the command name as description.
|
||||
|
||||
<pre>__fish_complete_suffix SUFFIX</pre>
|
||||
|
||||
performs file completion allowing only files ending in SUFFIX. The mimetype database is usded to find a suitable description.
|
||||
performs file completion allowing only files ending in SUFFIX. The mimetype database is used to find a suitable description.
|
||||
|
||||
<pre>__fish_complete_users</pre>
|
||||
|
||||
@@ -494,7 +498,7 @@ prints a list of all known network interfaces.
|
||||
<pre>__fish_print_packages</pre>
|
||||
|
||||
prints a list of all installed packages. This function currently handles
|
||||
debian, rpm and gentoo packages.
|
||||
Debian, rpm and Gentoo packages.
|
||||
|
||||
|
||||
|
||||
@@ -509,7 +513,7 @@ of the name of the command to complete and the suffix '.fish'.
|
||||
|
||||
The default value for \$fish_complete_path is ~/.config/fish/completions,
|
||||
/etc/fish/completions and /usr/share/fish/completions. The exact
|
||||
path to the last two of these may be slighly different depending on
|
||||
path to the last two of these may be slightly different depending on
|
||||
what install path prefix was chosen at configuration time. If a
|
||||
suitable file is found in one of these directories, it will be
|
||||
automatically loaded and the search will be stopped. The rationale
|
||||
@@ -519,20 +523,20 @@ completions and the last one is for default fish completions.
|
||||
|
||||
If you have written new completions for a common
|
||||
Unix command, please consider sharing your work by sending it to <a
|
||||
href='mailto: fish-users@lists.sf.net'>the fish mailinglist</a>.
|
||||
href='mailto: fish-users@lists.sf.net'>the fish mailing list</a>.
|
||||
|
||||
|
||||
\section expand Parameter expansion (Globbing)
|
||||
|
||||
When an argument for a program is given on the commandline, it
|
||||
undergoes the process of parameter expansion before it is sent on to
|
||||
the command. Parameter expansion is a powerful set of mechamisms that
|
||||
the command. Parameter expansion is a powerful set of mechanisms that
|
||||
allow you to expand the parameter in various ways, including
|
||||
performing wildcard matching on files, inserting the value of
|
||||
environment variables into the parameter or even using the output of
|
||||
another command as a parameter list.
|
||||
|
||||
\subsection expand-wildcard Wildcards
|
||||
\subsection expand-wildcard Wildcards
|
||||
|
||||
If a star (*) or a question mark (?) is present in the parameter, \c
|
||||
fish attempts to match the given parameter to any files in such a
|
||||
@@ -609,7 +613,7 @@ href="#variables"> Environment variables</a> section.
|
||||
Example:
|
||||
|
||||
<code> echo \$HOME</code> prints the home directory of the current
|
||||
user.
|
||||
user.
|
||||
|
||||
If you wish to combine environment variables with text, you can
|
||||
encase the variables within braces to embed a variable inside running
|
||||
@@ -620,9 +624,8 @@ The {$USER}san syntax might need a bit of an elaboration. Posix
|
||||
shells allow you to specify a variable name using '$VARNAME' or
|
||||
'${VARNAME}'. Fish supports the former, and has no support whatsoever
|
||||
for the latter or anything like it. So what is '{$VARNAME}' then?
|
||||
Well, '{WHATEVER}' is <a href='#brace'>brace expansion</a>, identical
|
||||
to that supported by e.g. bash. 'a{b,c}d' -> 'abd acd' works
|
||||
both in bash and on fish. So '{$VARNAME}' is a bracket-expansion with
|
||||
Well, '{WHATEVER}' is <a href='#brace'>brace expansion</a>, e.g. 'a{b,c}d' -> 'abd acd'.
|
||||
So '{$VARNAME}' is a bracket-expansion with
|
||||
only a single element, i.e. it becomes expanded to '$VARNAME', which
|
||||
will be variable expanded to the value of the variable 'VARNAME'. So
|
||||
you might think that the brackets don't actually do anything, and that
|
||||
@@ -684,12 +687,12 @@ The \% (percent) character at the beginning of a parameter followed by
|
||||
a string is expanded into a process id. The following expansions are
|
||||
performed:
|
||||
|
||||
- If the string is the entire word \c self, the shells pid is the result
|
||||
- If the string is the entire word \c self, the shells pid is the result.
|
||||
- Otherwise, if the string is the id of a job, the result is the process
|
||||
group id of the job.
|
||||
- Otherwise, if any child processes match the specified string, their
|
||||
pids are the result of the expansion.
|
||||
- Otherwise, if any processes owned by the user match the specified
|
||||
- Otherwise, if any child processes match the specified string, their
|
||||
pids are the result of the expansion.
|
||||
- Otherwise, if any processes owned by the user match the specified
|
||||
string, their pids are the result of the expansion.
|
||||
|
||||
This form of expansion is useful for commands like kill and fg, which
|
||||
@@ -739,19 +742,20 @@ expansion</a>.
|
||||
To set a variable value, use the <a href="commands.html#set"> \c set
|
||||
command</a>.
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
To set the variable \c smurf to the value \c blue, use the command
|
||||
<code>set smurf blue</code>.
|
||||
To set the variable \c smurf_color to the value \c blue, use the command
|
||||
<code>set smurf_color blue</code>.
|
||||
|
||||
After a variable has been set, you can use the value of a variable in
|
||||
the shell through <a href="expand-variable">variable expansion</a>.
|
||||
|
||||
Example:
|
||||
|
||||
To use the value of a the variable \c smurf, write $ (dollar symbol)
|
||||
To use the value of the variable \c smurf, write $ (dollar symbol)
|
||||
followed by the name of the variable, like <code>echo Smurfs are
|
||||
$smurf</code>, which would print the result 'Smurfs are blue'.
|
||||
usually $smurf_color</code>, which would print the result 'Smurfs are
|
||||
usually blue'.
|
||||
|
||||
\subsection variables-scope Variable scope
|
||||
|
||||
@@ -853,7 +857,7 @@ identical to the scoping rules for variables:
|
||||
|
||||
-# If a variable is explicitly set to either be exported or not exported, that setting will be honored.
|
||||
-# If a variable is not explicitly set to be exported or not exported, but has been previously defined, the previous exporting rule for the variable is kept.
|
||||
-# If a variable is not explicitly set to be either global or local and has never before been defined, the variable will not be exported.
|
||||
-# If a variable is not explicitly set to be either exported or not exported and has never before been defined, the variable will not be exported.
|
||||
|
||||
|
||||
\subsection variables-arrays Arrays
|
||||
@@ -867,8 +871,8 @@ echo $PATH[3]
|
||||
</pre>
|
||||
|
||||
Note that array indices start at 1 in fish, not 0, as is more common
|
||||
in other languages. This is because many common unix tools like seq
|
||||
are more suited to such use.
|
||||
in other languages. This is because many common Unix tools like seq
|
||||
are more suited to such use.
|
||||
|
||||
If you do not use any brackets, all the elements of the array will be
|
||||
written as separate items. This means you can easily iterate over an
|
||||
@@ -911,7 +915,7 @@ The user can change the settings of \c fish by changing the values of
|
||||
certain environment variables.
|
||||
|
||||
- \c BROWSER, which is the users preferred web browser. If this variable is set, fish will use the specified browser instead of the system default browser to display the fish documentation.
|
||||
- \c CDPATH, which is an array of directories in which to search for the new directory for the \c cd builtin.
|
||||
- \c CDPATH, which is an array of directories in which to search for the new directory for the \c cd builtin. The fish init files defined CDPATH to be a universal variable with the values . and ~.
|
||||
- A large number of variable starting with the prefixes \c fish_color and \c fish_pager_color. See <a href='#variables-color'>Variables for changing highlighting colors</a> for more information.
|
||||
- \c fish_greeting, which is the greeting message printed on startup.
|
||||
- \c LANG, \c LC_ALL, \c LC_COLLATE, \c LC_CTYPE, \c LC_MESSAGES, \c LC_MONETARY, \c LC_NUMERIC and \c LC_TIME set the language option for the shell and subprograms. See the section <a href='#variables-locale'>Locale variables</a> for more information.
|
||||
@@ -920,22 +924,30 @@ certain environment variables.
|
||||
|
||||
\c fish also sends additional information to the user through the
|
||||
values of certain environment variables. The user can not change the
|
||||
values of most of these variables.
|
||||
values of most of these variables.
|
||||
|
||||
- \c _, which is the name of the currently running command.
|
||||
- \c argv, which is an array of arguments to the shell or function. \c argv is only defined when inside a function call, or if fish was invoked with a list of arguments, like 'fish myscript.fish foo bar'. This variable can be changed by the user.
|
||||
- \c history, which is an array containing the last commands that where entered.
|
||||
- \c HOME, which is the users home directory. This variable can only be changed by the root user.
|
||||
- \c PWD, which is the current working directory.
|
||||
- \c status, which is the exit status of the last foreground job to exit.
|
||||
- \c PWD, which is the current working directory.
|
||||
- \c status, which is the exit status of the last foreground job to exit. If the job was terminated through a signal, the exit status will be 128 plus the signal number.
|
||||
- \c USER, which is the username. This variable can only be changed by the root user.
|
||||
|
||||
The names of these variables are mostly derived from the csh family of
|
||||
shells and differ from the ones used by Bourne style shells such as
|
||||
bash. The csh names where chosen because Bourne style names, such as
|
||||
?, * and @ lead to significantly less readable code, and much larger
|
||||
discoverability problems, and given the existence of tab completion,
|
||||
the keystroke savings are minimal.
|
||||
|
||||
Variables whose name are in uppercase are exported to the commands
|
||||
started by fish, those in lowercase are not exported. This rule is not
|
||||
enforced by fish, but it is good coding practice to use casing to
|
||||
distinguish between exported and unexported variables. \c fish also
|
||||
uses several variables internally. Such variables are prefixed with
|
||||
the string __FISH or __fish. These should be ignored by the user.
|
||||
the string __FISH or __fish. These should never be used by the
|
||||
user. Changing their value may break fish.
|
||||
|
||||
\subsection variables-status The status variable
|
||||
|
||||
@@ -953,10 +965,13 @@ If fish encounters a problem while executing a command, the status
|
||||
variable may also be set to a specific value:
|
||||
|
||||
- 1 is the generally the exit status from fish builtins if they where supplied with invalid arguments
|
||||
- 125 means an unknown error occured while trying to execute the command
|
||||
- 126 means that the command was not executed because none of the wildcards in the command produced any matches
|
||||
- 124 means that the command was not executed because none of the wildcards in the command produced any matches
|
||||
- 125 means that while an executable with the specified name was located, the operating system could not actually execute the command
|
||||
- 126 means that while a file with the specified name was located, it was not executable
|
||||
- 127 means that no function, builtin or command with the given name could be located
|
||||
|
||||
If a process exits through a signal, the exit status will be 128 plus the number of the signal.
|
||||
|
||||
\subsection variables-color Variables for changing highlighting colors
|
||||
|
||||
The colors used by fish for syntax highlighting can be configured by
|
||||
@@ -965,7 +980,7 @@ variables can be one of the colors accepted by the <a
|
||||
href='commands.html#set_color'>set_color</a> command. The \c --bold
|
||||
or \c -b switches accepted by \c set_color are also accepted.
|
||||
|
||||
The following variables are available to change the highligting colors
|
||||
The following variables are available to change the highlighting colors
|
||||
in fish:
|
||||
|
||||
- \c fish_color_normal, the default color
|
||||
@@ -1012,7 +1027,7 @@ variables set the specified aspect of the locale information. LANG
|
||||
is a fallback value, it will be used if none of the LC_ variables are
|
||||
specified.
|
||||
|
||||
\section builtin-overview Builtins
|
||||
\section builtin-overview Builtins
|
||||
|
||||
Many other shells have a large library of builtin commands. Most of
|
||||
these commands are also available as standalone commands, but have
|
||||
@@ -1030,7 +1045,7 @@ switch of the command.
|
||||
|
||||
The \c fish editor features copy and paste, a searchable history and
|
||||
many editor functions that can be bound to special keyboard
|
||||
shortcuts. The most important keybinding is probably the tab key, which is bound to the complete function.
|
||||
shortcuts. The most important keybinding is probably the tab key, which is bound to the complete function.
|
||||
Here are some of the commands available in the editor:
|
||||
|
||||
- Tab completes the current token
|
||||
@@ -1040,7 +1055,7 @@ Here are some of the commands available in the editor:
|
||||
- Alt-left and Alt-right moves one word left or right, or moves forward/backward in the directory history if the commandline is empty
|
||||
- Up and down search the command history for the previous/next command containing the string that was specified on the commandline before the search was started. If the commandline was empty when the search started, all commands match. See the <a href='#history'>history </a>section for more information on history searching.
|
||||
- Alt-up and Alt-down search the command history for the previous/next token containing the token under the cursor before the search was started. If the commandline was not on a token when the search started, all tokens match. See the <a href='#history'>history </a>section for more information on history searching.
|
||||
- Delete and backspace removes one character forwards or backwards respecitvely
|
||||
- Delete and backspace removes one character forwards or backwards respectively
|
||||
- Ctrl-c deletes entire line
|
||||
- Ctrl-d delete one character to the right of the cursor, unless the buffer is empty, in which case the shell will exit
|
||||
- Ctrl-k move contents from the cursor to the end of line to the <a href="#killring">killring</a>
|
||||
@@ -1048,18 +1063,12 @@ Here are some of the commands available in the editor:
|
||||
- Ctrl-l clear and repaint screen
|
||||
- Ctrl-w move previous word to the <a href="#killring">killring</a>
|
||||
- Alt-d move next word to the <a href="#killring">killring</a>
|
||||
- Alt-w prints a short description of the command under the cursor
|
||||
- Alt-l lists the contents of the current directory, unless the cursor is over a directory argument, in which case the contents of that directory will be listed
|
||||
- Alt-w prints a short description of the command under the cursor
|
||||
- Alt-l lists the contents of the current directory, unless the cursor is over a directory argument, in which case the contents of that directory will be listed
|
||||
- Alt-p adds the string '| less;' to the end of the job under the cursor. The result is that the output of the command will be paged.
|
||||
|
||||
You can change these key bindings by making an inputrc file. To do
|
||||
this, copy the file /etc/fish/fish_inputrc to your home directory and
|
||||
rename it to '.config/fish/fish_inputrc'. Now you can edit the file
|
||||
to change your key bindings. The file format of this file is described
|
||||
in the manual page for readline. Use the command <code>man readline</code>
|
||||
to read up on this syntax. Please note that the list of key binding
|
||||
functions in fish is different to that offered by readline. Currently,
|
||||
the following functions are available:
|
||||
You can change these key bindings using the
|
||||
<a href="commands.html#bind">bind</a> builtin command.
|
||||
|
||||
|
||||
- \c backward-char, moves one character to the left
|
||||
@@ -1086,13 +1095,11 @@ the following functions are available:
|
||||
- \c yank, insert the latest entry of the killring into the buffer
|
||||
- \c yank-pop, rotate to the previous entry of the killring
|
||||
|
||||
You can also bind a pice of shellscript to a key using the same
|
||||
syntax. For example, the Alt-p functionality described above is
|
||||
implemented using the following keybinding.
|
||||
If such a script produces output, the script needs to finish by
|
||||
calling 'commandline -f repaint' in order to tell fish that a repaint
|
||||
is in order.
|
||||
|
||||
<pre>"\M-p": if commandline -j|grep -v 'less *$' >/dev/null; commandline -aj "|less;"; end</pre>
|
||||
|
||||
\subsection killring Copy and paste (Kill Ring)
|
||||
\subsection killring Copy and paste (Kill Ring)
|
||||
|
||||
\c fish uses an Emacs style kill ring for copy and paste
|
||||
functionality. Use Ctrl-K to cut from the current cursor position to
|
||||
@@ -1103,7 +1110,7 @@ Meta-Y to rotate to the previous kill.
|
||||
|
||||
If the environment variable DISPLAY is set, \c fish will try to
|
||||
connect to the X-windows server specified by this variable, and use
|
||||
the clipboard on the X server for copying and pasting.
|
||||
the clipboard on the X server for copying and pasting.
|
||||
|
||||
\subsection history Searchable history
|
||||
|
||||
@@ -1138,7 +1145,7 @@ than a single line:
|
||||
|
||||
- Pressing the enter key while a block of commands is unclosed, i.e. when one or more block commands such as 'for', 'begin' or 'if' do not have a corresponding 'end' command.
|
||||
- Pressing Alt-enter instead of pressing the enter key.
|
||||
- By backslash escaping a newline, i.e. by inserting a backslash (\\) character pefore pressing the enter key.
|
||||
- By backslash escaping a newline, i.e. by inserting a backslash (\\) character before pressing the enter key.
|
||||
|
||||
The fish commandline editor works exactly the same in single line mode
|
||||
and in multiline mode. To move between lines use the left and right
|
||||
@@ -1154,7 +1161,7 @@ graphical user interface from the terminal, and then be able to
|
||||
continue using the shell. In such cases, there are several ways in
|
||||
which the user can change <code>fish</code>'s behavior.
|
||||
|
||||
-# By ending a command with the \& (ampersand) symbol, the user tells \c fish to put the specified command into the background. A background process will be run simultaneous with \c fish. \c fish will retain control of the terminal, so the program will not be able to read from the keyboard.
|
||||
-# By ending a command with the \& (ampersand) symbol, the user tells \c fish to put the specified command into the background. A background process will be run simultaneous with \c fish. \c fish will retain control of the terminal, so the program will not be able to read from the keyboard.
|
||||
-# By pressing ^Z, the user stops a currently running foreground program and returns control to \c fish. Some programs do not support this feature, or remap it to another key. Gnu emacs uses ^X z to stop running.
|
||||
-# By using the <a href="commands.html#fg">fg</a> and <a href="commands.html#bg">bg</a> builtin commands, the user can send any currently running job into the foreground or background.
|
||||
|
||||
@@ -1230,28 +1237,6 @@ Issuing <code>set fish_color_error black --background=red
|
||||
--bold</code> will make all commandline errors be written in a black,
|
||||
bold font, with a red background.
|
||||
|
||||
\subsection prompt Programmable prompt
|
||||
|
||||
By defining the \c fish_prompt function, the user can choose a custom
|
||||
prompt. The \c fish_prompt function is executed and the output is used
|
||||
as a prompt.
|
||||
|
||||
Example:
|
||||
<p>
|
||||
The default \c fish prompt is
|
||||
</p>
|
||||
<p>
|
||||
<pre>
|
||||
function fish_prompt -d "Write out the prompt"
|
||||
printf '\%s\@\%s\%s\%s\%s> ' (whoami) (hostname|cut -d . -f 1) (set_color \$fish_color_cwd) (prompt_pwd) (set_color normal)
|
||||
end
|
||||
</pre>
|
||||
|
||||
where \c prompt_pwd is a shellscript function that displays a condensed version of the current working directory.
|
||||
|
||||
</p>
|
||||
|
||||
|
||||
\subsection title Programmable title
|
||||
|
||||
When using most virtual terminals, it is possible to set the message
|
||||
@@ -1261,11 +1246,11 @@ fish_title function is executed before and after a new command is
|
||||
executed or put into the foreground and the output is used as a
|
||||
titlebar message. The $_ environment variable will always contain the
|
||||
name of the job to be put into the foreground (Or 'fish' if control is
|
||||
returning to the shell) when the fish_prompt function is called.
|
||||
returning to the shell) when the \c fish_prompt function is called.
|
||||
|
||||
Example:
|
||||
<p>
|
||||
The default \c fish title is
|
||||
The default \c fish title is
|
||||
</p>
|
||||
<p>
|
||||
<pre>
|
||||
@@ -1276,6 +1261,12 @@ end
|
||||
</pre>
|
||||
</p>
|
||||
|
||||
\subsection greeting Configurable greeting
|
||||
|
||||
If a function named fish_greeting exists after initialization, it will
|
||||
be run when entering interactive mode. Otherwise,if an environment
|
||||
variable named fish_greeting exists, it will be printed.
|
||||
|
||||
\subsection event Event handlers
|
||||
|
||||
When defining a new function in fish, it is possible to make it into an
|
||||
@@ -1285,6 +1276,8 @@ specific event takes place. Events that can trigger a handler currently are:
|
||||
- When a signal is delivered
|
||||
- When a process or job exits
|
||||
- When the value of a variable is updated
|
||||
- When the prompt is about to be shown
|
||||
- When a command lookup fails
|
||||
|
||||
Example:
|
||||
|
||||
@@ -1299,11 +1292,25 @@ For more information on how to define new event handlers, see the
|
||||
documentation for the <a href='commands.html#function'>function</a>
|
||||
command.
|
||||
|
||||
\subsection debugging Debugging fish scripts
|
||||
|
||||
Fish includes a built in debugger. The debugger allows you to stop
|
||||
execution of a script at an arbitrary point and launch a prompt. This
|
||||
prompt can then be used to check or change the value of any variables
|
||||
or perform any shellscript command. To resume normal execution of the
|
||||
script, simply exit the prompt.
|
||||
|
||||
To start the debugger, simply call the builtin command
|
||||
'breakpoint'. The default action of the TRAP signal is to call this
|
||||
builtin, so a running script can be debugged by sending it the TRAP
|
||||
signal. Once in the debugger, it is easy to insert new breakpoints by
|
||||
using the funced function to edit the definition of a function.
|
||||
|
||||
\section issues Common issues with fish
|
||||
|
||||
If you install fish in your home directory, fish will not work
|
||||
correctly for any other user than yourself. This is because fish needs
|
||||
its initalization files to function properly. To solve this
|
||||
its initialization files to function properly. To solve this
|
||||
problem, either copy the initialization files to each fish users home
|
||||
directory, or install them in /etc.
|
||||
|
||||
@@ -1315,7 +1322,7 @@ making a translation. Currently, only the shell itself can be
|
||||
translated, a future version of fish should also include translated
|
||||
manuals.
|
||||
|
||||
To make a translation of fish, you will first need the sourcecode,
|
||||
To make a translation of fish, you will first need the source code,
|
||||
available from the <a href='http://www.fishshell.org'>fish
|
||||
homepage</a>. Download the latest version, and then extract it using a
|
||||
command like <code>tar -zxf fish-VERSION.tar.gz</code>.
|
||||
@@ -1323,7 +1330,7 @@ command like <code>tar -zxf fish-VERSION.tar.gz</code>.
|
||||
Next, cd into the newly created fish directory using <code>cd
|
||||
fish-VERSION</code>.
|
||||
|
||||
You will now need to configure the sourcecode using the command
|
||||
You will now need to configure the source code using the command
|
||||
<code>./configure</code>. This step might take a while.
|
||||
|
||||
Before you continue, you will need to know the ISO 639 language code
|
||||
@@ -1331,7 +1338,7 @@ of the language you are translating to. These codes can be found <a
|
||||
href='http://www.w3.org/WAI/ER/IG/ert/iso639.htm'>here</a>. For
|
||||
example, the language code for Uighur is ug.
|
||||
|
||||
Now you have the sourcecode and it is properly configured. Lets start
|
||||
Now you have the source code and it is properly configured. Lets start
|
||||
translating. To do this, first create an empty translation table for
|
||||
the language you wish to translate to by writing <code>make
|
||||
po/[LANGUAGE CODE].po</code> in the fish terminal. For example, if you
|
||||
@@ -1351,7 +1358,7 @@ msgstr ""
|
||||
</pre>
|
||||
|
||||
The first line is the English string to translate, the second line
|
||||
should contain your translation. For example, in swedish the above
|
||||
should contain your translation. For example, in Swedish the above
|
||||
might become:
|
||||
|
||||
<pre>
|
||||
@@ -1374,29 +1381,20 @@ href='fish-users@lists.sf.net'>fish-users@lists.sf.net</a>.
|
||||
|
||||
\subsection todo-features Missing features
|
||||
|
||||
- A limited interactive mode for really dumb terminals
|
||||
- The completion autoloader does not remember which completions where actually autoloaded, and may unload manually specified completions.
|
||||
- Use a struct to describe a possible completion instead of a weirdly formated string
|
||||
- Complete vi-mode key bindings
|
||||
- More completions (for example xterm, vim,
|
||||
konsole, gnome-terminal, cron,
|
||||
- More completions (for example konsole, gnome-terminal,
|
||||
rlogin, rsync, arch, finger, bibtex, aspell, xpdf,
|
||||
compress, wine, xmms, dig, batch, cron,
|
||||
compress, wine, dig, batch,
|
||||
g++, javac, java, gcj, lpr, doxygen, whois)
|
||||
- Undo support
|
||||
- Check keybinding commands for output - if nothing has happened, don't repaint to reduce flicker
|
||||
- wait shellscript
|
||||
- Support for the screen clipboard
|
||||
- It should be possible to test in a script if a function is autoloaded or manually defined
|
||||
- A pretty-printer. It should among other things be able to indent a piece of code.
|
||||
- Up/down to move between lines in multiline mode
|
||||
- a 'funced' function, which works like the vared function. Needs the above three features in order to work well.
|
||||
- The validator should be better about error reporting unclosed quotes. They are usually reported as something else.
|
||||
|
||||
\subsection todo-possible Possible features
|
||||
|
||||
- tab completion could use smart casing
|
||||
- mouse support like zsh has with http://stchaz.free.fr/mouse.zsh
|
||||
- mouse support like zsh has with http://stchaz.free.fr/mouse.zsh
|
||||
installed would be awesome
|
||||
- suggest a completion on unique matches by writing it out in an understated color
|
||||
- Highlight beginning/end of block when moving over a block command
|
||||
@@ -1405,42 +1403,41 @@ g++, javac, java, gcj, lpr, doxygen, whois)
|
||||
- Descriptions for variables using 'set -d'.
|
||||
- Parse errors should when possible honor IO redirections
|
||||
- Support for writing strings like /u/l/b/foo and have them expand to /usr/local/bin/foo - perhaps through tab expansion
|
||||
- Autoreload inputrc-file on updates
|
||||
- Right-side prompt
|
||||
- Selectable completions in the pager
|
||||
- Per process output redirection
|
||||
- Reduce the space of the pager by one line to allow the commandline to remain visible.
|
||||
- down-arrow could be used to save the current command to the history. Or give the next command in-sequnce. Or both.
|
||||
- Drop support for inputrc-files. Use shellscripts and the bind builtin. Also, redo the syntax for the bind builtin to something more sane.
|
||||
- down-arrow could be used to save the current command to the history. Or give the next command in-sequence. Or both.
|
||||
- History could reload itself when the file is updated. This would need to be done in a clever way to avoid chain reactions
|
||||
- The error function should probably be moved into it's own library, and be made mere general purpose.
|
||||
- The code validation functions should be moved from the parser to parse_util.
|
||||
- The parser_is_* functions should be moved to parse_util. Possibly, they should be made into a single function, i.e. parse_util_classify( "begin", BLOCK_COMMAND);
|
||||
- Try to remove more malloc calls to reduce memory usage. The time_t arrays used by the autoloader sound like a good candidate.
|
||||
- Try to remove more malloc calls to reduce memory usage. The time_t arrays used by the autoloader sound like a good candidate.
|
||||
- The code validator should warn about unknown commands.
|
||||
- Auto-newlines
|
||||
- A fault injector could be written to increase robustness and testing of error recovery paths
|
||||
- The parser/validator could be more clever in order to make things like writing 'function --help' work as expected
|
||||
- Some event handler functions make much more sense as oneshots - maybe they should be automatically deleted after firing?
|
||||
- exec_subshell should be either merged with eval or moved to parser.c
|
||||
- Don't use expand_string to perform completions. wildcard_complete can be called directly, the brace expansion handling should be universal, and the process expansion can be moved to complete.c.
|
||||
- Make the history search support incremental searching
|
||||
- An automatic logout feature
|
||||
- Make tab completions completely silent by default, i.e. kill stderr when running completion commands. This needs to be overridalbe for debugging purposes.
|
||||
- Move history to an environment variable
|
||||
|
||||
\subsection bugs Known bugs and issues
|
||||
|
||||
- Suspending and then resuming pipelines containing a builtin or a shellscript function is broken. Ideally, the exec function in exec.c should be able to resume execution of a partially executed job.
|
||||
- delete-word is broken on the commandline 'sudo update-alternatives --config x-'
|
||||
- When a builtin has its output redirected to a file, and the builtin does not produce any IO, then the file is never opened. Thus tha file may not be cleared.
|
||||
- No '--' completion
|
||||
- else is not indented properly
|
||||
- if an if fails inside an if, the out if's else may trigger
|
||||
- Sometimes autoheader needs to be run on a fresh tarball. Fix dates before creating tarballs.
|
||||
- The completion autoloader does not remember which completions where actually autoloaded, and may unload manually specified completions.
|
||||
- There have been stray reports of issues with strange values of the PATH variable during startup.
|
||||
- bindings in config.fish are overwritten by default key bindings.
|
||||
- Adding 'bind -k ...' doesn't overwrite non-keybinding binds of the same sequence.
|
||||
- History file does not remove duplicates.
|
||||
- History file should apply some kind of maximum history length.
|
||||
- Older versions of Doxygen has bugs in the man-page generation which cause the builtin help to render incorrectly. Version 1.2.14 is known to have this problem.
|
||||
|
||||
If you think you have found a bug not described here, please send a
|
||||
report to <a href="mailto:fish-users@lists.sf.net">fish-users@lists.sf.net</a>.
|
||||
|
||||
|
||||
\subsection issues Known issues
|
||||
|
||||
Older versions of Doxygen has bugs in the man-page generation which
|
||||
cause the builtin help to render incorrectly. Version 1.2.14 is known
|
||||
to have this problem.
|
||||
|
||||
*/
|
||||
|
||||
@@ -1,28 +1,11 @@
|
||||
/** \page license Licenses
|
||||
|
||||
Fish Copyright (C) 2005-2006 Axel Liljencrantz. Fish is released under
|
||||
<h2>License for fish</h2>
|
||||
|
||||
Fish Copyright (C) 2005-2009 Axel Liljencrantz. Fish is released under
|
||||
the GNU General Public License, version 2. The license agreement is
|
||||
included below.
|
||||
|
||||
Fish contains code under the BSD license, namely versions of the
|
||||
two functions strlcat and strlcpy, modified for use with wide
|
||||
character strings. This code is copyrighted by Todd C. Miller. The
|
||||
license agreement is included below.
|
||||
|
||||
The XSel command, written and copyrighted by Conrad Parker, is
|
||||
distributed together with, and used by fish. It is released under the MIT
|
||||
license. The license agreement is included below.
|
||||
|
||||
The xdgmime library, written and copyrighted by Red Hat, Inc, is used
|
||||
by the mimedb command, which is a part of fish. It is released under
|
||||
the LGPL. The license agreement is included below.
|
||||
|
||||
Fish contains code from the glibc library, namely the wcstok
|
||||
function. This code is licensed under the LGPL. The license agreement
|
||||
is included below.
|
||||
|
||||
|
||||
<HR>
|
||||
|
||||
<H2><A NAME="SEC1" HREF="gpl.html#TOC1">GNU GENERAL PUBLIC LICENSE</A></H2>
|
||||
<P>
|
||||
@@ -31,7 +14,7 @@ Version 2, June 1991
|
||||
</P>
|
||||
|
||||
<PRE>
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
@@ -464,7 +447,7 @@ PERFORMANCE OF THIS SOFTWARE.
|
||||
<h2>License for XSel</h2>
|
||||
|
||||
The XSel command, written and copyrighted by Conrad Parker, is
|
||||
distributed together with \c fish.
|
||||
distributed together with \c fish.
|
||||
|
||||
|
||||
It is Copyright (C) 2001 Conrad Parker <conrad@vergenet.net>
|
||||
@@ -480,6 +463,18 @@ without express or implied warranty.
|
||||
|
||||
<HR>
|
||||
|
||||
<h2>License for xdgmime and glibc</h2>
|
||||
|
||||
The xdgmime library, written and copyrighted by Red Hat, Inc, is used
|
||||
by the mimedb command, which is a part of fish. It is released under
|
||||
the LGPL, version 2 or later, or under the Academic Free License,
|
||||
version 2. Version 2 of the LGPL license agreement is included below.
|
||||
|
||||
Fish contains code from the glibc library, namely the wcstok
|
||||
function. This code is licensed under the LGPL, version 2 or
|
||||
later. Version 2 of the LPGL license agreement is included below.
|
||||
|
||||
|
||||
<H2><A NAME="SEC1" HREF="#TOC1">GNU LESSER GENERAL PUBLIC LICENSE</A></H2>
|
||||
|
||||
<P>
|
||||
@@ -807,7 +802,7 @@ of these things:
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
|
||||
<LI><STRONG>b)</STRONG> Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
\subsection math-description Description
|
||||
|
||||
math is used to perform mathematical calcualtions. It is only a very
|
||||
math is used to perform mathematical calculations. It is only a very
|
||||
thin wrapper for the bc program, that makes it possible to specify an
|
||||
expression from the command line without using non-standard extensions
|
||||
or a pipeline. Simply use a command like <code>math 1+1</code>.
|
||||
or a pipeline. Simply use a command like <code>math 1+1</code>.
|
||||
|
||||
For a description of the syntax supported by math, see the manual for
|
||||
the bc program. Keep in mind that parameter expansion takes place on
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
\subsection mimedb-description Description
|
||||
|
||||
- \c FILES is a list of files to analyse
|
||||
- \c FILES is a list of files to analyse
|
||||
- \c -t, \c --input-file-data the specified files type should be determined both by their filename and by their contents (Default)
|
||||
- \c -f, \c --input-filename the specified files type should be determined by their filename
|
||||
- \c -i, \c --input-mime the arguments are not files but mimetypes
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
The mimedb command is used to query the mimetype database and the
|
||||
.desktop files installed on the system in order to find information on
|
||||
a file. The information that mimedb can retrive includes the mimetype
|
||||
a file. The information that mimedb can retrieve includes the mimetype
|
||||
for a file, a description of the type and what its default action
|
||||
is. mimedb can also be used to launch the default action for this
|
||||
file.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
\subsection not-description Description
|
||||
|
||||
The \c not builtin is used to negate the exit status of another command.
|
||||
The \c not builtin is used to negate the exit status of another command.
|
||||
|
||||
\subsection not-example Example
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
\section open open - open file in it's default application
|
||||
\section open open - open file in its default application
|
||||
|
||||
\subsection open-synopsis Synopsis
|
||||
<tt>open FILES...</tt>
|
||||
|
||||
\subsection open-description Description
|
||||
|
||||
The \c open command is used to open a file in it's default application. \c open is implemented using the <a href="commands.html#mimedb">mimedb</a> command.
|
||||
The \c open command is used to open a file in its default application. \c open is implemented using the \c xdg-open command if it exists, or else the <a href="commands.html#mimedb">mimedb</a> command.
|
||||
|
||||
\subsection open-example Example
|
||||
|
||||
<tt>open *.txt</tt> opens all the text files in the current directory using your systems default text editor.
|
||||
<tt>open *.txt</tt> opens all the text files in the current directory using your system's default text editor.
|
||||
|
||||
@@ -17,7 +17,7 @@ variable.
|
||||
\subsection or-example Example
|
||||
|
||||
The following code runs the \c make command to build a program, if the
|
||||
build succceds, the program is installed. If either step fails,
|
||||
build succeeds, the program is installed. If either step fails,
|
||||
<tt>make clean</tt> is run, which removes the files created by the
|
||||
build process
|
||||
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
\subsection popd-synopsis Synopsis
|
||||
<tt>popd</tt>
|
||||
|
||||
\subsection popd-description Description
|
||||
<tt>popd</tt> removes the top directory from the directory stack and
|
||||
\subsection popd-description Description
|
||||
<tt>popd</tt> removes the top directory from the directory stack and
|
||||
cd's to the new top directory.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
\section prevd prevd - move backward through direcotry history
|
||||
\section prevd prevd - move backward through directory history
|
||||
|
||||
\subsection prevd-synopsis Synopsis
|
||||
<tt>prevd [-l | --list] [pos]</tt>
|
||||
|
||||
\subsection prevd-description Description
|
||||
\subsection prevd-description Description
|
||||
|
||||
<tt>prevd</tt> moves backwards <tt>pos</tt> positions in the history
|
||||
of visited directories; if the beginning of the history has been hit,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
\subsection pushd-synopsis Synopsis
|
||||
<tt>pushd [DIRECTORY]</tt>
|
||||
|
||||
\subsection pushd-description Description
|
||||
\subsection pushd-description Description
|
||||
The <tt>pushd</tt> function adds DIRECTORY to the top of the directory stack
|
||||
and makes it the current directory. Use <tt>popd</tt> to pop it off and and
|
||||
return to the original directory.
|
||||
|
||||
@@ -21,4 +21,4 @@ for i in (seq (random) -1 1)
|
||||
echo $i
|
||||
sleep
|
||||
end
|
||||
</pre>
|
||||
</pre>
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
\subsection read-description Description
|
||||
|
||||
The <tt>read</tt> builtin causes fish to read one line from standard
|
||||
input and store the result in one or more environment variables.
|
||||
input and store the result in one or more environment variables.
|
||||
|
||||
- <tt>-c CMD</tt> or <tt>--command=CMD</tt> specifies that the initial string in the interactive mode command buffer should be CMD.
|
||||
- <tt>-e</tt> or <tt>--export</tt> specifies that the variables will be exported to subshells.
|
||||
- <tt>-g</tt> or <tt>--global</tt> specifies that the variables will be made global.
|
||||
- <tt>-m NAME</tt> or <tt>--mode-name=NAME</tt> specifies that the name NAME should be used to save/load the hiustory file. If NAME is fish, the regular fish history will be available.
|
||||
- <tt>-m NAME</tt> or <tt>--mode-name=NAME</tt> specifies that the name NAME should be used to save/load the history file. If NAME is fish, the regular fish history will be available.
|
||||
- <tt>-p PROMPT_CMD</tt> or <tt>--prompt=PROMPT_CMD</tt> specifies that the output of the shell command PROMPT_CMD should be used as the prompt for the interactive mode prompt. The default prompt command is <tt>set_color green; echo read; set_color normal; echo "> "</tt>.
|
||||
- <code>-s</code> or <code>--shell</code> Use syntax highlighting, tab completions and command termination suitable for entering shellscript code
|
||||
- <code>-u</code> or <code>--unexport</code> causes the specified environment not to be exported to child processes
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
\subsection return-synopsis Synopsis
|
||||
<tt>function NAME; [COMMANDS...;] return [STATUS]; [COMMANDS...;] end</tt>
|
||||
|
||||
\subsection return-description Description
|
||||
\subsection return-description Description
|
||||
|
||||
The \c return builtin is used to halt a currently running function. It
|
||||
is usually added inside of a conditional block such as an <a
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
\section save_function save_function - save the definition of a function to the users autoload directory
|
||||
|
||||
\subsection save_function-synopsis Synopsis
|
||||
<tt>save_function FUNCTION_NAME</tt>
|
||||
|
||||
\subsection save_function-description Description
|
||||
|
||||
save_function is used to save the current definition of a function to
|
||||
a file which will be autoloaded by current and future fish
|
||||
sessions. This can be useful if you have interactively created a new
|
||||
function and wish to save it for later use.
|
||||
|
||||
@@ -43,7 +43,7 @@ the last index of an array.
|
||||
The scoping rules when creating or updating a variable are:
|
||||
|
||||
-# If a variable is explicitly set to either universal, global or local, that setting will be honored. If a variable of the same name exists in a different scope, that variable will not be changed.
|
||||
-# If a variable is not explicitly set to be either universal, global or local, but has been previously defined, the previos variable scope is used.
|
||||
-# If a variable is not explicitly set to be either universal, global or local, but has been previously defined, the previous variable scope is used.
|
||||
-# If a variable is not explicitly set to be either universal, global or local and has never before been defined, the variable will be local to the currently executing functions. If no function is executing, the variable will be global.
|
||||
|
||||
The exporting rules when creating or updating a variable are identical
|
||||
@@ -51,7 +51,7 @@ to the scoping rules for variables:
|
||||
|
||||
-# If a variable is explicitly set to either be exported or not exported, that setting will be honored.
|
||||
-# If a variable is not explicitly set to be exported or not exported, but has been previously defined, the previous exporting rule for the variable is kept.
|
||||
-# If a variable is not explicitly set to be either global or local and has never before been defined, the variable will not be exported.
|
||||
-# If a variable is not explicitly set to be either exported or unexported and has never before been defined, the variable will not be exported.
|
||||
|
||||
In query mode, the scope to be examined can be specified.
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
Change the foreground and/or background color of the terminal.
|
||||
COLOR is one of black, red, green, brown, yellow, blue, magenta,
|
||||
purple, cyan, white and normal.
|
||||
purple, cyan, white and normal.
|
||||
|
||||
- \c -b, \c --background Set the background color
|
||||
- \c -c, \c --print-colors Prints a list of all valid color names
|
||||
@@ -28,3 +28,9 @@ result in a white font color.
|
||||
Not all terminal emulators support all these features. This is not a
|
||||
bug in set_color but a missing feature in the terminal emulator.
|
||||
|
||||
set_color uses the terminfo database to look up how to change terminal
|
||||
colors on whatever terminal is in use. Some systems have old and
|
||||
incomplete terminfo databases, and may lack color information for
|
||||
terminals that support it. Download and install the latest version of
|
||||
ncurses and recompile fish against it in order to fix this issue.
|
||||
|
||||
|
||||
@@ -1,15 +1,24 @@
|
||||
\section source . - evaluate contents of file.
|
||||
|
||||
\subsection source-synopsis Synopsis
|
||||
<tt>. FILENAME</tt>
|
||||
<tt>. FILENAME [ARGUMENTS...]</tt>
|
||||
|
||||
\subsection source-description Description
|
||||
\subsection source-description Description
|
||||
|
||||
Evaluates the commands of the specified file in the current
|
||||
shell. This is different from starting a new process to perform the
|
||||
commands (i.e. <tt>fish < FILENAME</tt>) since the commands will be
|
||||
evaluated by the current shell, which means that changes in
|
||||
environment variables, etc., will remain.
|
||||
environment variables, etc., will remain. If additional arguments are
|
||||
specified after the file name, they will be inserted into the $argv
|
||||
variable.
|
||||
|
||||
If no file is specified, or if the file name '-' is used, stdin will
|
||||
be read.
|
||||
|
||||
The return status of . is the return status of the last job to
|
||||
execute. If something goes wrong while opening or reading the file,
|
||||
. exits with a non-zero status.
|
||||
|
||||
\subsection source-example Example
|
||||
|
||||
|
||||
@@ -8,3 +8,11 @@
|
||||
- <tt>-b</tt> or <tt>--is-block</tt> returns 0 if fish is currently executing a block of code
|
||||
- <tt>-i</tt> or <tt>--is-interactive</tt> returns 0 if fish is interactive, i.e.connected to a keyboard
|
||||
- <tt>-l</tt> or <tt>--is-login</tt> returns 0 if fish is a login shell, i.e. if fish should perform login tasks such as setting up the PATH.
|
||||
- <tt>--is-full-job-control</tt> returns 0 if full job control is enabled
|
||||
- <tt>--is-interactive-job-control</tt> returns 0 if interactive job control is enabled
|
||||
- <tt>--is-no-job-control</tt> returns 0 if no job control is enabled
|
||||
- <tt>-f</tt> or <tt>--current-filename</tt> prints the filename of the currently running script
|
||||
- <tt>-n</tt> or <tt>--current-line-number</tt> prints the line number of the currently running script
|
||||
- <tt>-j CONTROLTYPE</tt> or <tt>--job-control=CONTROLTYPE</tt> set the job control type. Can be one of: none, full, interactive
|
||||
- <tt>-t</tt> or <tt>--print-stack-trace</tt> prints a stack trace of all function calls on the call stack
|
||||
- <tt>-h</tt> or <tt>--help</tt> display a help message and exit
|
||||
|
||||
@@ -19,7 +19,7 @@ regular wildcard expansion using filenames.
|
||||
|
||||
Note that fish does not fall through on case statements. Though the
|
||||
syntax may look a bit like C switch statements, it behaves more like
|
||||
the case stamantes of traditional shells.
|
||||
the case statements of traditional shells.
|
||||
|
||||
Also note that command substitutions in a case statement will be
|
||||
evaluated even if it's body is not taken. This may seem
|
||||
|
||||
@@ -11,7 +11,7 @@ omitted, the current value of the limit of the resource is printed.
|
||||
|
||||
Use one of the following switches to specify which resource limit to set or report:
|
||||
|
||||
- <code>-c</code> or <code>--core-size</code> The maximum size of core files created
|
||||
- <code>-c</code> or <code>--core-size</code> The maximum size of core files created. By setting this limit to zero, core dumps can be disabled.
|
||||
- <code>-d</code> or <code>--data-size</code> The maximum size of a process's data segment
|
||||
- <code>-f</code> or <code>--file-size</code> The maximum size of files created by the shell
|
||||
- <code>-l</code> or <code>--lock-size</code> The maximum size that may be locked into memory
|
||||
@@ -27,7 +27,7 @@ Note that not all these limits are available in all operating systems.
|
||||
The value of limit can be a number in the unit specified for
|
||||
the resource or one of the special values hard, soft, or unlimited,
|
||||
which stand for the current hard limit, the current soft limit, and no
|
||||
limit, respectively.
|
||||
limit, respectively.
|
||||
|
||||
If limit is given, it is the new value of the specified resource. If
|
||||
no option is given, then -f is assumed. Values are in kilobytes,
|
||||
@@ -35,16 +35,17 @@ except for -t, which is in seconds and -n and -u, which are unscaled
|
||||
values. The return status is 0 unless an invalid option or argument is
|
||||
supplied, or an error occurs while setting a new limit.
|
||||
|
||||
ulimit also accepts the following switches that determine what type of limit to set:
|
||||
ulimit also accepts the following switches that determine what type of
|
||||
limit to set:
|
||||
|
||||
- <code>-H</code> or <code>--hard</code> Set hard resource limit
|
||||
- <code>-S</code> or <code>--soft</code> Set soft resource limit
|
||||
|
||||
A hard limit cannot be increased once it is set; a soft limit may be
|
||||
increased up to the value of the hard limit. If neither -H nor -S is
|
||||
specified, both the soft and hard limits are updated when assigning a
|
||||
new limit value, and the soft limit is used when reporting the current
|
||||
value.
|
||||
A hard limit can only be decreased, once it is set it can not be
|
||||
increased; a soft limit may be increased up to the value of the hard
|
||||
limit. If neither -H nor -S is specified, both the soft and hard
|
||||
limits are updated when assigning a new limit value, and the soft
|
||||
limit is used when reporting the current value.
|
||||
|
||||
The following additional options are also understood by ulimit:
|
||||
|
||||
@@ -55,7 +56,7 @@ The fish implementation of ulimit should behave identically to the
|
||||
implementation in bash, except for these differences:
|
||||
|
||||
- Fish ulimit supports GNU-style long options for all switches
|
||||
- Fish ulimit does not support the -p option for getting the pipe size. The bash implementation consists of a compile-time check that empirically guesses this number by writing to a pipe and waiting for SIGPIPE. Depending on bash version, there may also be further additional limits to set in bash that do not exist in fish.
|
||||
- Fish ulimit does not support the -p option for getting the pipe size. The bash implementation consists of a compile-time check that empirically guesses this number by writing to a pipe and waiting for SIGPIPE. Fish does not do this because it this method of determining pipe size is unreliable. Depending on bash version, there may also be further additional limits to set in bash that do not exist in fish.
|
||||
- Fish ulimit does not support getting or setting multiple limits in one command, except reporting all values using the -a switch
|
||||
|
||||
\subsection ulimit-example Example
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
\section umask umask - set or get the shells resource usage limits
|
||||
\section umask umask - set or get the file-creation mask
|
||||
|
||||
\subsection umask-synopsis Synopsis
|
||||
<code>umask [OPTIONS] [MASK]</code>
|
||||
@@ -43,7 +43,7 @@ in bash.
|
||||
|
||||
\subsection umask-example Example
|
||||
|
||||
<code>umask 177</code> or <code>umask u=rw</code>sets the file
|
||||
<code>umask 177</code> or <code>umask u=rw</code> sets the file
|
||||
creation mask to read and write for the owner and no permissions at
|
||||
all for any other users.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
\section vared vared - interactively edit the value of an environment variable
|
||||
\section vared vared - interactively edit the value of an environment variable
|
||||
|
||||
\subsection vared-synopsis Synopsis
|
||||
<tt>vared VARIABLE_NAME</tt>
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
vared is used to interactively edit the value of an environment
|
||||
variable. Array variables as a whole can not be edited using vared,
|
||||
but individual array elements can.
|
||||
but individual array elements can.
|
||||
|
||||
\subsection vared-example Example
|
||||
|
||||
|
||||
13
env.h
13
env.h
@@ -63,7 +63,7 @@ void env_destroy();
|
||||
|
||||
|
||||
/**
|
||||
Set the value of the environment variable whose name matches key to val.
|
||||
Set the value of the environment variable whose name matches key to val.
|
||||
|
||||
Memory policy: All keys and values are copied, the parameters can and should be freed by the caller afterwards
|
||||
|
||||
@@ -79,7 +79,7 @@ void env_destroy();
|
||||
* ENV_INVALID, the variable name or mode was invalid
|
||||
*/
|
||||
|
||||
int env_set( const wchar_t *key,
|
||||
int env_set( const wchar_t *key,
|
||||
const wchar_t *val,
|
||||
int mode );
|
||||
|
||||
@@ -104,7 +104,7 @@ int env_exist( const wchar_t *key, int mode );
|
||||
|
||||
/**
|
||||
Remove environemnt variable
|
||||
|
||||
|
||||
\param key The name of the variable to remove
|
||||
\param mode should be ENV_USER if this is a remove request from the user, 0 otherwise. If this is a user request, read-only variables can not be removed. The mode may also specify the scope of the variable that should be erased.
|
||||
|
||||
@@ -132,4 +132,11 @@ char **env_export_arr( int recalc );
|
||||
*/
|
||||
void env_get_names( array_list_t *l, int flags );
|
||||
|
||||
/**
|
||||
Update the PWD variable
|
||||
directory
|
||||
*/
|
||||
int env_set_pwd();
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
144
env_universal.c
144
env_universal.c
@@ -83,27 +83,27 @@ static int get_socket( int fork_ok )
|
||||
{
|
||||
int s, len;
|
||||
struct sockaddr_un local;
|
||||
|
||||
|
||||
char *name;
|
||||
wchar_t *wdir;
|
||||
wchar_t *wuname;
|
||||
wchar_t *wuname;
|
||||
char *dir =0, *uname=0;
|
||||
|
||||
get_socket_count++;
|
||||
wdir = path;
|
||||
wuname = user;
|
||||
|
||||
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
|
||||
if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
|
||||
{
|
||||
wperror(L"socket");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if( wdir )
|
||||
dir = wcs2str(wdir );
|
||||
else
|
||||
dir = strdup("/tmp");
|
||||
|
||||
|
||||
if( wuname )
|
||||
uname = wcs2str(wuname );
|
||||
else
|
||||
@@ -112,53 +112,53 @@ static int get_socket( int fork_ok )
|
||||
pw = getpwuid( getuid() );
|
||||
uname = strdup( pw->pw_name );
|
||||
}
|
||||
|
||||
|
||||
name = malloc( strlen(dir) +
|
||||
strlen(uname) +
|
||||
strlen(SOCK_FILENAME) +
|
||||
strlen(uname) +
|
||||
strlen(SOCK_FILENAME) +
|
||||
2 );
|
||||
|
||||
|
||||
strcpy( name, dir );
|
||||
strcat( name, "/" );
|
||||
strcat( name, SOCK_FILENAME );
|
||||
strcat( name, uname );
|
||||
|
||||
|
||||
free( dir );
|
||||
free( uname );
|
||||
|
||||
|
||||
debug( 3, L"Connect to socket %s at fd %2", name, s );
|
||||
|
||||
|
||||
local.sun_family = AF_UNIX;
|
||||
strcpy(local.sun_path, name );
|
||||
free( name );
|
||||
len = sizeof(local);
|
||||
|
||||
if( connect( s, (struct sockaddr *)&local, len) == -1 )
|
||||
|
||||
if( connect( s, (struct sockaddr *)&local, len) == -1 )
|
||||
{
|
||||
close( s );
|
||||
if( fork_ok && start_fishd )
|
||||
{
|
||||
debug( 2, L"Could not connect to socket %d, starting fishd", s );
|
||||
|
||||
|
||||
start_fishd();
|
||||
|
||||
|
||||
return get_socket( 0 );
|
||||
}
|
||||
|
||||
|
||||
debug( 1, L"Could not connect to universal variable server, already tried manual restart (or no command supplied). You will not be able to share variable values between fish sessions. Is fish properly installed?" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
if( (fcntl( s, F_SETFL, O_NONBLOCK ) != 0) || (fcntl( s, F_SETFD, FD_CLOEXEC ) != 0) )
|
||||
|
||||
if( (fcntl( s, F_SETFL, O_NONBLOCK ) != 0) || (fcntl( s, F_SETFD, FD_CLOEXEC ) != 0) )
|
||||
{
|
||||
wperror( L"fcntl" );
|
||||
close( s );
|
||||
|
||||
close( s );
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug( 3, L"Connected to fd %d", s );
|
||||
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -166,7 +166,7 @@ static int get_socket( int fork_ok )
|
||||
Callback function used whenever a new fishd message is recieved
|
||||
*/
|
||||
static void callback( int type, const wchar_t *name, const wchar_t *val )
|
||||
{
|
||||
{
|
||||
if( type == BARRIER_REPLY )
|
||||
{
|
||||
barrier_reply = 1;
|
||||
@@ -174,8 +174,8 @@ static void callback( int type, const wchar_t *name, const wchar_t *val )
|
||||
else
|
||||
{
|
||||
if( external_callback )
|
||||
external_callback( type, name, val );
|
||||
}
|
||||
external_callback( type, name, val );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,21 +186,21 @@ static void check_connection()
|
||||
{
|
||||
if( !init )
|
||||
return;
|
||||
|
||||
|
||||
if( env_universal_server.killme )
|
||||
{
|
||||
debug( 3, L"Lost connection to universal variable server." );
|
||||
|
||||
|
||||
if( close( env_universal_server.fd ) )
|
||||
{
|
||||
wperror( L"close" );
|
||||
}
|
||||
|
||||
|
||||
env_universal_server.fd = -1;
|
||||
env_universal_server.killme=0;
|
||||
env_universal_server.input.used=0;
|
||||
env_universal_server.input.used=0;
|
||||
env_universal_read_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -210,10 +210,10 @@ static void env_universal_remove_all()
|
||||
{
|
||||
array_list_t lst;
|
||||
int i;
|
||||
|
||||
|
||||
al_init( &lst );
|
||||
|
||||
env_universal_common_get_names( &lst,
|
||||
|
||||
env_universal_common_get_names( &lst,
|
||||
1,
|
||||
1 );
|
||||
|
||||
@@ -224,7 +224,7 @@ static void env_universal_remove_all()
|
||||
}
|
||||
|
||||
al_destroy( &lst );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -237,9 +237,9 @@ static void reconnect()
|
||||
{
|
||||
if( get_socket_count >= RECONNECT_COUNT )
|
||||
return;
|
||||
|
||||
|
||||
debug( 3, L"Get new fishd connection" );
|
||||
|
||||
|
||||
init = 0;
|
||||
env_universal_server.buffer_consumed = env_universal_server.buffer_used = 0;
|
||||
env_universal_server.fd = get_socket(1);
|
||||
@@ -252,22 +252,22 @@ static void reconnect()
|
||||
}
|
||||
|
||||
|
||||
void env_universal_init( wchar_t * p,
|
||||
wchar_t *u,
|
||||
void env_universal_init( wchar_t * p,
|
||||
wchar_t *u,
|
||||
void (*sf)(),
|
||||
void (*cb)( int type, const wchar_t *name, const wchar_t *val ))
|
||||
{
|
||||
path=p;
|
||||
user=u;
|
||||
start_fishd=sf;
|
||||
start_fishd=sf;
|
||||
external_callback = cb;
|
||||
|
||||
connection_init( &env_universal_server, -1 );
|
||||
|
||||
|
||||
env_universal_server.fd = get_socket(1);
|
||||
env_universal_common_init( &callback );
|
||||
env_universal_read_all();
|
||||
init = 1;
|
||||
env_universal_read_all();
|
||||
init = 1;
|
||||
if( env_universal_server.fd >= 0 )
|
||||
{
|
||||
env_universal_barrier();
|
||||
@@ -285,7 +285,7 @@ void env_universal_destroy()
|
||||
{
|
||||
wperror( L"fcntl" );
|
||||
}
|
||||
try_send_all( &env_universal_server );
|
||||
try_send_all( &env_universal_server );
|
||||
}
|
||||
|
||||
connection_destroy( &env_universal_server );
|
||||
@@ -305,22 +305,22 @@ int env_universal_read_all()
|
||||
|
||||
if( env_universal_server.fd == -1 )
|
||||
{
|
||||
reconnect();
|
||||
reconnect();
|
||||
if( env_universal_server.fd == -1 )
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if( env_universal_server.fd != -1 )
|
||||
{
|
||||
read_message( &env_universal_server );
|
||||
check_connection();
|
||||
check_connection();
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 2, L"No connection to universal variable server" );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wchar_t *env_universal_get( const wchar_t *name )
|
||||
@@ -329,7 +329,7 @@ wchar_t *env_universal_get( const wchar_t *name )
|
||||
return 0;
|
||||
|
||||
CHECK( name, 0 );
|
||||
|
||||
|
||||
return env_universal_common_get( name );
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ int env_universal_get_export( const wchar_t *name )
|
||||
return 0;
|
||||
|
||||
CHECK( name, 0 );
|
||||
|
||||
|
||||
return env_universal_common_get_export( name );
|
||||
}
|
||||
|
||||
@@ -366,19 +366,19 @@ void env_universal_barrier()
|
||||
debug( 3, L"Create barrier" );
|
||||
while( 1 )
|
||||
{
|
||||
try_send_all( &env_universal_server );
|
||||
check_connection();
|
||||
|
||||
try_send_all( &env_universal_server );
|
||||
check_connection();
|
||||
|
||||
if( q_empty( &env_universal_server.unsent ) )
|
||||
break;
|
||||
|
||||
|
||||
if( env_universal_server.fd == -1 )
|
||||
{
|
||||
reconnect();
|
||||
debug( 2, L"barrier interrupted, exiting" );
|
||||
return;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
FD_ZERO( &fds );
|
||||
FD_SET( env_universal_server.fd, &fds );
|
||||
select( env_universal_server.fd+1, 0, &fds, 0, 0 );
|
||||
@@ -394,10 +394,10 @@ void env_universal_barrier()
|
||||
{
|
||||
reconnect();
|
||||
debug( 2, L"barrier interrupted, exiting (2)" );
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
FD_ZERO( &fds );
|
||||
FD_SET( env_universal_server.fd, &fds );
|
||||
FD_SET( env_universal_server.fd, &fds );
|
||||
select( env_universal_server.fd+1, &fds, 0, 0, 0 );
|
||||
env_universal_read_all();
|
||||
}
|
||||
@@ -408,12 +408,12 @@ void env_universal_barrier()
|
||||
void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
|
||||
{
|
||||
message_t *msg;
|
||||
|
||||
|
||||
if( !init )
|
||||
return;
|
||||
|
||||
CHECK( name, );
|
||||
|
||||
|
||||
debug( 3, L"env_universal_set( \"%ls\", \"%ls\" )", name, value );
|
||||
|
||||
if( is_dead() )
|
||||
@@ -422,8 +422,8 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
|
||||
}
|
||||
else
|
||||
{
|
||||
msg = create_message( export?SET_EXPORT:SET,
|
||||
name,
|
||||
msg = create_message( export?SET_EXPORT:SET,
|
||||
name,
|
||||
value);
|
||||
|
||||
if( !msg )
|
||||
@@ -431,7 +431,7 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
|
||||
debug( 1, L"Could not create universal variable message" );
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
msg->count=1;
|
||||
q_put( &env_universal_server.unsent, msg );
|
||||
env_universal_barrier();
|
||||
@@ -441,18 +441,18 @@ void env_universal_set( const wchar_t *name, const wchar_t *value, int export )
|
||||
int env_universal_remove( const wchar_t *name )
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
message_t *msg;
|
||||
if( !init )
|
||||
return 1;
|
||||
|
||||
|
||||
CHECK( name, 1 );
|
||||
|
||||
res = !env_universal_common_get( name );
|
||||
debug( 3,
|
||||
L"env_universal_remove( \"%ls\" )",
|
||||
name );
|
||||
|
||||
|
||||
if( is_dead() )
|
||||
{
|
||||
env_universal_common_remove( name );
|
||||
@@ -464,7 +464,7 @@ int env_universal_remove( const wchar_t *name )
|
||||
q_put( &env_universal_server.unsent, msg );
|
||||
env_universal_barrier();
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -476,8 +476,8 @@ void env_universal_get_names( array_list_t *l,
|
||||
return;
|
||||
|
||||
CHECK( l, );
|
||||
|
||||
env_universal_common_get_names( l,
|
||||
|
||||
env_universal_common_get_names( l,
|
||||
show_exported,
|
||||
show_unexported );
|
||||
show_unexported );
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ int env_universal_get_export( const wchar_t *name );
|
||||
void env_universal_set( const wchar_t *name, const wchar_t *val, int export );
|
||||
/**
|
||||
Erase a universal variable
|
||||
|
||||
|
||||
\return zero if the variable existed, and non-zero if the variable did not exist
|
||||
*/
|
||||
int env_universal_remove( const wchar_t *name );
|
||||
@@ -52,7 +52,7 @@ int env_universal_read_all();
|
||||
|
||||
/**
|
||||
Get the names of all universal variables
|
||||
|
||||
|
||||
\param l the list to insert the names into
|
||||
\param show_exported whether exported variables should be shown
|
||||
\param show_unexported whether unexported variables should be shown
|
||||
|
||||
@@ -93,13 +93,13 @@
|
||||
typedef struct var_uni_entry
|
||||
{
|
||||
int export; /**< Whether the variable should be exported */
|
||||
wchar_t val[0]; /**< The value of the variable */
|
||||
wchar_t val[1]; /**< The value of the variable */
|
||||
}
|
||||
var_uni_entry_t;
|
||||
|
||||
|
||||
static void parse_message( wchar_t *msg,
|
||||
connection_t *src );
|
||||
connection_t *src );
|
||||
|
||||
/**
|
||||
The table of all universal variables
|
||||
@@ -109,11 +109,10 @@ hash_table_t env_universal_var;
|
||||
/**
|
||||
Callback function, should be called on all events
|
||||
*/
|
||||
void (*callback)( int type,
|
||||
const wchar_t *key,
|
||||
void (*callback)( int type,
|
||||
const wchar_t *key,
|
||||
const wchar_t *val );
|
||||
|
||||
|
||||
/**
|
||||
Variable used by env_get_names to communicate auxiliary information
|
||||
to add_key_to_hash
|
||||
@@ -125,37 +124,109 @@ static int get_names_show_exported;
|
||||
*/
|
||||
static int get_names_show_unexported;
|
||||
|
||||
/**
|
||||
List of names for the UTF-8 character set.
|
||||
*/
|
||||
static char *iconv_utf8_names[]=
|
||||
{
|
||||
"utf-8", "UTF-8",
|
||||
"utf8", "UTF8",
|
||||
0
|
||||
}
|
||||
;
|
||||
|
||||
wchar_t *utf2wcs( const char *in )
|
||||
/**
|
||||
List of wide character names, undefined byte length.
|
||||
*/
|
||||
static char *iconv_wide_names_unknown[]=
|
||||
{
|
||||
"wchar_t", "WCHAR_T",
|
||||
"wchar", "WCHAR",
|
||||
0
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
List of wide character names, 4 bytes long.
|
||||
*/
|
||||
static char *iconv_wide_names_4[]=
|
||||
{
|
||||
"wchar_t", "WCHAR_T",
|
||||
"wchar", "WCHAR",
|
||||
"ucs-4", "UCS-4",
|
||||
"ucs4", "UCS4",
|
||||
"utf-32", "UTF-32",
|
||||
"utf32", "UTF32",
|
||||
0
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
List of wide character names, 2 bytes long.
|
||||
*/
|
||||
static char *iconv_wide_names_2[]=
|
||||
{
|
||||
"wchar_t", "WCHAR_T",
|
||||
"wchar", "WCHAR",
|
||||
"ucs-2", "UCS-2",
|
||||
"ucs2", "UCS2",
|
||||
"utf-16", "UTF-16",
|
||||
"utf16", "UTF16",
|
||||
0
|
||||
}
|
||||
;
|
||||
|
||||
/**
|
||||
Convert utf-8 string to wide string
|
||||
*/
|
||||
static wchar_t *utf2wcs( const char *in )
|
||||
{
|
||||
iconv_t cd=(iconv_t) -1;
|
||||
int i,j;
|
||||
|
||||
wchar_t *out;
|
||||
|
||||
char *to_name[]=
|
||||
{
|
||||
"wchar_t", "WCHAR_T", "wchar", "WCHAR", 0
|
||||
}
|
||||
;
|
||||
/*
|
||||
Try to convert to wchar_t. If that is not a valid character set,
|
||||
try various names for ucs-4. We can't be sure that ucs-4 is
|
||||
really the character set used by wchar_t, but it is the best
|
||||
assumption we can make.
|
||||
*/
|
||||
char **to_name=0;
|
||||
|
||||
char *from_name[]=
|
||||
switch (sizeof (wchar_t))
|
||||
{
|
||||
"utf-8", "UTF-8", "utf8", "UTF8", 0
|
||||
|
||||
case 2:
|
||||
to_name = iconv_wide_names_2;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
to_name = iconv_wide_names_4;
|
||||
break;
|
||||
|
||||
default:
|
||||
to_name = iconv_wide_names_unknown;
|
||||
break;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/*
|
||||
The line protocol fish uses is always utf-8.
|
||||
*/
|
||||
char **from_name = iconv_utf8_names;
|
||||
|
||||
size_t in_len = strlen( in );
|
||||
size_t out_len = sizeof( wchar_t )*(in_len+1);
|
||||
size_t out_len = sizeof( wchar_t )*(in_len+2);
|
||||
size_t nconv;
|
||||
char *nout;
|
||||
|
||||
|
||||
out = malloc( out_len );
|
||||
nout = (char *)out;
|
||||
|
||||
if( !out )
|
||||
return 0;
|
||||
|
||||
|
||||
for( i=0; to_name[i]; i++ )
|
||||
{
|
||||
for( j=0; from_name[j]; j++ )
|
||||
@@ -165,7 +236,7 @@ wchar_t *utf2wcs( const char *in )
|
||||
if( cd != (iconv_t) -1)
|
||||
{
|
||||
goto start_conversion;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,74 +246,108 @@ wchar_t *utf2wcs( const char *in )
|
||||
if (cd == (iconv_t) -1)
|
||||
{
|
||||
/* Something went wrong. */
|
||||
debug( 0, L"Could not perform utf-8 conversion" );
|
||||
debug( 0, L"Could not perform utf-8 conversion" );
|
||||
if(errno != EINVAL)
|
||||
wperror( L"iconv_open" );
|
||||
|
||||
|
||||
/* Terminate the output string. */
|
||||
free(out);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nconv = iconv( cd, (char **)&in, &in_len, &nout, &out_len );
|
||||
|
||||
|
||||
if (nconv == (size_t) -1)
|
||||
{
|
||||
debug( 0, L"Error while converting from utf string" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
*((wchar_t *) nout) = L'\0';
|
||||
|
||||
|
||||
/*
|
||||
Check for silly iconv behaviour inserting an bytemark in the output
|
||||
string.
|
||||
*/
|
||||
if (*out == L'\xfeff' || *out == L'\xffef' || *out == L'\xefbbbf')
|
||||
{
|
||||
wchar_t *out_old = out;
|
||||
out = wcsdup(out+1);
|
||||
if (! out )
|
||||
{
|
||||
debug(0, L"FNORD!!!!");
|
||||
free( out_old );
|
||||
return 0;
|
||||
}
|
||||
free( out_old );
|
||||
}
|
||||
|
||||
|
||||
if (iconv_close (cd) != 0)
|
||||
wperror (L"iconv_close");
|
||||
|
||||
return out;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
char *wcs2utf( const wchar_t *in )
|
||||
/**
|
||||
Convert wide string to utf-8
|
||||
*/
|
||||
static char *wcs2utf( const wchar_t *in )
|
||||
{
|
||||
iconv_t cd=(iconv_t) -1;
|
||||
int i,j;
|
||||
|
||||
|
||||
char *char_in = (char *)in;
|
||||
char *out;
|
||||
|
||||
char *from_name[]=
|
||||
{
|
||||
"wchar_t", "WCHAR_T", "wchar", "WCHAR", 0
|
||||
}
|
||||
;
|
||||
/*
|
||||
Try to convert to wchar_t. If that is not a valid character set,
|
||||
try various names for ucs-4. We can't be sure that ucs-4 is
|
||||
really the character set used by wchar_t, but it is the best
|
||||
assumption we can make.
|
||||
*/
|
||||
char **from_name=0;
|
||||
|
||||
char *to_name[]=
|
||||
switch (sizeof (wchar_t))
|
||||
{
|
||||
"utf-8", "UTF-8", "utf8", "UTF8", 0
|
||||
|
||||
case 2:
|
||||
from_name = iconv_wide_names_2;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
from_name = iconv_wide_names_4;
|
||||
break;
|
||||
|
||||
default:
|
||||
from_name = iconv_wide_names_unknown;
|
||||
break;
|
||||
}
|
||||
;
|
||||
|
||||
char **to_name = iconv_utf8_names;
|
||||
|
||||
size_t in_len = wcslen( in );
|
||||
size_t out_len = sizeof( char )*( (MAX_UTF8_BYTES*in_len)+1);
|
||||
size_t nconv;
|
||||
char *nout;
|
||||
|
||||
|
||||
out = malloc( out_len );
|
||||
nout = (char *)out;
|
||||
in_len *= sizeof( wchar_t );
|
||||
|
||||
if( !out )
|
||||
return 0;
|
||||
|
||||
|
||||
for( i=0; to_name[i]; i++ )
|
||||
{
|
||||
for( j=0; from_name[j]; j++ )
|
||||
{
|
||||
cd = iconv_open ( to_name[i], from_name[j] );
|
||||
|
||||
|
||||
if( cd != (iconv_t) -1)
|
||||
{
|
||||
goto start_conversion;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,17 +357,17 @@ char *wcs2utf( const wchar_t *in )
|
||||
if (cd == (iconv_t) -1)
|
||||
{
|
||||
/* Something went wrong. */
|
||||
debug( 0, L"Could not perform utf-8 conversion" );
|
||||
debug( 0, L"Could not perform utf-8 conversion" );
|
||||
if(errno != EINVAL)
|
||||
wperror( L"iconv_open" );
|
||||
|
||||
|
||||
/* Terminate the output string. */
|
||||
free(out);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
nconv = iconv( cd, &char_in, &in_len, &nout, &out_len );
|
||||
|
||||
|
||||
|
||||
if (nconv == (size_t) -1)
|
||||
{
|
||||
@@ -270,13 +375,13 @@ char *wcs2utf( const wchar_t *in )
|
||||
debug( 0, L"Error while converting from to string" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
*nout = '\0';
|
||||
|
||||
|
||||
if (iconv_close (cd) != 0)
|
||||
wperror (L"iconv_close");
|
||||
|
||||
return out;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
@@ -304,6 +409,9 @@ void env_universal_common_destroy()
|
||||
hash_destroy( &env_universal_var );
|
||||
}
|
||||
|
||||
/**
|
||||
Read one byte of date form the specified connection
|
||||
*/
|
||||
static int read_byte( connection_t *src )
|
||||
{
|
||||
|
||||
@@ -313,9 +421,9 @@ static int read_byte( connection_t *src )
|
||||
int res;
|
||||
|
||||
res = read( src->fd, src->buffer, ENV_UNIVERSAL_BUFFER_SIZE );
|
||||
|
||||
|
||||
// debug(4, L"Read chunk '%.*s'", res, src->buffer );
|
||||
|
||||
|
||||
if( res < 0 )
|
||||
{
|
||||
|
||||
@@ -324,20 +432,20 @@ static int read_byte( connection_t *src )
|
||||
{
|
||||
return ENV_UNIVERSAL_AGAIN;
|
||||
}
|
||||
|
||||
|
||||
return ENV_UNIVERSAL_ERROR;
|
||||
|
||||
}
|
||||
|
||||
|
||||
if( res == 0 )
|
||||
{
|
||||
return ENV_UNIVERSAL_EOF;
|
||||
}
|
||||
|
||||
|
||||
src->buffer_consumed = 0;
|
||||
src->buffer_used = res;
|
||||
}
|
||||
|
||||
|
||||
return src->buffer[src->buffer_consumed++];
|
||||
|
||||
}
|
||||
@@ -347,10 +455,10 @@ void read_message( connection_t *src )
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
|
||||
|
||||
int ib = read_byte( src );
|
||||
char b;
|
||||
|
||||
|
||||
switch( ib )
|
||||
{
|
||||
case ENV_UNIVERSAL_AGAIN:
|
||||
@@ -375,43 +483,43 @@ void read_message( connection_t *src )
|
||||
{
|
||||
char c = 0;
|
||||
b_append( &src->input, &c, 1 );
|
||||
debug( 1,
|
||||
L"Universal variable connection closed while reading command. Partial command recieved: '%s'",
|
||||
debug( 1,
|
||||
L"Universal variable connection closed while reading command. Partial command recieved: '%s'",
|
||||
(wchar_t *)src->input.buff );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
b = (char)ib;
|
||||
|
||||
|
||||
if( b == '\n' )
|
||||
{
|
||||
wchar_t *msg;
|
||||
|
||||
|
||||
b = 0;
|
||||
b_append( &src->input, &b, 1 );
|
||||
|
||||
|
||||
msg = utf2wcs( src->input.buff );
|
||||
|
||||
|
||||
/*
|
||||
Before calling parse_message, we must empty reset
|
||||
everything, since the callback function could
|
||||
potentially call read_message.
|
||||
*/
|
||||
src->input.used=0;
|
||||
|
||||
|
||||
if( msg )
|
||||
{
|
||||
parse_message( msg, src );
|
||||
parse_message( msg, src );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 0, _(L"Could not convert message '%s' to wide character string"), src->input.buff );
|
||||
}
|
||||
|
||||
|
||||
free( msg );
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -426,7 +534,7 @@ void read_message( connection_t *src )
|
||||
void env_universal_common_remove( const wchar_t *name )
|
||||
{
|
||||
void *k, *v;
|
||||
hash_remove( &env_universal_var,
|
||||
hash_remove( &env_universal_var,
|
||||
name,
|
||||
&k,
|
||||
&v );
|
||||
@@ -445,7 +553,7 @@ static int match( const wchar_t *msg, const wchar_t *cmd )
|
||||
|
||||
if( msg[len] && msg[len]!= L' ' && msg[len] != L'\t' )
|
||||
return 0;
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -456,20 +564,20 @@ void env_universal_common_set( const wchar_t *key, const wchar_t *val, int expor
|
||||
|
||||
CHECK( key, );
|
||||
CHECK( val, );
|
||||
|
||||
entry = malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) );
|
||||
|
||||
entry = malloc( sizeof(var_uni_entry_t) + sizeof(wchar_t)*(wcslen(val)+1) );
|
||||
name = wcsdup(key);
|
||||
|
||||
|
||||
if( !entry || !name )
|
||||
DIE_MEM();
|
||||
|
||||
|
||||
entry->export=export;
|
||||
|
||||
|
||||
wcscpy( entry->val, val );
|
||||
env_universal_common_remove( name );
|
||||
|
||||
|
||||
hash_put( &env_universal_var, name, entry );
|
||||
|
||||
|
||||
if( callback )
|
||||
{
|
||||
callback( export?SET_EXPORT:SET, name, val );
|
||||
@@ -480,67 +588,67 @@ void env_universal_common_set( const wchar_t *key, const wchar_t *val, int expor
|
||||
/**
|
||||
Parse message msg
|
||||
*/
|
||||
static void parse_message( wchar_t *msg,
|
||||
static void parse_message( wchar_t *msg,
|
||||
connection_t *src )
|
||||
{
|
||||
// debug( 3, L"parse_message( %ls );", msg );
|
||||
|
||||
|
||||
if( msg[0] == L'#' )
|
||||
return;
|
||||
|
||||
|
||||
if( match( msg, SET_STR ) || match( msg, SET_EXPORT_STR ))
|
||||
{
|
||||
wchar_t *name, *tmp;
|
||||
int export = match( msg, SET_EXPORT_STR );
|
||||
|
||||
|
||||
name = msg+(export?wcslen(SET_EXPORT_STR):wcslen(SET_STR));
|
||||
while( wcschr( L"\t ", *name ) )
|
||||
name++;
|
||||
|
||||
|
||||
tmp = wcschr( name, L':' );
|
||||
if( tmp )
|
||||
{
|
||||
wchar_t *key;
|
||||
wchar_t *val;
|
||||
|
||||
|
||||
key = malloc( sizeof( wchar_t)*(tmp-name+1));
|
||||
memcpy( key, name, sizeof( wchar_t)*(tmp-name));
|
||||
key[tmp-name]=0;
|
||||
|
||||
|
||||
val = tmp+1;
|
||||
val = unescape( val, 0 );
|
||||
|
||||
|
||||
env_universal_common_set( key, val, export );
|
||||
|
||||
|
||||
free( val );
|
||||
free( key );
|
||||
}
|
||||
else
|
||||
{
|
||||
debug( 1, PARSE_ERR, msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( match( msg, ERASE_STR ) )
|
||||
{
|
||||
wchar_t *name, *tmp;
|
||||
|
||||
|
||||
name = msg+wcslen(ERASE_STR);
|
||||
while( wcschr( L"\t ", *name ) )
|
||||
name++;
|
||||
|
||||
|
||||
tmp = name;
|
||||
while( iswalnum( *tmp ) || *tmp == L'_')
|
||||
tmp++;
|
||||
|
||||
|
||||
*tmp = 0;
|
||||
|
||||
|
||||
if( !wcslen( name ) )
|
||||
{
|
||||
debug( 1, PARSE_ERR, msg );
|
||||
}
|
||||
|
||||
env_universal_common_remove( name );
|
||||
|
||||
|
||||
if( callback )
|
||||
{
|
||||
callback( ERASE, name, 0 );
|
||||
@@ -563,7 +671,7 @@ static void parse_message( wchar_t *msg,
|
||||
else
|
||||
{
|
||||
debug( 1, PARSE_ERR, msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,7 +684,7 @@ static int try_send( message_t *msg,
|
||||
{
|
||||
|
||||
debug( 3,
|
||||
L"before write of %d chars to fd %d", strlen(msg->body), fd );
|
||||
L"before write of %d chars to fd %d", strlen(msg->body), fd );
|
||||
|
||||
int res = write( fd, msg->body, strlen(msg->body) );
|
||||
|
||||
@@ -588,26 +696,26 @@ static int try_send( message_t *msg,
|
||||
{
|
||||
debug( 4, L"Failed to write message '%s'", msg->body );
|
||||
}
|
||||
|
||||
|
||||
if( res == -1 )
|
||||
{
|
||||
switch( errno )
|
||||
{
|
||||
case EAGAIN:
|
||||
return 0;
|
||||
|
||||
|
||||
default:
|
||||
debug( 2,
|
||||
L"Error while sending universal variable message to fd %d. Closing connection",
|
||||
fd );
|
||||
if( debug_level > 2 )
|
||||
wperror( L"write" );
|
||||
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
msg->count--;
|
||||
|
||||
|
||||
if( !msg->count )
|
||||
{
|
||||
free( msg );
|
||||
@@ -618,7 +726,7 @@ static int try_send( message_t *msg,
|
||||
void try_send_all( connection_t *c )
|
||||
{
|
||||
/* debug( 3,
|
||||
L"Send all updates to connection on fd %d",
|
||||
L"Send all updates to connection on fd %d",
|
||||
c->fd );*/
|
||||
while( !q_empty( &c->unsent) )
|
||||
{
|
||||
@@ -627,12 +735,12 @@ void try_send_all( connection_t *c )
|
||||
case 1:
|
||||
q_get( &c->unsent);
|
||||
break;
|
||||
|
||||
|
||||
case 0:
|
||||
debug( 4,
|
||||
L"Socket full, send rest later" );
|
||||
L"Socket full, send rest later" );
|
||||
return;
|
||||
|
||||
|
||||
case -1:
|
||||
c->killme = 1;
|
||||
return;
|
||||
@@ -640,6 +748,9 @@ void try_send_all( connection_t *c )
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Escape specified string
|
||||
*/
|
||||
static wchar_t *full_escape( const wchar_t *in )
|
||||
{
|
||||
string_buffer_t out;
|
||||
@@ -668,16 +779,16 @@ static wchar_t *full_escape( const wchar_t *in )
|
||||
|
||||
|
||||
message_t *create_message( int type,
|
||||
const wchar_t *key_in,
|
||||
const wchar_t *key_in,
|
||||
const wchar_t *val_in )
|
||||
{
|
||||
message_t *msg=0;
|
||||
|
||||
|
||||
char *key=0;
|
||||
size_t sz;
|
||||
|
||||
// debug( 4, L"Crete message of type %d", type );
|
||||
|
||||
|
||||
if( key_in )
|
||||
{
|
||||
if( wcsvarname( key_in ) )
|
||||
@@ -685,7 +796,7 @@ message_t *create_message( int type,
|
||||
debug( 0, L"Illegal variable name: '%ls'", key_in );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
key = wcs2utf(key_in);
|
||||
if( !key )
|
||||
{
|
||||
@@ -695,8 +806,8 @@ message_t *create_message( int type,
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case SET:
|
||||
@@ -706,29 +817,29 @@ message_t *create_message( int type,
|
||||
{
|
||||
val_in=L"";
|
||||
}
|
||||
|
||||
|
||||
wchar_t *esc = full_escape( val_in );
|
||||
if( !esc )
|
||||
break;
|
||||
|
||||
|
||||
char *val = wcs2utf(esc );
|
||||
free(esc);
|
||||
|
||||
|
||||
sz = strlen(type==SET?SET_MBS:SET_EXPORT_MBS) + strlen(key) + strlen(val) + 4;
|
||||
msg = malloc( sizeof( message_t ) + sz );
|
||||
|
||||
|
||||
if( !msg )
|
||||
DIE_MEM();
|
||||
|
||||
|
||||
strcpy( msg->body, (type==SET?SET_MBS:SET_EXPORT_MBS) );
|
||||
strcat( msg->body, " " );
|
||||
strcat( msg->body, key );
|
||||
strcat( msg->body, ":" );
|
||||
strcat( msg->body, val );
|
||||
strcat( msg->body, "\n" );
|
||||
|
||||
|
||||
free( val );
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -739,7 +850,7 @@ message_t *create_message( int type,
|
||||
|
||||
if( !msg )
|
||||
DIE_MEM();
|
||||
|
||||
|
||||
strcpy( msg->body, ERASE_MBS " " );
|
||||
strcat( msg->body, key );
|
||||
strcat( msg->body, "\n" );
|
||||
@@ -748,14 +859,14 @@ message_t *create_message( int type,
|
||||
|
||||
case BARRIER:
|
||||
{
|
||||
msg = malloc( sizeof( message_t ) +
|
||||
msg = malloc( sizeof( message_t ) +
|
||||
strlen( BARRIER_MBS ) +2);
|
||||
if( !msg )
|
||||
DIE_MEM();
|
||||
strcpy( msg->body, BARRIER_MBS "\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case BARRIER_REPLY:
|
||||
{
|
||||
msg = malloc( sizeof( message_t ) +
|
||||
@@ -765,7 +876,7 @@ message_t *create_message( int type,
|
||||
strcpy( msg->body, BARRIER_REPLY_MBS "\n" );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
debug( 0, L"create_message: Unknown message type" );
|
||||
@@ -779,19 +890,19 @@ message_t *create_message( int type,
|
||||
|
||||
// debug( 4, L"Message body is '%s'", msg->body );
|
||||
|
||||
return msg;
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
Function used with hash_foreach to insert keys of one table into
|
||||
another
|
||||
*/
|
||||
static void add_key_to_hash( void *key,
|
||||
static void add_key_to_hash( void *key,
|
||||
void *data,
|
||||
void *aux )
|
||||
{
|
||||
var_uni_entry_t *e = (var_uni_entry_t *)data;
|
||||
if( ( e->export && get_names_show_exported) ||
|
||||
if( ( e->export && get_names_show_exported) ||
|
||||
( !e->export && get_names_show_unexported) )
|
||||
al_push( (array_list_t *)aux, key );
|
||||
}
|
||||
@@ -802,18 +913,18 @@ void env_universal_common_get_names( array_list_t *l,
|
||||
{
|
||||
get_names_show_exported = show_exported;
|
||||
get_names_show_unexported = show_unexported;
|
||||
|
||||
hash_foreach2( &env_universal_var,
|
||||
|
||||
hash_foreach2( &env_universal_var,
|
||||
add_key_to_hash,
|
||||
l );
|
||||
}
|
||||
|
||||
wchar_t *env_universal_common_get( const wchar_t *name )
|
||||
{
|
||||
var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name );
|
||||
var_uni_entry_t *e = (var_uni_entry_t *)hash_get( &env_universal_var, name );
|
||||
if( e )
|
||||
return e->val;
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int env_universal_common_get_export( const wchar_t *name )
|
||||
@@ -841,17 +952,17 @@ static void enqueue( void *k,
|
||||
const wchar_t *key = (const wchar_t *)k;
|
||||
const var_uni_entry_t *val = (const var_uni_entry_t *)v;
|
||||
dyn_queue_t *queue = (dyn_queue_t *)q;
|
||||
|
||||
|
||||
message_t *msg = create_message( val->export?SET_EXPORT:SET, key, val->val );
|
||||
msg->count=1;
|
||||
|
||||
|
||||
q_put( queue, msg );
|
||||
}
|
||||
|
||||
void enqueue_all( connection_t *c )
|
||||
{
|
||||
hash_foreach2( &env_universal_var,
|
||||
&enqueue,
|
||||
&enqueue,
|
||||
(void *)&c->unsent );
|
||||
try_send_all( c );
|
||||
}
|
||||
@@ -863,7 +974,7 @@ void connection_init( connection_t *c, int fd )
|
||||
c->fd = fd;
|
||||
b_init( &c->input );
|
||||
q_init( &c->unsent );
|
||||
c->buffer_consumed = c->buffer_used = 0;
|
||||
c->buffer_consumed = c->buffer_used = 0;
|
||||
}
|
||||
|
||||
void connection_destroy( connection_t *c)
|
||||
|
||||
@@ -76,9 +76,9 @@ typedef struct connection
|
||||
newline is encountered, the buffer is parsed and cleared.
|
||||
*/
|
||||
buffer_t input;
|
||||
|
||||
|
||||
/**
|
||||
The read buffer.
|
||||
The read buffer.
|
||||
*/
|
||||
char buffer[ENV_UNIVERSAL_BUFFER_SIZE];
|
||||
|
||||
@@ -86,12 +86,12 @@ typedef struct connection
|
||||
Number of bytes that have already been consumed.
|
||||
*/
|
||||
int buffer_consumed;
|
||||
|
||||
|
||||
/**
|
||||
Number of bytes that have been read into the buffer.
|
||||
Number of bytes that have been read into the buffer.
|
||||
*/
|
||||
int buffer_used;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Link to the next connection
|
||||
@@ -103,7 +103,7 @@ typedef struct connection
|
||||
/**
|
||||
A struct representing a message to be sent between client and server
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
Number of queues that contain this message. Once this reaches zero, the message should be deleted
|
||||
@@ -112,7 +112,7 @@ typedef struct
|
||||
/**
|
||||
Message body. The message must be allocated using enough memory to actually contain the message.
|
||||
*/
|
||||
char body[0];
|
||||
char body[1];
|
||||
}
|
||||
message_t;
|
||||
|
||||
@@ -163,7 +163,7 @@ void env_universal_common_get_names( array_list_t *l,
|
||||
void env_universal_common_set( const wchar_t *key, const wchar_t *val, int export );
|
||||
|
||||
/**
|
||||
Remove the specified variable.
|
||||
Remove the specified variable.
|
||||
|
||||
This function operate agains the local copy of all universal
|
||||
variables, it does not communicate with any other process.
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
#
|
||||
# @configure_input@
|
||||
|
||||
#
|
||||
# Set default field separators
|
||||
#
|
||||
|
||||
set -g IFS \ \t\n
|
||||
|
||||
#
|
||||
# Some things should only be done for login terminals
|
||||
#
|
||||
@@ -45,7 +39,7 @@ if status --is-login
|
||||
end
|
||||
|
||||
#
|
||||
# There are variables that contain colons that are not arrays. This
|
||||
# There are variables that contain colons that are not arrays. This
|
||||
# reverts them back to regular strings.
|
||||
#
|
||||
|
||||
@@ -63,4 +57,5 @@ if test -d include
|
||||
for i in include/*.fish
|
||||
. $i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#
|
||||
# This file contains key bindings for fish
|
||||
#
|
||||
|
||||
# Include system-wide inputrc file before including fish-specific key
|
||||
# bindings if it exists
|
||||
|
||||
$include /etc/inputrc
|
||||
|
||||
$if fish
|
||||
"\M-l": __fish_list_current_token
|
||||
"\M-w": set tok (commandline -pt); if test $tok[1]; whatis $tok[1]; end
|
||||
"\C-l": clear
|
||||
"\C-c": delete-line
|
||||
"\C-u": backward-kill-line
|
||||
"\M-d": kill-word
|
||||
"\C-w": backward-kill-word
|
||||
"\M-k": dump-functions
|
||||
"\M-d": if test -z (commandline); dirh; else; commandline -f kill-word; end
|
||||
"\C-d": delete-or-exit
|
||||
# This will make sure the output of the current command is paged using the less pager when you press Meta-p
|
||||
"\M-p": if commandline -j|grep -v 'less *$' >/dev/null; commandline -aj "|less;"; end
|
||||
$endif
|
||||
|
||||
# Include user-specific inputrc file after including fish-specific
|
||||
# bindings so that they will override fish defaults
|
||||
|
||||
$include ~/.inputrc
|
||||
234
event.c
234
event.c
@@ -44,11 +44,11 @@ typedef struct
|
||||
/**
|
||||
Whether signals have been skipped
|
||||
*/
|
||||
int overflow;
|
||||
int overflow;
|
||||
/**
|
||||
Array of signal events
|
||||
*/
|
||||
int signal[SIG_UNHANDLED_MAX];
|
||||
int signal[SIG_UNHANDLED_MAX];
|
||||
}
|
||||
signal_list_t;
|
||||
|
||||
@@ -78,11 +78,6 @@ static array_list_t *killme;
|
||||
*/
|
||||
static array_list_t *blocked;
|
||||
|
||||
/**
|
||||
String buffer used for formating event descriptions in event_get_desc()
|
||||
*/
|
||||
static string_buffer_t *get_desc_buff=0;
|
||||
|
||||
/**
|
||||
Tests if one event instance matches the definition of a event
|
||||
class. If both the class and the instance name a function,
|
||||
@@ -91,6 +86,7 @@ static string_buffer_t *get_desc_buff=0;
|
||||
*/
|
||||
static int event_match( event_t *class, event_t *instance )
|
||||
{
|
||||
|
||||
if( class->function_name && instance->function_name )
|
||||
{
|
||||
if( wcscmp( class->function_name, instance->function_name ) != 0 )
|
||||
@@ -99,23 +95,23 @@ static int event_match( event_t *class, event_t *instance )
|
||||
|
||||
if( class->type == EVENT_ANY )
|
||||
return 1;
|
||||
|
||||
|
||||
if( class->type != instance->type )
|
||||
return 0;
|
||||
|
||||
|
||||
|
||||
|
||||
switch( class->type )
|
||||
{
|
||||
|
||||
|
||||
case EVENT_SIGNAL:
|
||||
if( class->param1.signal == EVENT_ANY_SIGNAL )
|
||||
return 1;
|
||||
return class->param1.signal == instance->param1.signal;
|
||||
|
||||
|
||||
case EVENT_VARIABLE:
|
||||
return wcscmp( instance->param1.variable,
|
||||
class->param1.variable )==0;
|
||||
|
||||
|
||||
case EVENT_EXIT:
|
||||
if( class->param1.pid == EVENT_ANY_PID )
|
||||
return 1;
|
||||
@@ -123,12 +119,17 @@ static int event_match( event_t *class, event_t *instance )
|
||||
|
||||
case EVENT_JOB_ID:
|
||||
return class->param1.job_id == instance->param1.job_id;
|
||||
|
||||
case EVENT_GENERIC:
|
||||
return wcscmp( instance->param1.param,
|
||||
class->param1.param )==0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This should never be reached
|
||||
*/
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -139,8 +140,10 @@ static int event_match( event_t *class, event_t *instance )
|
||||
static event_t *event_copy( event_t *event, int copy_arguments )
|
||||
{
|
||||
event_t *e = malloc( sizeof( event_t ) );
|
||||
|
||||
if( !e )
|
||||
DIE_MEM();
|
||||
|
||||
memcpy( e, event, sizeof(event_t));
|
||||
|
||||
if( e->function_name )
|
||||
@@ -148,7 +151,9 @@ static event_t *event_copy( event_t *event, int copy_arguments )
|
||||
|
||||
if( e->type == EVENT_VARIABLE )
|
||||
e->param1.variable = wcsdup( e->param1.variable );
|
||||
|
||||
else if( e->type == EVENT_GENERIC )
|
||||
e->param1.param = wcsdup( e->param1.param );
|
||||
|
||||
al_init( &e->arguments );
|
||||
if( copy_arguments )
|
||||
{
|
||||
@@ -157,9 +162,9 @@ static event_t *event_copy( event_t *event, int copy_arguments )
|
||||
{
|
||||
al_push( &e->arguments, wcsdup( (wchar_t *)al_get( &event->arguments, i ) ) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -170,7 +175,7 @@ static int event_is_blocked( event_t *e )
|
||||
{
|
||||
block_t *block;
|
||||
event_block_t *eb;
|
||||
|
||||
|
||||
for( block = current_block; block; block = block->outer )
|
||||
{
|
||||
for( eb = block->first_event_block; eb; eb=eb->next )
|
||||
@@ -188,15 +193,20 @@ static int event_is_blocked( event_t *e )
|
||||
if( eb->type & (1<<e->type) )
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const wchar_t *event_get_desc( event_t *e )
|
||||
{
|
||||
|
||||
/*
|
||||
String buffer used for formating event descriptions in event_get_desc()
|
||||
*/
|
||||
static string_buffer_t *get_desc_buff=0;
|
||||
|
||||
CHECK( e, 0 );
|
||||
|
||||
if( !get_desc_buff )
|
||||
@@ -207,18 +217,18 @@ const wchar_t *event_get_desc( event_t *e )
|
||||
{
|
||||
sb_clear( get_desc_buff );
|
||||
}
|
||||
|
||||
|
||||
switch( e->type )
|
||||
{
|
||||
|
||||
|
||||
case EVENT_SIGNAL:
|
||||
sb_printf( get_desc_buff, _(L"signal handler for %ls (%ls)"), sig2wcs(e->param1.signal ), signal_get_desc( e->param1.signal ) );
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_VARIABLE:
|
||||
sb_printf( get_desc_buff, _(L"handler for variable '%ls'"), e->param1.variable );
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_EXIT:
|
||||
if( e->param1.pid > 0 )
|
||||
{
|
||||
@@ -232,9 +242,9 @@ const wchar_t *event_get_desc( event_t *e )
|
||||
else
|
||||
sb_printf( get_desc_buff, _(L"exit handler for job with process group %d"), -e->param1.pid );
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case EVENT_JOB_ID:
|
||||
{
|
||||
job_t *j = job_get( e->param1.job_id );
|
||||
@@ -245,9 +255,17 @@ const wchar_t *event_get_desc( event_t *e )
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case EVENT_GENERIC:
|
||||
sb_printf( get_desc_buff, _(L"handler for generic event '%ls'"), e->param1.param );
|
||||
break;
|
||||
|
||||
default:
|
||||
sb_printf( get_desc_buff, _(L"Unknown event type") );
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (const wchar_t *)get_desc_buff->buff;
|
||||
}
|
||||
|
||||
@@ -257,7 +275,7 @@ void event_add_handler( event_t *event )
|
||||
event_t *e;
|
||||
|
||||
CHECK( event, );
|
||||
|
||||
|
||||
e = event_copy( event, 0 );
|
||||
|
||||
if( !events )
|
||||
@@ -267,8 +285,8 @@ void event_add_handler( event_t *event )
|
||||
{
|
||||
signal_handle( e->param1.signal, 1 );
|
||||
}
|
||||
|
||||
al_push( events, e );
|
||||
|
||||
al_push( events, e );
|
||||
}
|
||||
|
||||
void event_remove( event_t *criterion )
|
||||
@@ -276,7 +294,7 @@ void event_remove( event_t *criterion )
|
||||
int i;
|
||||
array_list_t *new_list=0;
|
||||
event_t e;
|
||||
|
||||
|
||||
CHECK( criterion, );
|
||||
|
||||
/*
|
||||
@@ -287,19 +305,19 @@ void event_remove( event_t *criterion )
|
||||
that shouldn't be killed to new_list, and then drops the empty
|
||||
events-list.
|
||||
*/
|
||||
|
||||
|
||||
if( !events )
|
||||
return;
|
||||
|
||||
for( i=0; i<al_get_count( events); i++ )
|
||||
{
|
||||
event_t *n = (event_t *)al_get( events, i );
|
||||
event_t *n = (event_t *)al_get( events, i );
|
||||
if( event_match( criterion, n ) )
|
||||
{
|
||||
if( !killme )
|
||||
killme = al_new();
|
||||
|
||||
al_push( killme, n );
|
||||
|
||||
al_push( killme, n );
|
||||
|
||||
/*
|
||||
If this event was a signal handler and no other handler handles
|
||||
@@ -311,11 +329,11 @@ void event_remove( event_t *criterion )
|
||||
e.type = EVENT_SIGNAL;
|
||||
e.param1.signal = n->param1.signal;
|
||||
e.function_name = 0;
|
||||
|
||||
|
||||
if( event_get( &e, 0 ) == 1 )
|
||||
{
|
||||
signal_handle( e.param1.signal, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -326,7 +344,7 @@ void event_remove( event_t *criterion )
|
||||
}
|
||||
}
|
||||
al_destroy( events );
|
||||
free( events );
|
||||
free( events );
|
||||
events = new_list;
|
||||
}
|
||||
|
||||
@@ -334,21 +352,21 @@ int event_get( event_t *criterion, array_list_t *out )
|
||||
{
|
||||
int i;
|
||||
int found = 0;
|
||||
|
||||
|
||||
if( !events )
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
CHECK( criterion, 0 );
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( events); i++ )
|
||||
{
|
||||
event_t *n = (event_t *)al_get( events, i );
|
||||
event_t *n = (event_t *)al_get( events, i );
|
||||
if( event_match(criterion, n ) )
|
||||
{
|
||||
found++;
|
||||
if( out )
|
||||
al_push( out, n );
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
@@ -361,7 +379,7 @@ static void event_free_kills()
|
||||
int i;
|
||||
if( !killme )
|
||||
return;
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( killme ); i++ )
|
||||
{
|
||||
event_t *roadkill = (event_t *)al_get( killme, i );
|
||||
@@ -378,16 +396,16 @@ static int event_is_killed( event_t *e )
|
||||
int i;
|
||||
if( !killme )
|
||||
return 0;
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( killme ); i++ )
|
||||
{
|
||||
event_t *roadkill = (event_t *)al_get( events, i );
|
||||
if( roadkill ==e )
|
||||
return 1;
|
||||
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Perform the specified event. Since almost all event firings will
|
||||
@@ -400,11 +418,11 @@ static void event_fire_internal( event_t *event )
|
||||
int i, j;
|
||||
string_buffer_t *b=0;
|
||||
array_list_t *fire=0;
|
||||
|
||||
|
||||
/*
|
||||
First we free all events that have been removed
|
||||
*/
|
||||
event_free_kills();
|
||||
event_free_kills();
|
||||
|
||||
if( !events )
|
||||
return;
|
||||
@@ -419,7 +437,7 @@ static void event_fire_internal( event_t *event )
|
||||
for( i=0; i<al_get_count( events ); i++ )
|
||||
{
|
||||
event_t *criterion = (event_t *)al_get( events, i );
|
||||
|
||||
|
||||
/*
|
||||
Check if this event is a match
|
||||
*/
|
||||
@@ -430,17 +448,17 @@ static void event_fire_internal( event_t *event )
|
||||
al_push( fire, criterion );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
No matches. Time to return.
|
||||
*/
|
||||
if( !fire )
|
||||
return;
|
||||
|
||||
|
||||
/*
|
||||
Iterate over our list of matching events
|
||||
*/
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( fire ); i++ )
|
||||
{
|
||||
event_t *criterion = (event_t *)al_get( fire, i );
|
||||
@@ -459,19 +477,19 @@ static void event_fire_internal( event_t *event )
|
||||
b = sb_new();
|
||||
else
|
||||
sb_clear( b );
|
||||
|
||||
|
||||
sb_append( b, criterion->function_name );
|
||||
|
||||
|
||||
for( j=0; j<al_get_count(&event->arguments); j++ )
|
||||
{
|
||||
wchar_t *arg_esc = escape( (wchar_t *)al_get( &event->arguments, j), 1 );
|
||||
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 );
|
||||
free( arg_esc );
|
||||
}
|
||||
|
||||
// debug( 1, L"Event handler fires command '%ls'", (wchar_t *)b->buff );
|
||||
|
||||
|
||||
/*
|
||||
Event handlers are not part of the main flow of code, so
|
||||
they are marked as non-interactive
|
||||
@@ -482,27 +500,27 @@ static void event_fire_internal( event_t *event )
|
||||
current_block->param1.event = event;
|
||||
eval( (wchar_t *)b->buff, 0, TOP );
|
||||
parser_pop_block();
|
||||
proc_pop_interactive();
|
||||
proc_pop_interactive();
|
||||
proc_set_last_status( prev_status );
|
||||
}
|
||||
|
||||
if( b )
|
||||
{
|
||||
sb_destroy( b );
|
||||
free( b );
|
||||
free( b );
|
||||
}
|
||||
|
||||
|
||||
if( fire )
|
||||
{
|
||||
al_destroy( fire );
|
||||
free( fire );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Free killed events
|
||||
*/
|
||||
event_free_kills();
|
||||
|
||||
event_free_kills();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,7 +532,7 @@ static void event_fire_delayed()
|
||||
int i;
|
||||
|
||||
/*
|
||||
If is_event is one, we are running the event-handler non-recursively.
|
||||
If is_event is one, we are running the event-handler non-recursively.
|
||||
|
||||
When the event handler has called a piece of code that triggers
|
||||
another event, we do not want to fire delayed events because of
|
||||
@@ -523,7 +541,7 @@ static void event_fire_delayed()
|
||||
if( blocked && is_event==1)
|
||||
{
|
||||
array_list_t *new_blocked = 0;
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( blocked ); i++ )
|
||||
{
|
||||
event_t *e = (event_t *)al_get( blocked, i );
|
||||
@@ -531,24 +549,24 @@ static void event_fire_delayed()
|
||||
{
|
||||
if( !new_blocked )
|
||||
new_blocked = al_new();
|
||||
al_push( new_blocked, e );
|
||||
al_push( new_blocked, e );
|
||||
}
|
||||
else
|
||||
{
|
||||
event_fire_internal( e );
|
||||
event_free( e );
|
||||
}
|
||||
}
|
||||
}
|
||||
al_destroy( blocked );
|
||||
free( blocked );
|
||||
blocked = new_blocked;
|
||||
}
|
||||
|
||||
|
||||
while( sig_list[active_list].count > 0 )
|
||||
{
|
||||
signal_list_t *lst;
|
||||
event_t e;
|
||||
al_init( &e.arguments );
|
||||
al_init( &e.arguments );
|
||||
|
||||
/*
|
||||
Switch signal lists
|
||||
@@ -558,47 +576,47 @@ static void event_fire_delayed()
|
||||
active_list=1-active_list;
|
||||
|
||||
/*
|
||||
Set up
|
||||
Set up
|
||||
*/
|
||||
e.type=EVENT_SIGNAL;
|
||||
e.function_name=0;
|
||||
|
||||
|
||||
lst = &sig_list[1-active_list];
|
||||
|
||||
|
||||
if( lst->overflow )
|
||||
{
|
||||
debug( 0, _( L"Signal list overflow. Signals have been ignored." ) );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Send all signals in our private list
|
||||
*/
|
||||
for( i=0; i<lst->count; i++ )
|
||||
{
|
||||
e.param1.signal = lst->signal[i];
|
||||
al_set( &e.arguments, 0, sig2wcs( e.param1.signal ) );
|
||||
al_set( &e.arguments, 0, sig2wcs( e.param1.signal ) );
|
||||
if( event_is_blocked( &e ) )
|
||||
{
|
||||
if( !blocked )
|
||||
blocked = al_new();
|
||||
al_push( blocked, event_copy(&e, 1) );
|
||||
al_push( blocked, event_copy(&e, 1) );
|
||||
}
|
||||
else
|
||||
{
|
||||
event_fire_internal( &e );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
al_destroy( &e.arguments );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void event_fire( event_t *event )
|
||||
{
|
||||
is_event++;
|
||||
|
||||
|
||||
if( event && (event->type == EVENT_SIGNAL) )
|
||||
{
|
||||
/*
|
||||
@@ -614,16 +632,18 @@ void event_fire( event_t *event )
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*
|
||||
Fire events triggered by signals
|
||||
*/
|
||||
event_fire_delayed();
|
||||
|
||||
|
||||
if( event )
|
||||
{
|
||||
if( event_is_blocked( event ) )
|
||||
{
|
||||
if( !blocked )
|
||||
blocked = al_new();
|
||||
|
||||
|
||||
al_push( blocked, event_copy(event, 1) );
|
||||
}
|
||||
else
|
||||
@@ -631,8 +651,8 @@ void event_fire( event_t *event )
|
||||
event_fire_internal( event );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
is_event--;
|
||||
}
|
||||
|
||||
@@ -648,7 +668,7 @@ void event_destroy()
|
||||
{
|
||||
al_foreach( events, (void (*)(void *))&event_free );
|
||||
al_destroy( events );
|
||||
free( events );
|
||||
free( events );
|
||||
events=0;
|
||||
}
|
||||
|
||||
@@ -656,9 +676,9 @@ void event_destroy()
|
||||
{
|
||||
al_foreach( killme, (void (*)(void *))&event_free );
|
||||
al_destroy( killme );
|
||||
free( killme );
|
||||
killme=0;
|
||||
}
|
||||
free( killme );
|
||||
killme=0;
|
||||
}
|
||||
}
|
||||
|
||||
void event_free( event_t *e )
|
||||
@@ -673,7 +693,39 @@ void event_free( event_t *e )
|
||||
|
||||
free( (void *)e->function_name );
|
||||
if( e->type == EVENT_VARIABLE )
|
||||
{
|
||||
free( (void *)e->param1.variable );
|
||||
}
|
||||
else if( e->type == EVENT_GENERIC )
|
||||
{
|
||||
free( (void *)e->param1.param );
|
||||
}
|
||||
free( e );
|
||||
}
|
||||
|
||||
|
||||
void event_fire_generic_internal(const wchar_t *name, ...)
|
||||
{
|
||||
event_t ev;
|
||||
va_list va;
|
||||
wchar_t *arg;
|
||||
|
||||
CHECK( name, );
|
||||
|
||||
ev.type = EVENT_GENERIC;
|
||||
ev.param1.param = name;
|
||||
ev.function_name=0;
|
||||
|
||||
al_init( &ev.arguments );
|
||||
va_start( va, name );
|
||||
while( (arg=va_arg(va, wchar_t *) )!= 0 )
|
||||
{
|
||||
al_push( &ev.arguments, arg );
|
||||
}
|
||||
va_end( va );
|
||||
|
||||
event_fire( &ev );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
50
event.h
50
event.h
@@ -2,6 +2,12 @@
|
||||
|
||||
Functions for handling event triggers
|
||||
|
||||
Because most of these functions can be called by signal
|
||||
handler, it is important to make it well defined when these
|
||||
functions produce output or perform memory allocations, since
|
||||
such functions may not be safely called by signal handlers.
|
||||
|
||||
|
||||
*/
|
||||
#ifndef FISH_EVENT_H
|
||||
#define FISH_EVENT_H
|
||||
@@ -27,6 +33,7 @@ enum
|
||||
EVENT_VARIABLE, /**< An event triggered by a variable update */
|
||||
EVENT_EXIT, /**< An event triggered by a job or process exit */
|
||||
EVENT_JOB_ID, /**< An event triggered by a job exit */
|
||||
EVENT_GENERIC, /**< A generic event */
|
||||
}
|
||||
;
|
||||
|
||||
@@ -37,7 +44,7 @@ enum
|
||||
- When used as a parameter to event_add, it represents a class of events, and function_name is the name of the function which will be called whenever an event matching the specified class occurs. This is also how events are stored internally.
|
||||
- When used as a parameter to event_get, event_remove and event_fire, it represents a class of events, and if the function_name field is non-zero, only events which call the specified function will be returned.
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
Type of event
|
||||
@@ -67,13 +74,17 @@ typedef struct
|
||||
Job id for EVENT_JOB_ID type events
|
||||
*/
|
||||
int job_id;
|
||||
|
||||
/**
|
||||
The parameter describing this generic event
|
||||
*/
|
||||
const wchar_t *param;
|
||||
|
||||
} param1;
|
||||
|
||||
/**
|
||||
The name of the event handler function
|
||||
*/
|
||||
const wchar_t *function_name;
|
||||
const wchar_t *function_name;
|
||||
|
||||
/**
|
||||
The argument list. Only used when sending a new event using
|
||||
@@ -85,21 +96,28 @@ typedef struct
|
||||
event_t;
|
||||
|
||||
/**
|
||||
Add an event handler
|
||||
Add an event handler
|
||||
|
||||
May not be called by a signal handler, since it may allocate new memory.
|
||||
*/
|
||||
void event_add_handler( event_t *event );
|
||||
|
||||
/**
|
||||
Remove all events matching the specified criterion.
|
||||
Remove all events matching the specified criterion.
|
||||
|
||||
May not be called by a signal handler, since it may free allocated memory.
|
||||
*/
|
||||
void event_remove( event_t *event );
|
||||
|
||||
/**
|
||||
Return all events which match the specified event class
|
||||
Return all events which match the specified event class
|
||||
|
||||
This function is safe to call from a signal handler _ONLY_ if the
|
||||
out parameter is null.
|
||||
|
||||
\param criterion Is the class of events to return. If the criterion has a non-null function_name, only events which trigger the specified function will return.
|
||||
\param out the list to add events to. May be 0, in which case no events will be added, but the result count will still be valid
|
||||
|
||||
|
||||
\return the number of found matches
|
||||
*/
|
||||
int event_get( event_t *criterion, array_list_t *out );
|
||||
@@ -111,7 +129,14 @@ int event_get( event_t *criterion, array_list_t *out );
|
||||
called. If event is a null-pointer, all pending events are
|
||||
dispatched.
|
||||
|
||||
\param event the specific event whose handlers should fire
|
||||
This function is safe to call from a signal handler _ONLY_ if the
|
||||
event parameter is for a signal. Signal events not be fired, by the
|
||||
call to event_fire, instead they will be fired the next time
|
||||
event_fire is called with anull argument. This is needed to make
|
||||
sure that no code evaluation is ever performed by a signal handler.
|
||||
|
||||
\param event the specific event whose handlers should fire. If
|
||||
null, then all delayed events will be fired.
|
||||
*/
|
||||
void event_fire( event_t *event );
|
||||
|
||||
@@ -126,7 +151,7 @@ void event_init();
|
||||
void event_destroy();
|
||||
|
||||
/**
|
||||
Free all memory used by event
|
||||
Free all memory used by the specified event
|
||||
*/
|
||||
void event_free( event_t *e );
|
||||
|
||||
@@ -136,4 +161,11 @@ void event_free( event_t *e );
|
||||
*/
|
||||
const wchar_t *event_get_desc( event_t *e );
|
||||
|
||||
/**
|
||||
Fire a generic event with the specified name
|
||||
*/
|
||||
#define event_fire_generic( ... ) event_fire_generic_internal( __VA_ARGS__, (void *)0 )
|
||||
|
||||
void event_fire_generic_internal(const wchar_t *name,...);
|
||||
|
||||
#endif
|
||||
|
||||
4
exec.h
4
exec.h
@@ -19,7 +19,7 @@
|
||||
#define PIPE_ERROR _(L"An error occurred while setting up pipe")
|
||||
|
||||
/**
|
||||
Execute the processes specified by j.
|
||||
Execute the processes specified by j.
|
||||
|
||||
I've put a fair bit of work into making builtins behave like other
|
||||
programs as far as pipes are concerned. Unlike i.e. bash, builtins
|
||||
@@ -51,7 +51,7 @@ void exec( job_t *j );
|
||||
|
||||
\return the status of the last job to exit, or -1 if en error was encountered.
|
||||
*/
|
||||
__warn_unused int exec_subshell( const wchar_t *cmd,
|
||||
__warn_unused int exec_subshell( const wchar_t *cmd,
|
||||
array_list_t *l );
|
||||
|
||||
|
||||
|
||||
351
expand.c
351
expand.c
@@ -1,7 +1,7 @@
|
||||
/**\file expand.c
|
||||
|
||||
String expansion functions. These functions perform several kinds of
|
||||
parameter expansion.
|
||||
parameter expansion.
|
||||
|
||||
*/
|
||||
|
||||
@@ -85,7 +85,7 @@ parameter expansion.
|
||||
/**
|
||||
Description for short job. The job command is concatenated
|
||||
*/
|
||||
#define COMPLETE_JOB_DESC_VAL _( L"Job: ")
|
||||
#define COMPLETE_JOB_DESC_VAL _( L"Job: %ls")
|
||||
|
||||
/**
|
||||
Description for the shells own pid
|
||||
@@ -109,11 +109,11 @@ parameter expansion.
|
||||
|
||||
/**
|
||||
Characters which make a string unclean if they are the first
|
||||
character of the string. See \c is_clean().
|
||||
character of the string. See \c expand_is_clean().
|
||||
*/
|
||||
#define UNCLEAN_FIRST L"~%"
|
||||
/**
|
||||
Unclean characters. See \c is_clean().
|
||||
Unclean characters. See \c expand_is_clean().
|
||||
*/
|
||||
#define UNCLEAN L"$*?\\\"'({})"
|
||||
|
||||
@@ -168,7 +168,7 @@ static int is_quotable( wchar_t *str )
|
||||
case L'\t':
|
||||
case L'\r':
|
||||
case L'\b':
|
||||
case L'\e':
|
||||
case L'\x1b':
|
||||
return 0;
|
||||
|
||||
default:
|
||||
@@ -195,14 +195,14 @@ wchar_t *expand_escape_variable( const wchar_t *in )
|
||||
case 0:
|
||||
sb_append( &buff, L"''");
|
||||
break;
|
||||
|
||||
|
||||
case 1:
|
||||
{
|
||||
wchar_t *el = (wchar_t *)al_get( &l, 0 );
|
||||
|
||||
if( wcschr( el, L' ' ) && is_quotable( el ) )
|
||||
{
|
||||
sb_append2( &buff,
|
||||
sb_append( &buff,
|
||||
L"'",
|
||||
el,
|
||||
L"'",
|
||||
@@ -228,7 +228,7 @@ wchar_t *expand_escape_variable( const wchar_t *in )
|
||||
|
||||
if( is_quotable( el ) )
|
||||
{
|
||||
sb_append2( &buff,
|
||||
sb_append( &buff,
|
||||
L"'",
|
||||
el,
|
||||
L"'",
|
||||
@@ -276,14 +276,14 @@ static int match_pid( const wchar_t *cmd,
|
||||
int *offset)
|
||||
{
|
||||
/* Test for direct match */
|
||||
|
||||
|
||||
if( wcsncmp( cmd, proc, wcslen( proc ) ) == 0 )
|
||||
{
|
||||
if( offset )
|
||||
*offset = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Test if the commandline is a path to the command, if so we try
|
||||
to match against only the command part
|
||||
@@ -313,7 +313,7 @@ static int match_pid( const wchar_t *cmd,
|
||||
{
|
||||
if( offset )
|
||||
*offset = start+1-first_token;
|
||||
|
||||
|
||||
free( first_token );
|
||||
|
||||
return 1;
|
||||
@@ -329,14 +329,14 @@ static int match_pid( const wchar_t *cmd,
|
||||
Searches for a job with the specified job id, or a job or process
|
||||
which has the string \c proc as a prefix of its commandline.
|
||||
|
||||
If accept_incomplete is true, the remaining string for any matches
|
||||
If the ACCEPT_INCOMPLETE flag is set, the remaining string for any matches
|
||||
are inserted.
|
||||
|
||||
If accept_incomplete is false, any job matching the specified
|
||||
string is matched, and the job pgid is returned. If no job
|
||||
matches, all child processes are searched. If no child processes
|
||||
match, and <tt>fish</tt> can understand the contents of the /proc
|
||||
filesystem, all the users processes are searched for matches.
|
||||
Otherwise, any job matching the specified string is matched, and
|
||||
the job pgid is returned. If no job matches, all child processes
|
||||
are searched. If no child processes match, and <tt>fish</tt> can
|
||||
understand the contents of the /proc filesystem, all the users
|
||||
processes are searched for matches.
|
||||
*/
|
||||
|
||||
static int find_process( const wchar_t *proc,
|
||||
@@ -372,14 +372,20 @@ static int find_process( const wchar_t *proc,
|
||||
|
||||
if( wcsncmp( proc, jid, wcslen(proc ) )==0 )
|
||||
{
|
||||
al_push( out,
|
||||
wcsdupcat2( jid+wcslen(proc),
|
||||
COMPLETE_SEP_STR,
|
||||
COMPLETE_JOB_DESC_VAL,
|
||||
j->command,
|
||||
(void *)0 ) );
|
||||
string_buffer_t desc_buff;
|
||||
|
||||
sb_init( &desc_buff );
|
||||
|
||||
sb_printf( &desc_buff,
|
||||
COMPLETE_JOB_DESC_VAL,
|
||||
j->command );
|
||||
|
||||
completion_allocate( out,
|
||||
jid+wcslen(proc),
|
||||
(wchar_t *)desc_buff.buff,
|
||||
0 );
|
||||
|
||||
sb_destroy( &desc_buff );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +395,7 @@ static int find_process( const wchar_t *proc,
|
||||
|
||||
int jid;
|
||||
wchar_t *end;
|
||||
|
||||
|
||||
errno = 0;
|
||||
jid = wcstol( proc, &end, 10 );
|
||||
if( jid > 0 && !errno && !*end )
|
||||
@@ -397,7 +403,7 @@ static int find_process( const wchar_t *proc,
|
||||
j = job_get( jid );
|
||||
if( (j != 0) && (j->command != 0 ) )
|
||||
{
|
||||
|
||||
|
||||
{
|
||||
result = malloc(sizeof(wchar_t)*16 );
|
||||
swprintf( result, 16, L"%d", j->pgid );
|
||||
@@ -414,19 +420,18 @@ static int find_process( const wchar_t *proc,
|
||||
for( j=first_job; j != 0; j=j->next )
|
||||
{
|
||||
int offset;
|
||||
|
||||
|
||||
if( j->command == 0 )
|
||||
continue;
|
||||
|
||||
|
||||
if( match_pid( j->command, proc, flags, &offset ) )
|
||||
{
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
wchar_t *res = wcsdupcat2( j->command + offset + wcslen(proc),
|
||||
COMPLETE_SEP_STR,
|
||||
COMPLETE_JOB_DESC,
|
||||
(void *)0 );
|
||||
al_push( out, res );
|
||||
completion_allocate( out,
|
||||
j->command + offset + wcslen(proc),
|
||||
COMPLETE_JOB_DESC,
|
||||
0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -451,7 +456,7 @@ static int find_process( const wchar_t *proc,
|
||||
for( p=j->first_process; p; p=p->next )
|
||||
{
|
||||
int offset;
|
||||
|
||||
|
||||
if( p->actual_cmd == 0 )
|
||||
continue;
|
||||
|
||||
@@ -459,11 +464,10 @@ static int find_process( const wchar_t *proc,
|
||||
{
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
wchar_t *res = wcsdupcat2( p->actual_cmd + offset + wcslen(proc),
|
||||
COMPLETE_SEP_STR,
|
||||
COMPLETE_CHILD_PROCESS_DESC,
|
||||
(void *)0);
|
||||
al_push( out, res );
|
||||
completion_allocate( out,
|
||||
p->actual_cmd + offset + wcslen(proc),
|
||||
COMPLETE_CHILD_PROCESS_DESC,
|
||||
0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -492,7 +496,7 @@ static int find_process( const wchar_t *proc,
|
||||
pdir_name = malloc( sizeof(wchar_t)*256 );
|
||||
pfile_name = malloc( sizeof(wchar_t)*64 );
|
||||
wcscpy( pdir_name, L"/proc/" );
|
||||
|
||||
|
||||
while( (next=wreaddir(dir))!=0 )
|
||||
{
|
||||
wchar_t *name = next->d_name;
|
||||
@@ -529,7 +533,7 @@ static int find_process( const wchar_t *proc,
|
||||
signal_block();
|
||||
fgetws2( &cmd, &sz, cmdfile );
|
||||
signal_unblock();
|
||||
|
||||
|
||||
fclose( cmdfile );
|
||||
}
|
||||
else
|
||||
@@ -570,18 +574,15 @@ static int find_process( const wchar_t *proc,
|
||||
if( cmd != 0 )
|
||||
{
|
||||
int offset;
|
||||
|
||||
|
||||
if( match_pid( cmd, proc, flags, &offset ) )
|
||||
{
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
wchar_t *res = wcsdupcat2( cmd + offset + wcslen(proc),
|
||||
COMPLETE_SEP_STR,
|
||||
COMPLETE_PROCESS_DESC,
|
||||
(void *)0);
|
||||
if( res )
|
||||
al_push( out, res );
|
||||
|
||||
completion_allocate( out,
|
||||
cmd + offset + wcslen(proc),
|
||||
COMPLETE_PROCESS_DESC,
|
||||
0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -614,7 +615,7 @@ static int expand_pid( wchar_t *in,
|
||||
|
||||
CHECK( in, 0 );
|
||||
CHECK( out, 0 );
|
||||
|
||||
|
||||
if( *in != PROCESS_EXPAND )
|
||||
{
|
||||
al_push( out, in );
|
||||
@@ -625,13 +626,17 @@ static int expand_pid( wchar_t *in,
|
||||
{
|
||||
if( wcsncmp( in+1, SELF_STR, wcslen(in+1) )==0 )
|
||||
{
|
||||
wchar_t *res = wcsdupcat2( SELF_STR+wcslen(in+1), COMPLETE_SEP_STR, COMPLETE_SELF_DESC, (void *)0 );
|
||||
al_push( out, res );
|
||||
completion_allocate( out,
|
||||
SELF_STR+wcslen(in+1),
|
||||
COMPLETE_SELF_DESC,
|
||||
0 );
|
||||
}
|
||||
else if( wcsncmp( in+1, LAST_STR, wcslen(in+1) )==0 )
|
||||
{
|
||||
wchar_t *res = wcsdupcat2( LAST_STR+wcslen(in+1), COMPLETE_SEP_STR, COMPLETE_LAST_DESC, (void *)0 );
|
||||
al_push( out, res );
|
||||
completion_allocate( out,
|
||||
LAST_STR+wcslen(in+1),
|
||||
COMPLETE_LAST_DESC,
|
||||
0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -687,7 +692,7 @@ static int expand_pid( wchar_t *in,
|
||||
void expand_variable_error( const wchar_t *token, int token_pos, int error_pos )
|
||||
{
|
||||
int stop_pos = token_pos+1;
|
||||
|
||||
|
||||
switch( token[stop_pos] )
|
||||
{
|
||||
case BRACKET_BEGIN:
|
||||
@@ -702,13 +707,13 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos )
|
||||
{
|
||||
post = end+1;
|
||||
*end = 0;
|
||||
|
||||
|
||||
if( !wcsvarname( name ) )
|
||||
{
|
||||
is_var = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( is_var )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
@@ -716,7 +721,7 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos )
|
||||
COMPLETE_VAR_BRACKET_DESC,
|
||||
cpy,
|
||||
name,
|
||||
post );
|
||||
post );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -728,18 +733,18 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos )
|
||||
L"" );
|
||||
}
|
||||
free( cpy );
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case INTERNAL_SEPARATOR:
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
error_pos,
|
||||
COMPLETE_VAR_PARAN_DESC );
|
||||
COMPLETE_VAR_PARAN_DESC );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 0:
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
@@ -747,7 +752,7 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos )
|
||||
COMPLETE_VAR_NULL_DESC );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
@@ -759,31 +764,33 @@ void expand_variable_error( const wchar_t *token, int token_pos, int error_pos )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse an array slicing specification
|
||||
*/
|
||||
static int parse_slice( wchar_t *in, wchar_t **end_ptr, array_list_t *idx )
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
wchar_t *end;
|
||||
|
||||
|
||||
int pos = 1;
|
||||
|
||||
// debug( 0, L"parse_slice on '%ls'", in );
|
||||
|
||||
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
long tmp;
|
||||
|
||||
|
||||
while( iswspace(in[pos]) || (in[pos]==INTERNAL_SEPARATOR))
|
||||
pos++;
|
||||
|
||||
pos++;
|
||||
|
||||
if( in[pos] == L']' )
|
||||
{
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
errno=0;
|
||||
tmp = wcstol( &in[pos], &end, 10 );
|
||||
if( ( errno ) || ( end == &in[pos] ) )
|
||||
@@ -791,19 +798,19 @@ static int parse_slice( wchar_t *in, wchar_t **end_ptr, array_list_t *idx )
|
||||
return 1;
|
||||
}
|
||||
// debug( 0, L"Push idx %d", tmp );
|
||||
|
||||
|
||||
al_push_long( idx, tmp );
|
||||
pos = end-in;
|
||||
}
|
||||
|
||||
|
||||
if( end_ptr )
|
||||
{
|
||||
// debug( 0, L"Remainder is '%ls', slice def was %d characters long", in+pos, pos );
|
||||
|
||||
|
||||
*end_ptr = in+pos;
|
||||
}
|
||||
// debug( 0, L"ok, done" );
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -836,7 +843,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
|
||||
CHECK( in, 0 );
|
||||
CHECK( out, 0 );
|
||||
|
||||
|
||||
if( !var_tmp )
|
||||
{
|
||||
var_tmp = sb_halloc( global_context );
|
||||
@@ -871,7 +878,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
wchar_t * new_in;
|
||||
int is_single = (c==VARIABLE_EXPAND_SINGLE);
|
||||
int var_name_stop_pos;
|
||||
|
||||
|
||||
stop_pos = start_pos;
|
||||
|
||||
while( 1 )
|
||||
@@ -885,15 +892,15 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
stop_pos++;
|
||||
}
|
||||
var_name_stop_pos = stop_pos;
|
||||
|
||||
|
||||
/* printf( "Stop for '%c'\n", in[stop_pos]);*/
|
||||
|
||||
var_len = stop_pos - start_pos;
|
||||
|
||||
if( var_len == 0 )
|
||||
{
|
||||
expand_variable_error( in, stop_pos-1, -1 );
|
||||
|
||||
expand_variable_error( in, stop_pos-1, -1 );
|
||||
|
||||
is_ok = 0;
|
||||
break;
|
||||
}
|
||||
@@ -912,17 +919,17 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
{
|
||||
wchar_t *slice_end;
|
||||
all_vars=0;
|
||||
|
||||
|
||||
if( parse_slice( &in[stop_pos], &slice_end, var_idx_list ) )
|
||||
{
|
||||
error( SYNTAX_ERROR,
|
||||
-1,
|
||||
L"Invalid index value" );
|
||||
L"Invalid index value" );
|
||||
is_ok = 0;
|
||||
}
|
||||
}
|
||||
stop_pos = (slice_end-in);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
tokenize_variable_array( var_val, &var_item_list );
|
||||
@@ -967,12 +974,12 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
|
||||
|
||||
if( is_single )
|
||||
{
|
||||
string_buffer_t res;
|
||||
in[i]=0;
|
||||
|
||||
|
||||
sb_init( &res );
|
||||
sb_append( &res, in );
|
||||
sb_append_char( &res, INTERNAL_SEPARATOR );
|
||||
@@ -980,7 +987,7 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
for( j=0; j<al_get_count( &var_item_list); j++ )
|
||||
{
|
||||
wchar_t *next = (wchar_t *)al_get( &var_item_list, j );
|
||||
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
if( j != 0 )
|
||||
@@ -1003,19 +1010,19 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
if( is_ok )
|
||||
{
|
||||
new_len = wcslen(in) - (stop_pos-start_pos+1);
|
||||
new_len += wcslen( next) +2;
|
||||
|
||||
|
||||
if( !(new_in = malloc( sizeof(wchar_t)*new_len )))
|
||||
{
|
||||
DIE_MEM();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
wcslcpy( new_in, in, start_pos );
|
||||
|
||||
if(start_pos>1 && new_in[start_pos-2]!=VARIABLE_EXPAND)
|
||||
@@ -1025,20 +1032,20 @@ static int expand_variables( wchar_t *in, array_list_t *out, int last_idx )
|
||||
}
|
||||
else
|
||||
new_in[start_pos-1]=L'\0';
|
||||
|
||||
|
||||
wcscat( new_in, next );
|
||||
wcscat( new_in, &in[stop_pos] );
|
||||
|
||||
|
||||
is_ok &= expand_variables( new_in, out, i );
|
||||
}
|
||||
}
|
||||
free( next );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(in);
|
||||
al_destroy( &var_item_list );
|
||||
return is_ok;
|
||||
@@ -1109,7 +1116,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
|
||||
CHECK( in, 0 );
|
||||
CHECK( out, 0 );
|
||||
|
||||
|
||||
for( pos=in;
|
||||
(*pos) && !syntax_error;
|
||||
pos++ )
|
||||
@@ -1131,7 +1138,7 @@ static int expand_brackets( wchar_t *in, int flags, array_list_t *out )
|
||||
{
|
||||
bracket_end = pos;
|
||||
}
|
||||
|
||||
|
||||
if( bracket_count < 0 )
|
||||
{
|
||||
syntax_error = 1;
|
||||
@@ -1239,12 +1246,12 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out )
|
||||
array_list_t *sub_res, *tail_expand;
|
||||
int i, j;
|
||||
const wchar_t *item_begin;
|
||||
wchar_t *tail_begin = 0;
|
||||
wchar_t *tail_begin = 0;
|
||||
void *context;
|
||||
|
||||
CHECK( in, 0 );
|
||||
CHECK( out, 0 );
|
||||
|
||||
|
||||
|
||||
|
||||
switch( parse_util_locate_cmdsubst(in,
|
||||
@@ -1274,7 +1281,7 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out )
|
||||
sub_res = al_halloc( context );
|
||||
if( !(subcmd = halloc( context, sizeof(wchar_t)*(paran_end-paran_begin) )))
|
||||
{
|
||||
halloc_free( context );
|
||||
halloc_free( context );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1293,10 +1300,10 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out )
|
||||
{
|
||||
array_list_t *slice_idx = al_halloc( context );
|
||||
wchar_t *slice_end;
|
||||
|
||||
|
||||
if( parse_slice( tail_begin, &slice_end, slice_idx ) )
|
||||
{
|
||||
halloc_free( context );
|
||||
halloc_free( context );
|
||||
error( SYNTAX_ERROR, -1, L"Invalid index value" );
|
||||
return 0;
|
||||
}
|
||||
@@ -1311,23 +1318,23 @@ static int expand_cmdsubst( wchar_t *in, array_list_t *out )
|
||||
{
|
||||
idx = al_get_count( sub_res ) + idx + 1;
|
||||
}
|
||||
|
||||
|
||||
if( idx < 1 || idx > al_get_count( sub_res ) )
|
||||
{
|
||||
halloc_free( context );
|
||||
error( SYNTAX_ERROR, -1, L"Invalid index value" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
idx = idx-1;
|
||||
|
||||
|
||||
al_push( sub_res2, al_get( sub_res, idx ) );
|
||||
// debug( 0, L"Pushing item '%ls' with index %d onto sliced result", al_get( sub_res, idx ), idx );
|
||||
|
||||
|
||||
al_set( sub_res, idx, 0 );
|
||||
}
|
||||
al_foreach( sub_res, &free );
|
||||
sub_res = sub_res2;
|
||||
sub_res = sub_res2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1364,16 +1371,16 @@ static int expand_cmdsubst( 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 );
|
||||
}
|
||||
|
||||
|
||||
free( sub_item2 );
|
||||
}
|
||||
free(in);
|
||||
|
||||
al_foreach( tail_expand, &free );
|
||||
halloc_free( context );
|
||||
halloc_free( context );
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1474,7 +1481,7 @@ static wchar_t * expand_tilde_internal( wchar_t *in )
|
||||
wchar_t *expand_tilde( wchar_t *in)
|
||||
{
|
||||
CHECK( in, 0 );
|
||||
|
||||
|
||||
if( in[0] == L'~' )
|
||||
{
|
||||
in[0] = HOME_DIRECTORY;
|
||||
@@ -1491,7 +1498,7 @@ static void remove_internal_separator( const void *s, int conv )
|
||||
{
|
||||
wchar_t *in = (wchar_t *)s;
|
||||
wchar_t *out=in;
|
||||
|
||||
|
||||
CHECK( s, );
|
||||
|
||||
while( *in )
|
||||
@@ -1501,7 +1508,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;
|
||||
@@ -1512,6 +1519,11 @@ static void remove_internal_separator( const void *s, int conv )
|
||||
*out++ = conv?L'*':ANY_STRING;
|
||||
break;
|
||||
|
||||
case ANY_STRING_RECURSIVE:
|
||||
in++;
|
||||
*out++ = conv?L'*':ANY_STRING_RECURSIVE;
|
||||
break;
|
||||
|
||||
default:
|
||||
*out++ = *in++;
|
||||
}
|
||||
@@ -1519,6 +1531,7 @@ static void remove_internal_separator( const void *s, int conv )
|
||||
*out=0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The real expansion function. expand_one is just a wrapper around this one.
|
||||
*/
|
||||
@@ -1551,7 +1564,7 @@ int expand_string( void *context,
|
||||
if( EXPAND_SKIP_CMDSUBST & flags )
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
|
||||
|
||||
if( parse_util_locate_cmdsubst( str,
|
||||
&begin,
|
||||
&end,
|
||||
@@ -1598,7 +1611,7 @@ int expand_string( void *context,
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( EXPAND_SKIP_VARIABLES & flags )
|
||||
@@ -1632,8 +1645,8 @@ int expand_string( void *context,
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !expand_brackets( next, flags, out ))
|
||||
{
|
||||
@@ -1654,8 +1667,8 @@ int expand_string( void *context,
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !(next=expand_tilde_internal( next ) ) )
|
||||
{
|
||||
@@ -1679,7 +1692,9 @@ int expand_string( void *context,
|
||||
return EXPAND_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
al_push( out, next );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1704,65 +1719,83 @@ int expand_string( void *context,
|
||||
if( !next )
|
||||
{
|
||||
debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ );
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
remove_internal_separator( next, EXPAND_SKIP_WILDCARDS & flags );
|
||||
|
||||
|
||||
if( ((flags & ACCEPT_INCOMPLETE) && (!(flags & EXPAND_SKIP_WILDCARDS))) ||
|
||||
wildcard_has( next, 1 ) )
|
||||
{
|
||||
wchar_t *start, *rest;
|
||||
array_list_t *list = out;
|
||||
|
||||
if( next[0] == '/' )
|
||||
{
|
||||
wc_res = wildcard_expand( &next[1], L"/",flags, out );
|
||||
start = L"/";
|
||||
rest = &next[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
wc_res = wildcard_expand( next, L"", flags, out );
|
||||
start = L"";
|
||||
rest = next;
|
||||
}
|
||||
free( next );
|
||||
switch( wc_res )
|
||||
|
||||
if( flags & ACCEPT_INCOMPLETE )
|
||||
{
|
||||
case 0:
|
||||
list = end_out;
|
||||
}
|
||||
|
||||
wc_res = wildcard_expand( rest, start, flags, list );
|
||||
|
||||
free( next );
|
||||
|
||||
if( !(flags & ACCEPT_INCOMPLETE) )
|
||||
{
|
||||
|
||||
switch( wc_res )
|
||||
{
|
||||
if( !(flags & ACCEPT_INCOMPLETE) )
|
||||
case 0:
|
||||
{
|
||||
if( res == EXPAND_OK )
|
||||
res = EXPAND_WILDCARD_NO_MATCH;
|
||||
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 );
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
int j;
|
||||
res = EXPAND_WILDCARD_MATCH;
|
||||
sort_list( out );
|
||||
|
||||
for( j=0; j<al_get_count( out ); j++ )
|
||||
case -1:
|
||||
{
|
||||
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_foreach( out, &free );
|
||||
al_destroy( in );
|
||||
al_destroy( out );
|
||||
return EXPAND_ERROR;
|
||||
}
|
||||
al_truncate( out, 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
case -1:
|
||||
{
|
||||
al_foreach( out, &free );
|
||||
al_destroy( in );
|
||||
al_destroy( out );
|
||||
return EXPAND_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1775,6 +1808,7 @@ int expand_string( void *context,
|
||||
al_push( end_out, next );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
al_destroy( in );
|
||||
al_destroy( out );
|
||||
@@ -1787,7 +1821,8 @@ int expand_string( void *context,
|
||||
halloc_register( context, (void *)al_get( end_out, i ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return res;
|
||||
|
||||
}
|
||||
@@ -1800,13 +1835,13 @@ wchar_t *expand_one( void *context, wchar_t *string, int flags )
|
||||
wchar_t *one;
|
||||
|
||||
CHECK( string, 0 );
|
||||
|
||||
|
||||
if( (!(flags & ACCEPT_INCOMPLETE)) && expand_is_clean( string ) )
|
||||
{
|
||||
halloc_register( context, string );
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
al_init( &l );
|
||||
res = expand_string( 0, string, &l, flags );
|
||||
if( !res )
|
||||
|
||||
18
expand.h
18
expand.h
@@ -6,7 +6,7 @@
|
||||
benefit from using a more clever memory allocation scheme, perhaps
|
||||
an evil combination of talloc, string buffers and reference
|
||||
counting.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#ifndef FISH_EXPAND_H
|
||||
@@ -58,6 +58,10 @@
|
||||
Use unencoded private-use keycodes for internal characters
|
||||
*/
|
||||
#define EXPAND_RESERVED 0xf000
|
||||
/**
|
||||
End of range reserved for expand
|
||||
*/
|
||||
#define EXPAND_RESERVED_END 0xf000f
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -66,7 +70,7 @@ enum
|
||||
|
||||
/** Character represeting process expansion */
|
||||
PROCESS_EXPAND,
|
||||
|
||||
|
||||
/** Character representing variable expansion */
|
||||
VARIABLE_EXPAND,
|
||||
|
||||
@@ -82,7 +86,7 @@ enum
|
||||
/** Character representing separation between two bracket elements */
|
||||
BRACKET_SEP,
|
||||
/**
|
||||
Separate subtokens in a token with this character.
|
||||
Separate subtokens in a token with this character.
|
||||
*/
|
||||
INTERNAL_SEPARATOR,
|
||||
|
||||
@@ -124,7 +128,7 @@ enum
|
||||
(\$VAR_NAME becomes the value of the environment variable VAR_NAME),
|
||||
cmdsubst expansion and wildcard expansion. The results are inserted
|
||||
into the list out.
|
||||
|
||||
|
||||
If the parameter does not need expansion, it is copied into the list
|
||||
out. If expansion is performed, the original parameter is freed and
|
||||
newly allocated strings are inserted into the list out.
|
||||
@@ -132,7 +136,7 @@ enum
|
||||
If \c context is non-null, all the strings contained in the
|
||||
array_list_t \c out will be registered to be free'd when context is
|
||||
free'd.
|
||||
|
||||
|
||||
\param context the halloc context to use for automatic deallocation
|
||||
\param in The parameter to expand
|
||||
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
|
||||
@@ -148,8 +152,8 @@ __warn_unused int expand_string( void *context, wchar_t *in, array_list_t *out,
|
||||
|
||||
If \c context is non-null, the returning string ill be registered
|
||||
to be free'd when context is free'd.
|
||||
|
||||
\param context the halloc context to use for automatic deallocation
|
||||
|
||||
\param context the halloc context to use for automatic deallocation
|
||||
\param in The parameter to expand
|
||||
\param flag Specifies if any expansion pass should be skipped. Legal values are any combination of EXPAND_SKIP_CMDSUBST EXPAND_SKIP_VARIABLES and EXPAND_SKIP_WILDCARDS
|
||||
\return The expanded parameter, or 0 on failiure
|
||||
|
||||
282
fallback.c
282
fallback.c
@@ -60,11 +60,69 @@ int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t))
|
||||
while( *str )
|
||||
{
|
||||
fish_putc( *str++ );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TPARM_SOLARIS_KLUDGE
|
||||
|
||||
#undef tparm
|
||||
|
||||
/**
|
||||
Checks for known string values and maps to correct number of parameters.
|
||||
*/
|
||||
char *tparm_solaris_kludge( char *str, ... )
|
||||
{
|
||||
long int param[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
va_list ap;
|
||||
va_start( ap, str );
|
||||
|
||||
if( ( set_a_foreground && ! strcmp( str, set_a_foreground ) )
|
||||
|| ( set_a_background && ! strcmp( str, set_a_background ) )
|
||||
|| ( set_foreground && ! strcmp( str, set_foreground ) )
|
||||
|| ( set_background && ! strcmp( str, set_background ) )
|
||||
|| ( enter_underline_mode && ! strcmp( str, enter_underline_mode ) )
|
||||
|| ( exit_underline_mode && ! strcmp( str, exit_underline_mode ) )
|
||||
|| ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) )
|
||||
|| ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) )
|
||||
|| ( flash_screen && ! strcmp( str, flash_screen ) )
|
||||
|| ( enter_subscript_mode && ! strcmp( str, enter_subscript_mode ) )
|
||||
|| ( exit_subscript_mode && ! strcmp( str, exit_subscript_mode ) )
|
||||
|| ( enter_superscript_mode && ! strcmp( str, enter_superscript_mode ) )
|
||||
|| ( exit_superscript_mode && ! strcmp( str, exit_superscript_mode ) )
|
||||
|| ( enter_blink_mode && ! strcmp( str, enter_blink_mode ) )
|
||||
|| ( enter_italics_mode && ! strcmp( str, enter_italics_mode ) )
|
||||
|| ( exit_italics_mode && ! strcmp( str, exit_italics_mode ) )
|
||||
|| ( enter_reverse_mode && ! strcmp( str, enter_reverse_mode ) )
|
||||
|| ( enter_shadow_mode && ! strcmp( str, enter_shadow_mode ) )
|
||||
|| ( exit_shadow_mode && ! strcmp( str, exit_shadow_mode ) )
|
||||
|| ( enter_standout_mode && ! strcmp( str, enter_standout_mode ) )
|
||||
|| ( exit_standout_mode && ! strcmp( str, exit_standout_mode ) )
|
||||
|| ( enter_secure_mode && ! strcmp( str, enter_secure_mode ) )
|
||||
|| ( enter_bold_mode && ! strcmp ( str, enter_bold_mode ) ) )
|
||||
{
|
||||
param[0] = va_arg( ap, long int );
|
||||
}
|
||||
else if( cursor_address && ! strcmp( str, cursor_address ) )
|
||||
{
|
||||
param[0] = va_arg( ap, long int );
|
||||
param[1] = va_arg( ap, long int );
|
||||
}
|
||||
|
||||
va_end( ap );
|
||||
|
||||
|
||||
return tparm( str, param[0], param[1], param[2], param[3],
|
||||
param[4], param[5], param[6], param[7], param[8] );
|
||||
}
|
||||
|
||||
// Re-defining just to make sure nothing breaks further down in this file.
|
||||
#define tparm tparm_solaris_kludge
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_FWPRINTF
|
||||
#define INTERNAL_FWPRINTF 1
|
||||
@@ -82,11 +140,11 @@ int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t))
|
||||
*/
|
||||
static void pad( void (*writer)(wchar_t), int count)
|
||||
{
|
||||
|
||||
|
||||
int i;
|
||||
if( count < 0 )
|
||||
return;
|
||||
|
||||
|
||||
for( i=0; i<count; i++ )
|
||||
{
|
||||
writer( L' ' );
|
||||
@@ -113,13 +171,13 @@ static void pad( void (*writer)(wchar_t), int count)
|
||||
|
||||
For a full description on the usage of *printf, see use 'man 3 printf'.
|
||||
*/
|
||||
static int vgwprintf( void (*writer)(wchar_t),
|
||||
const wchar_t *filter,
|
||||
static int vgwprintf( void (*writer)(wchar_t),
|
||||
const wchar_t *filter,
|
||||
va_list va )
|
||||
{
|
||||
const wchar_t *filter_org=filter;
|
||||
int count=0;
|
||||
|
||||
|
||||
for( ;*filter; filter++)
|
||||
{
|
||||
if(*filter == L'%')
|
||||
@@ -130,19 +188,19 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
int loop=1;
|
||||
int precision=-1;
|
||||
int pad_left = 1;
|
||||
|
||||
|
||||
if( iswdigit( *filter ) )
|
||||
{
|
||||
width=0;
|
||||
while( (*filter >= L'0') && (*filter <= L'9'))
|
||||
{
|
||||
width=10*width+(*filter++ - L'0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while( loop )
|
||||
{
|
||||
|
||||
|
||||
switch(*filter)
|
||||
{
|
||||
case L'l':
|
||||
@@ -161,9 +219,9 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
filter++;
|
||||
pad_left=0;
|
||||
break;
|
||||
|
||||
|
||||
case L'.':
|
||||
/*
|
||||
/*
|
||||
Set precision.
|
||||
*/
|
||||
filter++;
|
||||
@@ -177,10 +235,10 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
while( (*filter >= L'0') && (*filter <= L'9'))
|
||||
{
|
||||
precision=10*precision+(*filter++ - L'0');
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
loop=0;
|
||||
break;
|
||||
@@ -195,8 +253,8 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
|
||||
if( (width >= 0) && pad_left )
|
||||
{
|
||||
pad( writer, width-1 );
|
||||
count += maxi( width-1, 0 );
|
||||
pad( writer, width-1 );
|
||||
count += maxi( width-1, 0 );
|
||||
}
|
||||
|
||||
c = is_long?va_arg(va, wint_t):btowc(va_arg(va, int));
|
||||
@@ -207,16 +265,16 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
if( (width >= 0) && !pad_left )
|
||||
{
|
||||
pad( writer, width-1 );
|
||||
count += maxi( width-1, 0 );
|
||||
count += maxi( width-1, 0 );
|
||||
}
|
||||
|
||||
|
||||
count++;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case L's':
|
||||
{
|
||||
|
||||
{
|
||||
|
||||
wchar_t *ss=0;
|
||||
if( is_long )
|
||||
{
|
||||
@@ -229,41 +287,41 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
if( ns )
|
||||
{
|
||||
ss = str2wcs( ns );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( !ss )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if( (width >= 0) && pad_left )
|
||||
{
|
||||
pad( writer, width-wcslen(ss) );
|
||||
count += maxi(width-wcslen(ss), 0);
|
||||
pad( writer, width-wcslen(ss) );
|
||||
count += maxi(width-wcslen(ss), 0);
|
||||
}
|
||||
|
||||
|
||||
wchar_t *s=ss;
|
||||
int precount = count;
|
||||
|
||||
|
||||
while( *s )
|
||||
{
|
||||
if( (precision > 0) && (precision <= (count-precount) ) )
|
||||
break;
|
||||
|
||||
|
||||
writer( *(s++) );
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
if( (width >= 0) && !pad_left )
|
||||
{
|
||||
pad( writer, width-wcslen(ss) );
|
||||
count += maxi( width-wcslen(ss), 0 );
|
||||
pad( writer, width-wcslen(ss) );
|
||||
count += maxi( width-wcslen(ss), 0 );
|
||||
}
|
||||
|
||||
|
||||
if( !is_long )
|
||||
free( ss );
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -278,7 +336,7 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
char *pos;
|
||||
char format[16];
|
||||
int len;
|
||||
|
||||
|
||||
format[0]=0;
|
||||
strcat( format, "%");
|
||||
if( precision >= 0 )
|
||||
@@ -292,7 +350,7 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
strcat( format, "l" );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
len = strlen(format);
|
||||
format[len++]=(char)*filter;
|
||||
format[len]=0;
|
||||
@@ -302,7 +360,7 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
case L'd':
|
||||
case L'i':
|
||||
{
|
||||
|
||||
|
||||
switch( is_long )
|
||||
{
|
||||
case 0:
|
||||
@@ -312,10 +370,10 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
snprintf( str, 32, format, precision, d );
|
||||
else
|
||||
snprintf( str, 32, format, d );
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 1:
|
||||
{
|
||||
long d = va_arg( va, long );
|
||||
@@ -325,7 +383,7 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
snprintf( str, 32, format, d );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 2:
|
||||
{
|
||||
long long d = va_arg( va, long long );
|
||||
@@ -335,21 +393,21 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
snprintf( str, 32, format, d );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
debug( 0, L"Invalid length modifier in string %ls\n", filter_org );
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
case L'u':
|
||||
case L'o':
|
||||
case L'x':
|
||||
case L'X':
|
||||
{
|
||||
|
||||
|
||||
switch( is_long )
|
||||
{
|
||||
case 0:
|
||||
@@ -361,7 +419,7 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
snprintf( str, 32, format, d );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 1:
|
||||
{
|
||||
unsigned long d = va_arg( va, unsigned long );
|
||||
@@ -371,7 +429,7 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
snprintf( str, 32, format, d );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 2:
|
||||
{
|
||||
unsigned long long d = va_arg( va, unsigned long long );
|
||||
@@ -381,43 +439,43 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
snprintf( str, 32, format, d );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
debug( 0, L"Invalid length modifier in string %ls\n", filter_org );
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
debug( 0, L"Invalid filter %ls in string %ls\n", *filter, filter_org );
|
||||
return -1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
if( (width >= 0) && pad_left )
|
||||
{
|
||||
int l = maxi(width-strlen(str), 0 );
|
||||
pad( writer, l );
|
||||
count += l;
|
||||
}
|
||||
|
||||
|
||||
pos = str;
|
||||
|
||||
|
||||
while( *pos )
|
||||
{
|
||||
writer( *(pos++) );
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
if( (width >= 0) && !pad_left )
|
||||
{
|
||||
int l = maxi(width-strlen(str), 0 );
|
||||
pad( writer, l );
|
||||
count += l;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -426,7 +484,7 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
char str[32];
|
||||
char *pos;
|
||||
double val = va_arg( va, double );
|
||||
|
||||
|
||||
if( precision>= 0 )
|
||||
{
|
||||
if( width>= 0 )
|
||||
@@ -451,21 +509,21 @@ static int vgwprintf( void (*writer)(wchar_t),
|
||||
}
|
||||
|
||||
pos = str;
|
||||
|
||||
|
||||
while( *pos )
|
||||
{
|
||||
writer( *(pos++) );
|
||||
count++;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case L'n':
|
||||
{
|
||||
int *n = va_arg( va, int *);
|
||||
|
||||
*n = count;
|
||||
|
||||
*n = count;
|
||||
break;
|
||||
}
|
||||
case L'%':
|
||||
@@ -506,14 +564,14 @@ sw_data;
|
||||
static void sw_writer( wchar_t c )
|
||||
{
|
||||
if( sw_data.count < sw_data.max )
|
||||
*(sw_data.pos++)=c;
|
||||
*(sw_data.pos++)=c;
|
||||
sw_data.count++;
|
||||
}
|
||||
|
||||
int vswprintf( wchar_t *out, size_t n, const wchar_t *filter, va_list va )
|
||||
{
|
||||
int written;
|
||||
|
||||
|
||||
sw_data.pos=out;
|
||||
sw_data.max=n;
|
||||
sw_data.count=0;
|
||||
@@ -528,7 +586,7 @@ int vswprintf( wchar_t *out, size_t n, const wchar_t *filter, va_list va )
|
||||
{
|
||||
written=-1;
|
||||
}
|
||||
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
@@ -536,7 +594,7 @@ int swprintf( wchar_t *out, size_t n, const wchar_t *filter, ... )
|
||||
{
|
||||
va_list va;
|
||||
int written;
|
||||
|
||||
|
||||
va_start( va, filter );
|
||||
written = vswprintf( out, n, filter, va );
|
||||
va_end( va );
|
||||
@@ -566,7 +624,7 @@ int fwprintf( FILE *f, const wchar_t *filter, ... )
|
||||
{
|
||||
va_list va;
|
||||
int written;
|
||||
|
||||
|
||||
va_start( va, filter );
|
||||
written = vfwprintf( f, filter, va );
|
||||
va_end( va );
|
||||
@@ -582,7 +640,7 @@ int wprintf( const wchar_t *filter, ... )
|
||||
{
|
||||
va_list va;
|
||||
int written;
|
||||
|
||||
|
||||
va_start( va, filter );
|
||||
written=vwprintf( filter, va );
|
||||
va_end( va );
|
||||
@@ -603,16 +661,16 @@ wint_t fgetwc(FILE *stream)
|
||||
{
|
||||
int b = fgetc( stream );
|
||||
char bb;
|
||||
|
||||
|
||||
int sz;
|
||||
|
||||
|
||||
if( b == EOF )
|
||||
return WEOF;
|
||||
|
||||
bb=b;
|
||||
|
||||
|
||||
sz = mbrtowc( &res, &bb, 1, &state );
|
||||
|
||||
|
||||
switch( sz )
|
||||
{
|
||||
case -1:
|
||||
@@ -675,13 +733,13 @@ static size_t fish_wcsspn (const wchar_t *wcs,
|
||||
for (a = accept; *a != L'\0'; ++a)
|
||||
if (*p == *a)
|
||||
break;
|
||||
|
||||
|
||||
if (*a == L'\0')
|
||||
return count;
|
||||
else
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -694,7 +752,7 @@ static wchar_t *fish_wcspbrk (const wchar_t *wcs, const wchar_t *accept)
|
||||
++wcs;
|
||||
else
|
||||
return (wchar_t *) wcs;
|
||||
return NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -717,18 +775,18 @@ wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **save_ptr)
|
||||
|
||||
/* Scan leading delimiters. */
|
||||
wcs += fish_wcsspn (wcs, delim);
|
||||
|
||||
|
||||
if (*wcs == L'\0')
|
||||
{
|
||||
*save_ptr = NULL;
|
||||
*save_ptr = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find the end of the token. */
|
||||
result = wcs;
|
||||
|
||||
|
||||
wcs = fish_wcspbrk (result, delim);
|
||||
|
||||
|
||||
if (wcs == NULL)
|
||||
{
|
||||
/* This token finishes the string. */
|
||||
@@ -757,7 +815,7 @@ wchar_t *wcsdup( const wchar_t *in )
|
||||
|
||||
memcpy( out, in, sizeof( wchar_t)*(len+1));
|
||||
return out;
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -797,7 +855,7 @@ int wcsncasecmp( const wchar_t *a, const wchar_t *b, int count )
|
||||
{
|
||||
if( count == 0 )
|
||||
return 0;
|
||||
|
||||
|
||||
if( *a == 0 )
|
||||
{
|
||||
return (*b==0)?0:-1;
|
||||
@@ -834,7 +892,7 @@ wchar_t *wcsndup( const wchar_t *in, int c )
|
||||
return 0;
|
||||
}
|
||||
wcslcpy( res, in, c+1 );
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -847,22 +905,22 @@ long convert_digit( wchar_t d, int base )
|
||||
}
|
||||
else if( (d <= L'z') && (d >= L'a') )
|
||||
{
|
||||
res = d + 10 - L'a';
|
||||
res = d + 10 - L'a';
|
||||
}
|
||||
else if( (d <= L'Z') && (d >= L'A') )
|
||||
{
|
||||
res = d + 10 - L'A';
|
||||
res = d + 10 - L'A';
|
||||
}
|
||||
if( res >= base )
|
||||
{
|
||||
res = -1;
|
||||
}
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifndef HAVE_WCSTOL
|
||||
long wcstol(const wchar_t *nptr,
|
||||
long wcstol(const wchar_t *nptr,
|
||||
wchar_t **endptr,
|
||||
int base)
|
||||
{
|
||||
@@ -885,7 +943,7 @@ long wcstol(const wchar_t *nptr,
|
||||
{
|
||||
errno = EINVAL;
|
||||
}
|
||||
return res;
|
||||
return res;
|
||||
}
|
||||
res = (res*base)+nxt;
|
||||
is_set = 1;
|
||||
@@ -927,25 +985,25 @@ long wcstol(const wchar_t *nptr,
|
||||
size_t
|
||||
wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
{
|
||||
|
||||
|
||||
register wchar_t *d = dst;
|
||||
register const wchar_t *s = src;
|
||||
register size_t n = siz;
|
||||
register size_t n = siz;
|
||||
size_t dlen;
|
||||
|
||||
/* Find the end of dst and adjust bytes left but don't go past end */
|
||||
while (n-- != 0 && *d != '\0')
|
||||
d++;
|
||||
|
||||
|
||||
dlen = d - dst;
|
||||
n = siz - dlen;
|
||||
n = siz - dlen;
|
||||
|
||||
if (n == 0)
|
||||
return(dlen + wcslen(s));
|
||||
|
||||
while (*s != '\0')
|
||||
while (*s != '\0')
|
||||
{
|
||||
if (n != 1)
|
||||
if (n != 1)
|
||||
{
|
||||
*d++ = *s;
|
||||
n--;
|
||||
@@ -985,12 +1043,12 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
register wchar_t *d = dst;
|
||||
register const wchar_t *s = src;
|
||||
register size_t n = siz;
|
||||
|
||||
|
||||
/* Copy as many bytes as will fit */
|
||||
if (n != 0 && --n != 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (n != 0 && --n != 0)
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((*d++ = *s++) == 0)
|
||||
break;
|
||||
}
|
||||
@@ -998,8 +1056,8 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
}
|
||||
|
||||
/* Not enough room in dst, add NUL and traverse rest of src */
|
||||
if (n == 0)
|
||||
{
|
||||
if (n == 0)
|
||||
{
|
||||
if (siz != 0)
|
||||
*d = '\0';
|
||||
/* NUL-terminate dst */
|
||||
@@ -1016,7 +1074,7 @@ wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
|
||||
|
||||
int lrand48_r(struct drand48_data *buffer, long int *result)
|
||||
{
|
||||
*result = rand_r( &buffer->seed );
|
||||
*result = rand_r( &buffer->seed );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1085,10 +1143,10 @@ int killpg( int pgr, int sig )
|
||||
|
||||
#ifndef HAVE_WORKING_GETOPT_LONG
|
||||
|
||||
int getopt_long( int argc,
|
||||
int getopt_long( int argc,
|
||||
char * const argv[],
|
||||
const char *optstring,
|
||||
const struct option *longopts,
|
||||
const struct option *longopts,
|
||||
int *longindex )
|
||||
{
|
||||
return getopt( argc, argv, optstring );
|
||||
@@ -1110,3 +1168,27 @@ char ** backtrace_symbols (void *const *buffer, int size)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYSCONF
|
||||
|
||||
long sysconf(int name)
|
||||
{
|
||||
if( name == _SC_ARG_MAX )
|
||||
{
|
||||
#ifdef ARG_MAX
|
||||
return ARG_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_NAN
|
||||
double nan(char *tagp)
|
||||
{
|
||||
return 0.0/0.0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
88
fallback.h
88
fallback.h
@@ -54,12 +54,21 @@ typedef char tputs_arg_t;
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_WINSIZE
|
||||
struct winsize
|
||||
/**
|
||||
Structure used to get the size of a terminal window
|
||||
*/
|
||||
struct winsize
|
||||
{
|
||||
unsigned short ws_row;
|
||||
/**
|
||||
Number of rows
|
||||
*/
|
||||
unsigned short ws_row;
|
||||
/**
|
||||
Number of columns
|
||||
*/
|
||||
unsigned short ws_col;
|
||||
}
|
||||
;
|
||||
;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -73,6 +82,18 @@ int tputs(const char *str, int affcnt, int (*fish_putc)(tputs_arg_t));
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef TPARM_SOLARIS_KLUDGE
|
||||
|
||||
/**
|
||||
Solaris tparm has a set fixed of paramters in it's curses implementation,
|
||||
work around this here.
|
||||
*/
|
||||
|
||||
#define tparm tparm_solaris_kludge
|
||||
char *tparm_solaris_kludge( char *str, ... );
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FWPRINTF
|
||||
|
||||
/**
|
||||
@@ -172,7 +193,7 @@ wchar_t *wcstok(wchar_t *wcs, const wchar_t *delim, wchar_t **ptr);
|
||||
/**
|
||||
Return the number of columns used by a character. This is a libc
|
||||
function, but the prototype for this function is missing in some libc
|
||||
implementations.
|
||||
implementations.
|
||||
|
||||
Fish has a fallback implementation in case the implementation is
|
||||
missing altogether. In locales without a native wcwidth, Unicode
|
||||
@@ -271,8 +292,8 @@ long convert_digit( wchar_t d, int base );
|
||||
supported.
|
||||
*/
|
||||
long wcstol(const wchar_t *nptr,
|
||||
wchar_t **endptr,
|
||||
int base);
|
||||
wchar_t **endptr,
|
||||
int base);
|
||||
|
||||
#endif
|
||||
#ifndef HAVE_WCSLCAT
|
||||
@@ -299,7 +320,7 @@ size_t wcslcat( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
wcslen(src); if retval >= siz, truncation occurred.
|
||||
|
||||
This is the OpenBSD strlcpy function, modified for wide characters,
|
||||
and renamed to reflect this change.
|
||||
and renamed to reflect this change.
|
||||
*/
|
||||
size_t wcslcpy( wchar_t *dst, const wchar_t *src, size_t siz );
|
||||
|
||||
@@ -325,7 +346,7 @@ struct drand48_data
|
||||
*/
|
||||
unsigned int seed;
|
||||
}
|
||||
;
|
||||
;
|
||||
|
||||
/**
|
||||
Fallback implementation of lrand48_r. Internally uses rand_r, so it is pretty weak.
|
||||
@@ -369,9 +390,9 @@ char * textdomain( const char * domainname );
|
||||
/**
|
||||
Fallback implementation of dcgettext. Just returns the original string.
|
||||
*/
|
||||
char * dcgettext ( const char * domainname,
|
||||
const char * msgid,
|
||||
int category );
|
||||
char * dcgettext ( const char * domainname,
|
||||
const char * msgid,
|
||||
int category );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -388,20 +409,38 @@ extern int _nl_msg_cat_cntr;
|
||||
|
||||
|
||||
#ifndef HAVE_KILLPG
|
||||
/**
|
||||
Send specified signal to specified process group.
|
||||
*/
|
||||
int killpg( int pgr, int sig );
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef HAVE_WORKING_GETOPT_LONG
|
||||
|
||||
struct option
|
||||
/**
|
||||
Struct describing a long getopt option
|
||||
*/
|
||||
struct option
|
||||
{
|
||||
/**
|
||||
Name of option
|
||||
*/
|
||||
const char *name;
|
||||
/**
|
||||
Flag
|
||||
*/
|
||||
int has_arg;
|
||||
/**
|
||||
Flag
|
||||
*/
|
||||
int *flag;
|
||||
int val;
|
||||
/**
|
||||
Return value
|
||||
*/
|
||||
int val;
|
||||
}
|
||||
;
|
||||
;
|
||||
|
||||
#ifndef no_argument
|
||||
#define no_argument 0
|
||||
@@ -415,13 +454,24 @@ struct option
|
||||
#define optional_argument 2
|
||||
#endif
|
||||
|
||||
int getopt_long(int argc,
|
||||
char * const argv[],
|
||||
const char *optstring,
|
||||
const struct option *longopts,
|
||||
int *longindex);
|
||||
int getopt_long(int argc,
|
||||
char * const argv[],
|
||||
const char *optstring,
|
||||
const struct option *longopts,
|
||||
int *longindex);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYSCONF
|
||||
|
||||
#define _SC_ARG_MAX 1
|
||||
long sysconf(int name);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_NAN
|
||||
double nan(char *tagp);
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
188
main.c → fish.c
188
main.c → fish.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright (C) 2005-2006 Axel Liljencrantz
|
||||
Copyright (C) 2005-2008 Axel Liljencrantz
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
@@ -16,7 +16,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
/** \file main.c
|
||||
/** \file fish.c
|
||||
The main loop of <tt>fish</tt>.
|
||||
*/
|
||||
|
||||
@@ -66,140 +66,131 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
/**
|
||||
The string describing the single-character options accepted by the main fish binary
|
||||
*/
|
||||
#define GETOPT_STRING "hilnvc:p:d:"
|
||||
#define GETOPT_STRING "+hilnvc:p:d:"
|
||||
|
||||
/**
|
||||
Parse init files
|
||||
*/
|
||||
static int read_init()
|
||||
{
|
||||
wchar_t cwd[4096];
|
||||
wchar_t *config_dir;
|
||||
wchar_t *config_dir_escaped;
|
||||
void *context;
|
||||
string_buffer_t *eval_buff;
|
||||
|
||||
if( !wgetcwd( cwd, 4096 ) )
|
||||
{
|
||||
wperror( L"wgetcwd" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
eval( L"builtin cd " DATADIR L"/fish 2>/dev/null; and builtin . config.fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin cd " SYSCONFDIR L"/fish 2>/dev/null; and builtin . config.fish 2>/dev/null", 0, TOP );
|
||||
|
||||
eval( L"builtin . " DATADIR "/fish/config.fish 2>/dev/null", 0, TOP );
|
||||
eval( L"builtin . " SYSCONFDIR L"/fish/config.fish 2>/dev/null", 0, TOP );
|
||||
|
||||
/*
|
||||
We need to get the configuration directory before we can source the user configuration file
|
||||
*/
|
||||
context = halloc( 0, 0 );
|
||||
eval_buff = sb_halloc( context );
|
||||
config_dir = path_get_config( context );
|
||||
config_dir_escaped = escape( config_dir, 1 );
|
||||
sb_printf( eval_buff, L"builtin cd %ls 2>/dev/null; and builtin . config.fish 2>/dev/null", config_dir_escaped );
|
||||
eval( (wchar_t *)eval_buff->buff, 0, TOP );
|
||||
|
||||
|
||||
/*
|
||||
If config_dir is null then we have no configuration directory
|
||||
and no custom config to load.
|
||||
*/
|
||||
if( config_dir )
|
||||
{
|
||||
config_dir_escaped = escape( config_dir, 1 );
|
||||
sb_printf( eval_buff, L"builtin . %ls/config.fish 2>/dev/null", config_dir_escaped );
|
||||
eval( (wchar_t *)eval_buff->buff, 0, TOP );
|
||||
free( config_dir_escaped );
|
||||
}
|
||||
|
||||
halloc_free( context );
|
||||
free( config_dir_escaped );
|
||||
|
||||
if( wchdir( cwd ) == -1 )
|
||||
{
|
||||
/*
|
||||
If we can't change back to previos directory, we go to
|
||||
~. Should be a sane default behavior.
|
||||
*/
|
||||
eval( L"builtin cd", 0, TOP );
|
||||
}
|
||||
else
|
||||
{
|
||||
env_set( L"PWD", cwd, ENV_EXPORT );
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Parse the argument list, return the index of the first non-switch
|
||||
arguments.
|
||||
*/
|
||||
static int fish_parse_opt( int argc, char **argv, char **cmd_ptr )
|
||||
{
|
||||
int my_optind;
|
||||
int force_interactive=0;
|
||||
|
||||
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
"command", required_argument, 0, 'c'
|
||||
"command", required_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
{
|
||||
"debug-level", required_argument, 0, 'd'
|
||||
"debug-level", required_argument, 0, 'd'
|
||||
}
|
||||
,
|
||||
{
|
||||
"interactive", no_argument, 0, 'i'
|
||||
"interactive", no_argument, 0, 'i'
|
||||
}
|
||||
,
|
||||
{
|
||||
"login", no_argument, 0, 'l'
|
||||
"login", no_argument, 0, 'l'
|
||||
}
|
||||
,
|
||||
{
|
||||
"no-execute", no_argument, 0, 'n'
|
||||
"no-execute", no_argument, 0, 'n'
|
||||
}
|
||||
,
|
||||
{
|
||||
"profile", required_argument, 0, 'p'
|
||||
"profile", required_argument, 0, 'p'
|
||||
}
|
||||
,
|
||||
{
|
||||
"help", no_argument, 0, 'h'
|
||||
"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
"version", no_argument, 0, 'v'
|
||||
"version", no_argument, 0, 'v'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
int opt_index = 0;
|
||||
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
argv,
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
|
||||
switch( opt )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 'c':
|
||||
|
||||
case 'c':
|
||||
{
|
||||
*cmd_ptr = optarg;
|
||||
*cmd_ptr = optarg;
|
||||
is_interactive_session = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 'd':
|
||||
|
||||
case 'd':
|
||||
{
|
||||
char *end;
|
||||
int tmp;
|
||||
|
||||
errno = 0;
|
||||
tmp = strtol(optarg, &end, 10);
|
||||
|
||||
|
||||
if( tmp >= 0 && tmp <=10 && !*end && !errno )
|
||||
{
|
||||
debug_level=tmp;
|
||||
@@ -211,61 +202,69 @@ static int fish_parse_opt( int argc, char **argv, char **cmd_ptr )
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'h':
|
||||
{
|
||||
*cmd_ptr = "__fish_print_help fish";
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'i':
|
||||
{
|
||||
force_interactive = 1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'l':
|
||||
{
|
||||
is_login=1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'n':
|
||||
{
|
||||
no_exec=1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'p':
|
||||
{
|
||||
profile = optarg;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'v':
|
||||
{
|
||||
fwprintf( stderr,
|
||||
_(L"%s, version %s\n"),
|
||||
fwprintf( stderr,
|
||||
_(L"%s, version %s\n"),
|
||||
PACKAGE_NAME,
|
||||
PACKAGE_VERSION );
|
||||
exit( 0 );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
|
||||
case '?':
|
||||
{
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
my_optind = optind;
|
||||
|
||||
|
||||
is_login |= (strcmp( argv[0], "-fish") == 0);
|
||||
|
||||
|
||||
/*
|
||||
We are an interactive session if we have not been given an
|
||||
explicit command to execute, _and_ stdin is a tty.
|
||||
*/
|
||||
is_interactive_session &= (*cmd_ptr == 0);
|
||||
is_interactive_session &= (my_optind == argc);
|
||||
is_interactive_session &= isatty(STDIN_FILENO);
|
||||
is_interactive_session &= isatty(STDIN_FILENO);
|
||||
|
||||
/*
|
||||
We are also an interactive session if we have are forced-
|
||||
*/
|
||||
is_interactive_session |= force_interactive;
|
||||
|
||||
return my_optind;
|
||||
@@ -283,7 +282,7 @@ int main( int argc, char **argv )
|
||||
char *cmd=0;
|
||||
int my_optind=0;
|
||||
|
||||
halloc_util_init();
|
||||
halloc_util_init();
|
||||
|
||||
wsetlocale( LC_ALL, L"" );
|
||||
is_interactive_session=1;
|
||||
@@ -300,10 +299,9 @@ int main( int argc, char **argv )
|
||||
debug( 1, _(L"Can not use the no-execute mode when running an interactive session") );
|
||||
no_exec = 0;
|
||||
}
|
||||
|
||||
|
||||
proc_init();
|
||||
event_init();
|
||||
proc_init();
|
||||
event_init();
|
||||
wutil_init();
|
||||
parser_init();
|
||||
builtin_init();
|
||||
@@ -325,28 +323,28 @@ int main( int argc, char **argv )
|
||||
{
|
||||
if( my_optind == argc )
|
||||
{
|
||||
res = reader_read( 0 );
|
||||
res = reader_read( STDIN_FILENO, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
char **ptr;
|
||||
char *file = *(argv+1);
|
||||
int i;
|
||||
char **ptr;
|
||||
char *file = *(argv+(my_optind++));
|
||||
int i;
|
||||
string_buffer_t sb;
|
||||
int fd;
|
||||
wchar_t *rel_filename, *abs_filename;
|
||||
|
||||
|
||||
if( ( fd = open(file, O_RDONLY) ) == -1 )
|
||||
{
|
||||
wperror( L"open" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
if( *(argv+2))
|
||||
if( *(argv+my_optind))
|
||||
{
|
||||
sb_init( &sb );
|
||||
|
||||
for( i=1,ptr = argv+2; *ptr; i++, ptr++ )
|
||||
|
||||
for( i=1,ptr = argv+my_optind; *ptr; i++, ptr++ )
|
||||
{
|
||||
if( i != 1 )
|
||||
sb_append( &sb, ARRAY_SEP_STR );
|
||||
@@ -354,27 +352,31 @@ int main( int argc, char **argv )
|
||||
sb_append( &sb, val );
|
||||
free( val );
|
||||
}
|
||||
|
||||
|
||||
env_set( L"argv", (wchar_t *)sb.buff, 0 );
|
||||
sb_destroy( &sb );
|
||||
}
|
||||
|
||||
rel_filename = str2wcs( file );
|
||||
abs_filename = wrealpath( rel_filename, 0 );
|
||||
|
||||
if( !abs_filename )
|
||||
{
|
||||
abs_filename = wcsdup(rel_filename);
|
||||
}
|
||||
|
||||
reader_push_current_filename( intern( abs_filename ) );
|
||||
free( rel_filename );
|
||||
free( abs_filename );
|
||||
|
||||
res = reader_read( fd );
|
||||
res = reader_read( fd, 0 );
|
||||
|
||||
if( res )
|
||||
{
|
||||
debug( 1,
|
||||
_(L"Error while reading file %ls\n"),
|
||||
reader_current_filename()?reader_current_filename(): _(L"Standard input") );
|
||||
}
|
||||
debug( 1,
|
||||
_(L"Error while reading file %ls\n"),
|
||||
reader_current_filename()?reader_current_filename(): _(L"Standard input") );
|
||||
}
|
||||
reader_pop_current_filename();
|
||||
}
|
||||
}
|
||||
@@ -397,5 +399,5 @@ int main( int argc, char **argv )
|
||||
|
||||
intern_free_all();
|
||||
|
||||
return res?STATUS_UNKNOWN_COMMAND:proc_get_last_status();
|
||||
return res?STATUS_UNKNOWN_COMMAND:proc_get_last_status();
|
||||
}
|
||||
33
fish.spec.in
33
fish.spec.in
@@ -11,7 +11,7 @@ URL: http://www.fishshell.org
|
||||
Source0: http://www.fishshell.org/files/%{version}/%{name}-%{version}.tar.bz2
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: ncurses-devel gettext groff
|
||||
BuildRequires: ncurses-devel gettext groff
|
||||
|
||||
|
||||
# Locate correct build time-dependencies for providing X headers
|
||||
@@ -50,10 +50,10 @@ BuildRequires: %{xinclude}/X11/Intrinsic.h, %{xinclude}/X11/Xatom.h
|
||||
%endif
|
||||
|
||||
|
||||
%description
|
||||
%description
|
||||
|
||||
fish is a shell geared towards interactive use. Its features are
|
||||
focused on user friendliness and discoverability. The language syntax
|
||||
fish is a shell geared towards interactive use. Its features are
|
||||
focused on user friendliness and discoverability. The language syntax
|
||||
is simple but incompatible with other shell languages.
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ make %{?_smp_mflags}
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make install DESTDIR="$RPM_BUILD_ROOT"
|
||||
make install DESTDIR="$RPM_BUILD_ROOT"
|
||||
|
||||
# Find translation files
|
||||
%find_lang %{name}.\*
|
||||
@@ -116,31 +116,29 @@ fi
|
||||
|
||||
# man files
|
||||
%_mandir/man1/fish.1*
|
||||
%_mandir/man1/xsel.1x*
|
||||
%_mandir/man1/fish_pager.1*
|
||||
%_mandir/man1/fish_indent.1*
|
||||
%_mandir/man1/fishd.1*
|
||||
%_mandir/man1/mimedb.1*
|
||||
%_mandir/man1/set_color.1*
|
||||
%_mandir/man1/count.1*
|
||||
%_mandir/man1/fishd.1*
|
||||
%_mandir/man1/fish_pager.1*
|
||||
%_mandir/man1/xsel.1x*
|
||||
|
||||
# The program binaries
|
||||
%attr(0755,root,root) %_bindir/fish
|
||||
%attr(0755,root,root) %_bindir/fishd
|
||||
%attr(0755,root,root) %_bindir/fish_indent
|
||||
%attr(0755,root,root) %_bindir/fish_pager
|
||||
%attr(0755,root,root) %_bindir/xsel
|
||||
%attr(0755,root,root) %_bindir/set_color
|
||||
%attr(0755,root,root) %_bindir/fishd
|
||||
%attr(0755,root,root) %_bindir/mimedb
|
||||
%attr(0755,root,root) %_bindir/count
|
||||
%attr(0755,root,root) %_bindir/set_color
|
||||
%attr(0755,root,root) %_bindir/xsel
|
||||
|
||||
# Configuration files
|
||||
%config %_sysconfdir/fish/config.fish
|
||||
%config %_sysconfdir/fish/fish_inputrc
|
||||
%dir %_sysconfdir/fish
|
||||
|
||||
# Non-configuration initialization files
|
||||
%dir %_datadir/fish
|
||||
%_datadir/fish/config.fish
|
||||
%_datadir/fish/config_interactive.fish
|
||||
|
||||
# Program specific tab-completions
|
||||
%dir %_datadir/fish/completions
|
||||
@@ -156,9 +154,10 @@ fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
%changelog
|
||||
* Sat Apr 21 2007 Axel Liljencrantz<axel@liljencrantz.se> 1.23.0-0
|
||||
- Add fish_indent command
|
||||
|
||||
* Thu Feb 8 2007 Axel Liljencrantz<axel@liljencrantz.se> 1.22.3-0
|
||||
- Tell rpm about the help pages in %_datadir/fish/man/
|
||||
|
||||
|
||||
408
fish_indent.c
Normal file
408
fish_indent.c
Normal file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
Copyright (C) 2005-2008 Axel Liljencrantz
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
/** \file fish_indent.c
|
||||
The fish_indent proegram.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <wchar.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
#include <locale.h>
|
||||
|
||||
#include "fallback.h"
|
||||
#include "util.h"
|
||||
#include "common.h"
|
||||
#include "wutil.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
#include "tokenizer.h"
|
||||
#include "print_help.h"
|
||||
#include "parser_keywords.h"
|
||||
|
||||
/**
|
||||
The string describing the single-character options accepted by the main fish binary
|
||||
*/
|
||||
#define GETOPT_STRING "hvi"
|
||||
|
||||
/**
|
||||
Read the entire contents of a file into the specified string_Buffer_t
|
||||
*/
|
||||
static void read_file( FILE *f, string_buffer_t *b )
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
errno=0;
|
||||
wint_t c = fgetwc( f );
|
||||
if( c == WEOF )
|
||||
{
|
||||
if( errno )
|
||||
{
|
||||
wperror(L"fgetwc");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
sb_append_char( b, c );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Insert the specified number of tabe into the output buffer
|
||||
*/
|
||||
static void insert_tabs( string_buffer_t *out, int indent )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i=0; i<indent; i++ )
|
||||
{
|
||||
sb_append( out, L"\t" );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Indent the specified input
|
||||
*/
|
||||
static int indent( string_buffer_t *out, wchar_t *in, int flags )
|
||||
{
|
||||
tokenizer tok;
|
||||
int res=0;
|
||||
int is_command = 1;
|
||||
int indent = 0;
|
||||
int do_indent = 1;
|
||||
int prev_type = 0;
|
||||
int prev_prev_type = 0;
|
||||
|
||||
tok_init( &tok, in, TOK_SHOW_COMMENTS );
|
||||
|
||||
for( ; tok_has_next( &tok ); tok_next( &tok ) )
|
||||
{
|
||||
int type = tok_last_type( &tok );
|
||||
wchar_t *last = tok_last( &tok );
|
||||
|
||||
switch( type )
|
||||
{
|
||||
case TOK_STRING:
|
||||
{
|
||||
if( is_command )
|
||||
{
|
||||
int next_indent = indent;
|
||||
is_command = 0;
|
||||
|
||||
wchar_t *unesc = unescape( last, UNESCAPE_SPECIAL );
|
||||
|
||||
if( parser_keywords_is_block( unesc ) )
|
||||
{
|
||||
next_indent++;
|
||||
}
|
||||
else if( wcscmp( unesc, L"else" ) == 0 )
|
||||
{
|
||||
indent--;
|
||||
}
|
||||
/* case should have the same indent level as switch*/
|
||||
else if( wcscmp( unesc, L"case" ) == 0 )
|
||||
{
|
||||
indent--;
|
||||
}
|
||||
else if( wcscmp( unesc, L"end" ) == 0 )
|
||||
{
|
||||
indent--;
|
||||
next_indent--;
|
||||
}
|
||||
|
||||
|
||||
if( do_indent && flags && prev_type != TOK_PIPE )
|
||||
{
|
||||
insert_tabs( out, indent );
|
||||
}
|
||||
|
||||
sb_printf( out, L"%ls", last );
|
||||
|
||||
indent = next_indent;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( prev_type != TOK_REDIRECT_FD )
|
||||
sb_append( out, L" " );
|
||||
sb_append( out, last );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_END:
|
||||
{
|
||||
if( prev_type != TOK_END || prev_prev_type != TOK_END )
|
||||
sb_append( out, L"\n" );
|
||||
do_indent = 1;
|
||||
is_command = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_PIPE:
|
||||
{
|
||||
sb_append( out, L" " );
|
||||
if ( last[0] == '2' && !last[1] ) {
|
||||
sb_append( out, L"^" );
|
||||
} else if ( last[0] != '1' || last[1] ) {
|
||||
sb_append( out, last, L">" );
|
||||
}
|
||||
sb_append( out, L"| " );
|
||||
is_command = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_REDIRECT_OUT:
|
||||
{
|
||||
sb_append( out, L" " );
|
||||
if ( wcscmp( last, L"2" ) == 0 ) {
|
||||
sb_append( out, L"^" );
|
||||
} else {
|
||||
if ( wcscmp( last, L"1" ) != 0 )
|
||||
sb_append( out, last );
|
||||
sb_append( out, L">" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_REDIRECT_APPEND:
|
||||
{
|
||||
sb_append( out, L" " );
|
||||
if ( wcscmp( last, L"2" ) == 0 ) {
|
||||
sb_append( out, L"^^" );
|
||||
} else {
|
||||
if ( wcscmp( last, L"1" ) != 0 )
|
||||
sb_append( out, last );
|
||||
sb_append( out, L">>" );
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_REDIRECT_IN:
|
||||
{
|
||||
sb_append( out, L" " );
|
||||
if ( wcscmp( last, L"0" ) != 0 )
|
||||
sb_append( out, last );
|
||||
sb_append( out, L"<" );
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_REDIRECT_FD:
|
||||
{
|
||||
sb_append( out, L" " );
|
||||
if ( wcscmp( last, L"1" ) != 0 )
|
||||
sb_append( out, last );
|
||||
sb_append( out, L">&" );
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_BACKGROUND:
|
||||
{
|
||||
sb_append( out, L"&\n" );
|
||||
do_indent = 1;
|
||||
is_command = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
case TOK_COMMENT:
|
||||
{
|
||||
if( do_indent && flags)
|
||||
{
|
||||
insert_tabs( out, indent );
|
||||
}
|
||||
|
||||
sb_printf( out, L"%ls", last );
|
||||
do_indent = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
debug( 0, L"Unknown token '%ls'", last );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
prev_prev_type = prev_type;
|
||||
prev_type = type;
|
||||
|
||||
}
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove any prefix and suffix newlines from the specified
|
||||
string. Does not allocete a new string, edits the string in place
|
||||
and returns a pointer somewhere into the string.
|
||||
*/
|
||||
static wchar_t *trim( wchar_t *in )
|
||||
{
|
||||
wchar_t *end;
|
||||
|
||||
while( *in == L'\n' )
|
||||
{
|
||||
in++;
|
||||
}
|
||||
|
||||
end = in + wcslen(in);
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if( end < in+2 )
|
||||
break;
|
||||
|
||||
end--;
|
||||
|
||||
if( (*end == L'\n' ) && ( *(end-1) == L'\n' ) )
|
||||
*end=0;
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
The main mathod. Run the program.
|
||||
*/
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
string_buffer_t sb_in;
|
||||
string_buffer_t sb_out;
|
||||
|
||||
int do_indent=1;
|
||||
|
||||
wsetlocale( LC_ALL, L"" );
|
||||
program_name=L"fish_indent";
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
"no-indent", no_argument, 0, 'i'
|
||||
}
|
||||
,
|
||||
{
|
||||
"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
"version", no_argument, 0, 'v'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
int opt_index = 0;
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
switch( opt )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
case 'h':
|
||||
{
|
||||
print_help( "fish_indent", 1 );
|
||||
exit( 0 );
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v':
|
||||
{
|
||||
fwprintf( stderr,
|
||||
_(L"%ls, version %s\n"),
|
||||
program_name,
|
||||
PACKAGE_VERSION );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
case 'i':
|
||||
{
|
||||
do_indent = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case '?':
|
||||
{
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
halloc_util_init();
|
||||
|
||||
sb_init( &sb_in );
|
||||
sb_init( &sb_out );
|
||||
|
||||
read_file( stdin, &sb_in );
|
||||
|
||||
wutil_init();
|
||||
|
||||
if( !indent( &sb_out, (wchar_t *)sb_in.buff, do_indent ) )
|
||||
{
|
||||
fwprintf( stdout, L"%ls", trim( (wchar_t *)sb_out.buff) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Indenting failed - print original input
|
||||
*/
|
||||
fwprintf( stdout, L"%ls", (wchar_t *)sb_in.buff );
|
||||
}
|
||||
|
||||
|
||||
wutil_destroy();
|
||||
|
||||
halloc_util_destroy();
|
||||
|
||||
return 0;
|
||||
}
|
||||
425
fish_pager.c
425
fish_pager.c
@@ -61,7 +61,7 @@
|
||||
#include "halloc_util.h"
|
||||
#include "print_help.h"
|
||||
|
||||
enum
|
||||
enum
|
||||
{
|
||||
LINE_UP = R_NULL+1,
|
||||
LINE_DOWN,
|
||||
@@ -146,7 +146,7 @@ static buffer_t *pager_buffer;
|
||||
The environment variables used to specify the color of different
|
||||
tokens.
|
||||
*/
|
||||
static wchar_t *hightlight_var[] =
|
||||
static wchar_t *hightlight_var[] =
|
||||
{
|
||||
L"fish_pager_color_prefix",
|
||||
L"fish_pager_color_completion",
|
||||
@@ -167,7 +167,7 @@ static FILE *out_file;
|
||||
/**
|
||||
Data structure describing one or a group of related completions
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
The list of all completin strings this entry applies to
|
||||
@@ -180,11 +180,11 @@ typedef struct
|
||||
/**
|
||||
On-screen width of the completion string
|
||||
*/
|
||||
int comp_width;
|
||||
int comp_width;
|
||||
/**
|
||||
On-screen width of the description information
|
||||
*/
|
||||
int desc_width;
|
||||
int desc_width;
|
||||
/**
|
||||
Preffered total width
|
||||
*/
|
||||
@@ -208,20 +208,20 @@ static int get_color( int highlight )
|
||||
return FISH_COLOR_NORMAL;
|
||||
if( highlight >= (4) )
|
||||
return FISH_COLOR_NORMAL;
|
||||
|
||||
|
||||
val = wgetenv( hightlight_var[highlight]);
|
||||
|
||||
if( !val )
|
||||
{
|
||||
val = env_universal_get( hightlight_var[highlight]);
|
||||
}
|
||||
|
||||
|
||||
if( !val )
|
||||
{
|
||||
return FISH_COLOR_NORMAL;
|
||||
}
|
||||
|
||||
return output_color_code( val );
|
||||
|
||||
return output_color_code( val );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -236,11 +236,11 @@ static void recalc_width( array_list_t *l, const wchar_t *prefix )
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -251,14 +251,14 @@ static int try_sequence( char *seq )
|
||||
{
|
||||
int j, k;
|
||||
wint_t c=0;
|
||||
|
||||
for( j=0;
|
||||
seq[j] != '\0' && seq[j] == (c=input_common_readch( j>0 ));
|
||||
j++ )
|
||||
|
||||
for( j=0;
|
||||
seq[j] != '\0' && seq[j] == (c=input_common_readch( j>0 ));
|
||||
j++ )
|
||||
;
|
||||
|
||||
if( seq[j] == '\0' )
|
||||
{
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
@@ -281,19 +281,19 @@ static wint_t readch()
|
||||
wint_t bnd;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
struct mapping m[]=
|
||||
{
|
||||
{
|
||||
"\e[A", LINE_UP
|
||||
{
|
||||
"\x1b[A", LINE_UP
|
||||
}
|
||||
,
|
||||
{
|
||||
key_up, LINE_UP
|
||||
}
|
||||
,
|
||||
{
|
||||
"\e[B", LINE_DOWN
|
||||
{
|
||||
"\x1b[B", LINE_DOWN
|
||||
}
|
||||
,
|
||||
{
|
||||
@@ -319,13 +319,18 @@ static wint_t readch()
|
||||
{
|
||||
0, 0
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
;
|
||||
int i;
|
||||
|
||||
for( i=0; m[i].seq; i++ )
|
||||
|
||||
for( i=0; m[i].bnd; i++ )
|
||||
{
|
||||
if( !m[i].seq )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( try_sequence(m[i].seq ) )
|
||||
return m[i].bnd;
|
||||
}
|
||||
@@ -346,7 +351,7 @@ static int pager_buffered_writer( char c)
|
||||
*/
|
||||
static void pager_flush()
|
||||
{
|
||||
write( 1, pager_buffer->buff, pager_buffer->used );
|
||||
write_loop( 1, pager_buffer->buff, pager_buffer->used );
|
||||
pager_buffer->used = 0;
|
||||
}
|
||||
|
||||
@@ -364,7 +369,7 @@ static int print_max( const wchar_t *str, int max, int has_more )
|
||||
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]) )
|
||||
@@ -373,7 +378,7 @@ static int print_max( const wchar_t *str, int max, int has_more )
|
||||
written += wcwidth(ellipsis_char );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
writech( str[i] );
|
||||
written+= wcwidth( str[i] );
|
||||
}
|
||||
@@ -388,7 +393,7 @@ 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 )
|
||||
{
|
||||
/*
|
||||
@@ -406,17 +411,17 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width )
|
||||
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 );
|
||||
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 );
|
||||
@@ -438,7 +443,7 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width )
|
||||
}
|
||||
written += print_max( L"(", 1, 0 );
|
||||
set_color( get_color( HIGHLIGHT_PAGER_DESCRIPTION ),
|
||||
FISH_COLOR_IGNORE );
|
||||
FISH_COLOR_IGNORE );
|
||||
written += print_max( c->desc, desc_width, 0 );
|
||||
written += print_max( L")", 1, 0 );
|
||||
}
|
||||
@@ -450,7 +455,7 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width )
|
||||
writech( L' ');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -467,12 +472,12 @@ static void completion_print_item( const wchar_t *prefix, comp_t *c, int width )
|
||||
*/
|
||||
|
||||
static void completion_print( int cols,
|
||||
int *width,
|
||||
int row_start,
|
||||
int row_stop,
|
||||
wchar_t *prefix,
|
||||
int is_quoted,
|
||||
array_list_t *l)
|
||||
int *width,
|
||||
int row_start,
|
||||
int row_stop,
|
||||
wchar_t *prefix,
|
||||
int is_quoted,
|
||||
array_list_t *l)
|
||||
{
|
||||
|
||||
int rows = (al_get_count( l )-1)/cols+1;
|
||||
@@ -485,14 +490,14 @@ static void completion_print( int cols,
|
||||
comp_t *el;
|
||||
|
||||
int is_last = (j==(cols-1));
|
||||
|
||||
|
||||
if( al_get_count( l ) <= j*rows + i )
|
||||
continue;
|
||||
|
||||
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" " );
|
||||
}
|
||||
@@ -520,9 +525,9 @@ static void completion_print( int cols,
|
||||
*/
|
||||
|
||||
static int completion_try_print( int cols,
|
||||
wchar_t *prefix,
|
||||
int is_quoted,
|
||||
array_list_t *l )
|
||||
wchar_t *prefix,
|
||||
int is_quoted,
|
||||
array_list_t *l )
|
||||
{
|
||||
/*
|
||||
The calculated preferred width of each column
|
||||
@@ -540,24 +545,24 @@ static int completion_try_print( int cols,
|
||||
Set to one if the list should be printed at this width
|
||||
*/
|
||||
int print=0;
|
||||
|
||||
|
||||
int i, j;
|
||||
|
||||
|
||||
int rows = (al_get_count( l )-1)/cols+1;
|
||||
|
||||
|
||||
int pref_tot_width=0;
|
||||
int min_tot_width = 0;
|
||||
int res=PAGER_RETRY;
|
||||
/*
|
||||
Skip completions on tiny terminals
|
||||
*/
|
||||
|
||||
|
||||
if( termsize.ws_col < PAGER_MIN_WIDTH )
|
||||
return PAGER_DONE;
|
||||
|
||||
|
||||
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++ )
|
||||
{
|
||||
@@ -571,16 +576,16 @@ static int completion_try_print( int cols,
|
||||
c = (comp_t *)al_get( l, j*rows + i );
|
||||
pref = c->pref_width;
|
||||
min = c->min_width;
|
||||
|
||||
|
||||
if( j != cols-1 )
|
||||
{
|
||||
pref += 2;
|
||||
min += 2;
|
||||
}
|
||||
min_width[j] = maxi( min_width[j],
|
||||
min );
|
||||
min );
|
||||
pref_width[j] = maxi( pref_width[j],
|
||||
pref );
|
||||
pref );
|
||||
}
|
||||
min_tot_width += min_width[j];
|
||||
pref_tot_width += pref_width[j];
|
||||
@@ -614,8 +619,8 @@ static int completion_try_print( int cols,
|
||||
pref_tot_width-termsize.ws_col );
|
||||
*/
|
||||
if( min_tot_width < termsize.ws_col &&
|
||||
( ( (rows < termsize.ws_row) && (next_rows >= termsize.ws_row ) ) ||
|
||||
( pref_tot_width-termsize.ws_col< 4 && cols < 3 ) ) )
|
||||
( ( (rows < termsize.ws_row) && (next_rows >= termsize.ws_row ) ) ||
|
||||
( pref_tot_width-termsize.ws_col< 4 && cols < 3 ) ) )
|
||||
{
|
||||
/*
|
||||
Terminal almost wide enough, or squeezing makes the
|
||||
@@ -627,7 +632,7 @@ static int completion_try_print( int cols,
|
||||
be helped, but it is not uncommon for the completions to
|
||||
_almost_ fit on one screen. In those cases, it is almost
|
||||
always desirable to 'squeeze' the completions into a
|
||||
single page.
|
||||
single page.
|
||||
|
||||
If we are using N columns and can get everything to
|
||||
fit using squeezing, but everything would also fit
|
||||
@@ -663,7 +668,7 @@ static int completion_try_print( int cols,
|
||||
is_ca_mode = 0;
|
||||
writembs(exit_ca_mode);
|
||||
}
|
||||
|
||||
|
||||
completion_print( cols, width, 0, rows, prefix, is_quoted, l);
|
||||
pager_flush();
|
||||
}
|
||||
@@ -672,16 +677,25 @@ static int completion_try_print( int cols,
|
||||
int npos, pos = 0;
|
||||
int do_loop = 1;
|
||||
|
||||
is_ca_mode=1;
|
||||
writembs(enter_ca_mode);
|
||||
/*
|
||||
Enter ca_mode, which means that the terminal
|
||||
content will be restored to the current
|
||||
state on exit.
|
||||
*/
|
||||
if( enter_ca_mode && exit_ca_mode )
|
||||
{
|
||||
is_ca_mode=1;
|
||||
writembs(enter_ca_mode);
|
||||
}
|
||||
|
||||
|
||||
completion_print( cols,
|
||||
width,
|
||||
0,
|
||||
termsize.ws_row-1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l);
|
||||
width,
|
||||
0,
|
||||
termsize.ws_row-1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l);
|
||||
/*
|
||||
List does not fit on screen. Print one screenfull and
|
||||
leave a scrollable interface
|
||||
@@ -690,15 +704,18 @@ static int completion_try_print( int cols,
|
||||
{
|
||||
string_buffer_t msg;
|
||||
sb_init( &msg );
|
||||
|
||||
|
||||
set_color( FISH_COLOR_BLACK,
|
||||
get_color(HIGHLIGHT_PAGER_PROGRESS) );
|
||||
get_color(HIGHLIGHT_PAGER_PROGRESS) );
|
||||
sb_printf( &msg,
|
||||
_(L" %d to %d of %d \r"),
|
||||
pos,
|
||||
pos+termsize.ws_row-1,
|
||||
rows );
|
||||
|
||||
_(L" %d to %d of %d"),
|
||||
pos,
|
||||
pos+termsize.ws_row-1,
|
||||
rows );
|
||||
|
||||
sb_printf( &msg,
|
||||
L" \r" );
|
||||
|
||||
writestr((wchar_t *)msg.buff);
|
||||
sb_destroy( &msg );
|
||||
set_color( FISH_COLOR_NORMAL, FISH_COLOR_NORMAL );
|
||||
@@ -715,14 +732,14 @@ static int completion_try_print( int cols,
|
||||
writembs(tparm( cursor_address, 0, 0));
|
||||
writembs(scroll_reverse);
|
||||
completion_print( cols,
|
||||
width,
|
||||
pos,
|
||||
pos+1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l );
|
||||
width,
|
||||
pos,
|
||||
pos+1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l );
|
||||
writembs( tparm( cursor_address,
|
||||
termsize.ws_row-1, 0) );
|
||||
termsize.ws_row-1, 0) );
|
||||
writembs(clr_eol );
|
||||
|
||||
}
|
||||
@@ -736,12 +753,12 @@ static int completion_try_print( int cols,
|
||||
{
|
||||
pos++;
|
||||
completion_print( cols,
|
||||
width,
|
||||
pos+termsize.ws_row-2,
|
||||
pos+termsize.ws_row-1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l );
|
||||
width,
|
||||
pos+termsize.ws_row-2,
|
||||
pos+termsize.ws_row-1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l );
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -750,17 +767,17 @@ static int completion_try_print( int cols,
|
||||
{
|
||||
|
||||
npos = mini( rows - termsize.ws_row+1,
|
||||
pos + termsize.ws_row-1 );
|
||||
pos + termsize.ws_row-1 );
|
||||
if( npos != pos )
|
||||
{
|
||||
pos = npos;
|
||||
completion_print( cols,
|
||||
width,
|
||||
pos,
|
||||
pos+termsize.ws_row-1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l );
|
||||
width,
|
||||
pos,
|
||||
pos+termsize.ws_row-1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -774,18 +791,18 @@ static int completion_try_print( int cols,
|
||||
case PAGE_UP:
|
||||
{
|
||||
npos = maxi( 0,
|
||||
pos - termsize.ws_row+1 );
|
||||
pos - termsize.ws_row+1 );
|
||||
|
||||
if( npos != pos )
|
||||
{
|
||||
pos = npos;
|
||||
completion_print( cols,
|
||||
width,
|
||||
pos,
|
||||
pos+termsize.ws_row-1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l );
|
||||
width,
|
||||
pos,
|
||||
pos+termsize.ws_row-1,
|
||||
prefix,
|
||||
is_quoted,
|
||||
l );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -800,15 +817,15 @@ static int completion_try_print( int cols,
|
||||
do_loop=0;
|
||||
res=PAGER_RESIZE;
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
sb_append_char( &out_buff, c );
|
||||
do_loop = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
writembs(clr_eol);
|
||||
@@ -830,31 +847,31 @@ static void mangle_descriptions( array_list_t *l )
|
||||
wchar_t *next = (wchar_t *)al_get(l, i);
|
||||
wchar_t *in, *out;
|
||||
skip=1;
|
||||
|
||||
|
||||
while( *next != COMPLETE_SEP && *next )
|
||||
next++;
|
||||
|
||||
|
||||
if( !*next )
|
||||
continue;
|
||||
|
||||
|
||||
in=out=(next+1);
|
||||
|
||||
|
||||
while( *in != 0 )
|
||||
{
|
||||
if( *in == L' ' || *in==L'\t' || *in<32 )
|
||||
{
|
||||
if( !skip )
|
||||
*out++=L' ';
|
||||
skip=1;
|
||||
skip=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
*out++ = *in;
|
||||
*out++ = *in;
|
||||
skip=0;
|
||||
}
|
||||
in++;
|
||||
}
|
||||
*out=0;
|
||||
*out=0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -866,7 +883,7 @@ static void join_completions( array_list_t *l )
|
||||
long i;
|
||||
int 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++ )
|
||||
@@ -874,7 +891,7 @@ static void join_completions( array_list_t *l )
|
||||
wchar_t *item = (wchar_t *)al_get( l, i );
|
||||
wchar_t *desc = wcschr( item, COMPLETE_SEP );
|
||||
long prev_idx;
|
||||
|
||||
|
||||
if( !desc )
|
||||
continue;
|
||||
desc++;
|
||||
@@ -888,11 +905,11 @@ static void join_completions( array_list_t *l )
|
||||
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 );
|
||||
@@ -904,23 +921,23 @@ static void join_completions( array_list_t *l )
|
||||
free( (void *)al_get( l, i ) );
|
||||
al_set( l, i, 0 );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
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 );
|
||||
al_truncate( l, out );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -929,23 +946,23 @@ static void join_completions( array_list_t *l )
|
||||
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 );
|
||||
|
||||
wchar_t * str = escape( start, ESCAPE_ALL | ESCAPE_NO_QUOTED );
|
||||
|
||||
comp->comp_width += my_wcswidth( str );
|
||||
halloc_register( global_context, str );
|
||||
al_push( comp->comp, str );
|
||||
@@ -956,22 +973,22 @@ static void mangle_completions( array_list_t *l, const wchar_t *prefix )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
@@ -1008,11 +1025,11 @@ static void init( int mangle_descriptors, int out )
|
||||
struct sigaction act;
|
||||
|
||||
static struct termios pager_modes;
|
||||
|
||||
char *term;
|
||||
|
||||
if( mangle_descriptors )
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
Make fd 1 output to screen, and use some other fd for writing
|
||||
the resulting output back to the caller
|
||||
@@ -1025,13 +1042,13 @@ static void init( int mangle_descriptors, int out )
|
||||
if( (in = open( ttyname(2), O_RDWR )) != -1 )
|
||||
{
|
||||
if( dup2( 2, 1 ) == -1 )
|
||||
{
|
||||
{
|
||||
debug( 0, _(L"Could not set up output file descriptors for pager") );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
|
||||
if( dup2( in, 0 ) == -1 )
|
||||
{
|
||||
{
|
||||
debug( 0, _(L"Could not set up input file descriptors for pager") );
|
||||
exit( 1 );
|
||||
}
|
||||
@@ -1042,13 +1059,13 @@ static void init( int mangle_descriptors, int out )
|
||||
exit( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( !(out_file = fdopen( out, "w" )) )
|
||||
{
|
||||
debug( 0, _(L"Could not initialize result pipe" ) );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Init the stringbuffer used to keep any output in
|
||||
@@ -1071,27 +1088,28 @@ static void init( int mangle_descriptors, int out )
|
||||
wperror( L"sigaction" );
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
handle_winch( 0 ); /* Set handler for window change events */
|
||||
|
||||
tcgetattr(0,&pager_modes); /* get the current terminal modes */
|
||||
memcpy( &saved_modes,
|
||||
&pager_modes,
|
||||
sizeof(saved_modes)); /* save a copy so we can reset the terminal later */
|
||||
&pager_modes,
|
||||
sizeof(saved_modes)); /* save a copy so we can reset the terminal later */
|
||||
|
||||
pager_modes.c_lflag &= ~ICANON; /* turn off canonical mode */
|
||||
pager_modes.c_lflag &= ~ECHO; /* turn off echo mode */
|
||||
pager_modes.c_cc[VMIN]=1;
|
||||
pager_modes.c_cc[VTIME]=0;
|
||||
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");
|
||||
exit(1);
|
||||
}
|
||||
if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */
|
||||
{
|
||||
wperror(L"tcsetattr");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
if( setupterm( 0, STDOUT_FILENO, 0) == ERR )
|
||||
{
|
||||
@@ -1099,6 +1117,14 @@ static void init( int mangle_descriptors, int out )
|
||||
exit(1);
|
||||
}
|
||||
|
||||
term = getenv("TERM");
|
||||
if( term )
|
||||
{
|
||||
wchar_t *wterm = str2wcs(term);
|
||||
output_set_term( wterm );
|
||||
free( wterm );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1111,9 +1137,9 @@ static void destroy()
|
||||
wutil_destroy();
|
||||
if( del_curterm( cur_term ) == ERR )
|
||||
{
|
||||
debug( 0, _(L"Error while closing terminfo") );
|
||||
debug( 0, _(L"Error while closing terminfo") );
|
||||
}
|
||||
|
||||
|
||||
sb_destroy( &out_buff );
|
||||
fclose( out_file );
|
||||
}
|
||||
@@ -1137,8 +1163,8 @@ static void read_array( FILE* file, array_list_t *comp )
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
c = getc( file );
|
||||
if( c == EOF )
|
||||
c = getc( file );
|
||||
if( c == EOF )
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -1149,7 +1175,7 @@ static void read_array( FILE* file, array_list_t *comp )
|
||||
}
|
||||
|
||||
cc=c;
|
||||
|
||||
|
||||
b_append( &buffer, &cc, 1 );
|
||||
}
|
||||
|
||||
@@ -1157,12 +1183,15 @@ static void read_array( FILE* file, array_list_t *comp )
|
||||
{
|
||||
cc=0;
|
||||
b_append( &buffer, &cc, 1 );
|
||||
|
||||
|
||||
wcs = str2wcs( buffer.buff );
|
||||
if( wcs )
|
||||
if( wcs )
|
||||
{
|
||||
unescaped = unescape( wcs, 0 );
|
||||
al_push( comp, unescaped );
|
||||
if( unescaped )
|
||||
{
|
||||
al_push( comp, unescaped );
|
||||
}
|
||||
free( wcs );
|
||||
}
|
||||
}
|
||||
@@ -1174,9 +1203,9 @@ static void read_array( FILE* file, array_list_t *comp )
|
||||
|
||||
static int get_fd( const char *str )
|
||||
{
|
||||
char *end;
|
||||
char *end;
|
||||
long fd;
|
||||
|
||||
|
||||
errno = 0;
|
||||
fd = strtol( str, &end, 10 );
|
||||
if( fd < 0 || *end || errno )
|
||||
@@ -1191,13 +1220,13 @@ static int get_fd( const char *str )
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
int i;
|
||||
int is_quoted=0;
|
||||
int is_quoted=0;
|
||||
array_list_t *comp;
|
||||
wchar_t *prefix = 0;
|
||||
|
||||
int mangle_descriptors = 0;
|
||||
int result_fd = -1;
|
||||
|
||||
|
||||
/*
|
||||
This initialization is made early, so that the other init code
|
||||
can use global_context for memory managment
|
||||
@@ -1223,69 +1252,69 @@ int main( int argc, char **argv )
|
||||
/*
|
||||
Third mode
|
||||
*/
|
||||
|
||||
|
||||
int completion_fd = -1;
|
||||
FILE *completion_file;
|
||||
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
static struct option
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
"result-fd", required_argument, 0, 'r'
|
||||
"result-fd", required_argument, 0, 'r'
|
||||
}
|
||||
,
|
||||
{
|
||||
"completion-fd", required_argument, 0, 'c'
|
||||
"completion-fd", required_argument, 0, 'c'
|
||||
}
|
||||
,
|
||||
{
|
||||
"prefix", required_argument, 0, 'p'
|
||||
"prefix", required_argument, 0, 'p'
|
||||
}
|
||||
,
|
||||
{
|
||||
"is-quoted", no_argument, 0, 'q'
|
||||
"is-quoted", no_argument, 0, 'q'
|
||||
}
|
||||
,
|
||||
{
|
||||
"help", no_argument, 0, 'h'
|
||||
"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
"version", no_argument, 0, 'v'
|
||||
"version", no_argument, 0, 'v'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
int opt_index = 0;
|
||||
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
argv,
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
|
||||
switch( opt )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'r':
|
||||
{
|
||||
result_fd = get_fd( optarg );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 'c':
|
||||
{
|
||||
completion_fd = get_fd( optarg );
|
||||
@@ -1301,20 +1330,20 @@ int main( int argc, char **argv )
|
||||
case 'h':
|
||||
{
|
||||
print_help( argv[0], 1 );
|
||||
exit(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
case 'v':
|
||||
{
|
||||
debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION );
|
||||
exit( 0 );
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
|
||||
case 'q':
|
||||
{
|
||||
is_quoted = 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1323,7 +1352,7 @@ int main( int argc, char **argv )
|
||||
debug( 0, _(L"Unspecified file descriptors") );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
if( (completion_file = fdopen( completion_fd, "r" ) ) )
|
||||
{
|
||||
@@ -1341,8 +1370,8 @@ int main( int argc, char **argv )
|
||||
{
|
||||
prefix = wcsdup( L"" );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1356,7 +1385,7 @@ int main( int argc, char **argv )
|
||||
forward. A reasonable time frame for removal of the code
|
||||
below has yet to be determined.
|
||||
*/
|
||||
|
||||
|
||||
if( argc < 3 )
|
||||
{
|
||||
print_help( argv[0], 1 );
|
||||
@@ -1365,10 +1394,10 @@ int main( int argc, char **argv )
|
||||
else
|
||||
{
|
||||
mangle_descriptors = 1;
|
||||
|
||||
|
||||
prefix = str2wcs( argv[2] );
|
||||
is_quoted = strcmp( "1", argv[1] )==0;
|
||||
|
||||
|
||||
if( argc > 3 )
|
||||
{
|
||||
/*
|
||||
@@ -1391,11 +1420,11 @@ int main( int argc, char **argv )
|
||||
read_array( stdin, comp );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// debug( 3, L"prefix is '%ls'", prefix );
|
||||
|
||||
|
||||
init( mangle_descriptors, result_fd );
|
||||
|
||||
mangle_descriptions( comp );
|
||||
@@ -1433,9 +1462,9 @@ int main( int argc, char **argv )
|
||||
i=PAGER_MAX_COLS+1;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
free(prefix );
|
||||
|
||||
fwprintf( out_file, L"%ls", (wchar_t *)out_buff.buff );
|
||||
@@ -1447,6 +1476,6 @@ int main( int argc, char **argv )
|
||||
destroy();
|
||||
|
||||
halloc_util_destroy();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
415
fish_tests.c
415
fish_tests.c
@@ -16,7 +16,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef HAVE_GETOPT_H
|
||||
#include <getopt.h>
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <locale.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "fallback.h"
|
||||
#include "util.h"
|
||||
@@ -44,8 +45,23 @@
|
||||
#include "output.h"
|
||||
#include "exec.h"
|
||||
#include "event.h"
|
||||
#include "path.h"
|
||||
#include "halloc.h"
|
||||
#include "halloc_util.h"
|
||||
|
||||
/**
|
||||
The number of tests to run
|
||||
*/
|
||||
#define ESCAPE_TEST_COUNT 1000000
|
||||
/**
|
||||
The average length of strings to unescape
|
||||
*/
|
||||
#define ESCAPE_TEST_LENGTH 100
|
||||
/**
|
||||
The higest character number of character to try and escape
|
||||
*/
|
||||
#define ESCAPE_TEST_CHAR 4000
|
||||
|
||||
/**
|
||||
Number of laps to run performance testing loop
|
||||
*/
|
||||
@@ -69,7 +85,7 @@ static void say( wchar_t *blah, ... )
|
||||
va_list va;
|
||||
va_start( va, blah );
|
||||
vwprintf( blah, va );
|
||||
va_end( va );
|
||||
va_end( va );
|
||||
wprintf( L"\n" );
|
||||
}
|
||||
|
||||
@@ -81,10 +97,10 @@ static void err( wchar_t *blah, ... )
|
||||
va_list va;
|
||||
va_start( va, blah );
|
||||
err_count++;
|
||||
|
||||
|
||||
wprintf( L"Error: " );
|
||||
vwprintf( blah, va );
|
||||
va_end( va );
|
||||
va_end( va );
|
||||
wprintf( L"\n" );
|
||||
}
|
||||
|
||||
@@ -103,13 +119,13 @@ static void pq_test( int elements )
|
||||
{
|
||||
int i;
|
||||
int prev;
|
||||
|
||||
|
||||
int *count = calloc( sizeof(int), 100 );
|
||||
|
||||
|
||||
priority_queue_t q;
|
||||
pq_init( &q, pq_compare );
|
||||
|
||||
|
||||
|
||||
for( i=0; i<elements; i++ )
|
||||
{
|
||||
long foo = rand() % 100;
|
||||
@@ -117,9 +133,9 @@ static void pq_test( int elements )
|
||||
pq_put( &q, (void *)foo );
|
||||
count[foo]++;
|
||||
}
|
||||
|
||||
|
||||
prev = 100;
|
||||
|
||||
|
||||
for( i=0; i<elements; i++ )
|
||||
{
|
||||
long pos = (long)pq_get( &q );
|
||||
@@ -127,7 +143,7 @@ static void pq_test( int elements )
|
||||
if( pos > prev )
|
||||
err( L"Wrong order of elements in priority_queue_t" );
|
||||
prev = pos;
|
||||
|
||||
|
||||
}
|
||||
|
||||
for( i=0; i<100; i++ )
|
||||
@@ -147,10 +163,10 @@ static int stack_test( int elements )
|
||||
long i;
|
||||
|
||||
int res=1;
|
||||
|
||||
|
||||
array_list_t s;
|
||||
|
||||
al_init( &s );
|
||||
al_init( &s );
|
||||
|
||||
for( i=0; i<elements; i++ )
|
||||
{
|
||||
@@ -158,11 +174,11 @@ static int stack_test( int elements )
|
||||
|
||||
al_push_long( &s, i);
|
||||
al_push_long( &s, i);
|
||||
|
||||
|
||||
if( (foo=al_pop_long( &s )) != i )
|
||||
{
|
||||
err( L"Unexpected data" );
|
||||
res = 0;
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -170,18 +186,18 @@ static int stack_test( int elements )
|
||||
for( i=0; i<elements; i++ )
|
||||
{
|
||||
long foo;
|
||||
|
||||
|
||||
if( (foo=al_pop_long( &s )) != (elements-i-1) )
|
||||
{
|
||||
err( L"Unexpected data" );
|
||||
res = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
al_destroy( &s );
|
||||
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -194,7 +210,7 @@ static int hash_func( void *data )
|
||||
return rand();
|
||||
*/
|
||||
int foo = (int)(long)data;
|
||||
return 127*((foo^0xefc7e214)) ^(foo<<11);
|
||||
return 127*((foo^0xefc7e214)) ^(foo<<11);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,26 +229,26 @@ static int hash_test( long elements )
|
||||
{
|
||||
long i;
|
||||
int res=1;
|
||||
|
||||
|
||||
hash_table_t h;
|
||||
|
||||
hash_init( &h, hash_func, compare_func );
|
||||
|
||||
|
||||
for( i=1; i< elements+1; i++ )
|
||||
{
|
||||
hash_put( &h, (void*)i, (void*)100l-i );
|
||||
}
|
||||
|
||||
|
||||
for( i=1; i< elements+1; i++ )
|
||||
{
|
||||
if( (long)hash_get( &h, (void*)i ) != (100l-i) )
|
||||
{
|
||||
err( L"Key %d gave data %d, expected data %d",
|
||||
i,
|
||||
i,
|
||||
(long)hash_get( &h, (void*)i ),
|
||||
100l-i );
|
||||
res = 0;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -243,14 +259,14 @@ static int hash_test( long elements )
|
||||
hash_get_count( &h ),
|
||||
elements );
|
||||
res = 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
for( i=1; i<elements+1; i+=2 )
|
||||
{
|
||||
hash_remove( &h, (void*)i, 0, 0 );
|
||||
|
||||
|
||||
}
|
||||
|
||||
if( hash_get_count( &h ) != ((elements)/2) )
|
||||
@@ -260,7 +276,7 @@ static int hash_test( long elements )
|
||||
elements/2 );
|
||||
res = 0;
|
||||
}
|
||||
|
||||
|
||||
for( i=1; i<elements+1; i++ )
|
||||
{
|
||||
if( hash_contains( &h, (void*)i) != (i+1l)%2l )
|
||||
@@ -279,7 +295,7 @@ static int hash_test( long elements )
|
||||
hash_destroy( &h );
|
||||
|
||||
return res;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,19 +303,19 @@ static int hash_test( long elements )
|
||||
*/
|
||||
static void al_test( int sz)
|
||||
{
|
||||
long i;
|
||||
long i;
|
||||
array_list_t l;
|
||||
|
||||
|
||||
|
||||
|
||||
al_init( &l );
|
||||
|
||||
|
||||
al_set_long( &l, 1, 7L );
|
||||
al_set_long( &l, sz, 7L );
|
||||
|
||||
|
||||
if( al_get_count( &l ) != maxi( sz+1, 2 ) )
|
||||
err( L"Wrong number of elements in array list" );
|
||||
|
||||
|
||||
for( i=0; i<al_get_count( &l ); i++ )
|
||||
{
|
||||
long val = al_get_long( &l, i );
|
||||
@@ -323,15 +339,15 @@ static void sb_test()
|
||||
{
|
||||
string_buffer_t b;
|
||||
int res;
|
||||
|
||||
|
||||
sb_init( &b );
|
||||
|
||||
|
||||
if( (res=sb_printf( &b, L"%ls%s", L"Testing ", "string_buffer_t " )) == -1 )
|
||||
{
|
||||
err( L"Error %d while testing stringbuffers", res );
|
||||
}
|
||||
|
||||
if( (res=sb_printf( &b, L"%ls", L"functionality" ))==-1)
|
||||
|
||||
if( (res=sb_printf( &b, L"%ls", L"functionality" ))==-1)
|
||||
{
|
||||
err( L"Error %d while testing stringbuffers", res );
|
||||
}
|
||||
@@ -346,9 +362,9 @@ static void sb_test()
|
||||
err( L"numerical formating is broken, '%ls' != '%ls'", (wchar_t *)b.buff, NUM_ANS );
|
||||
}
|
||||
else
|
||||
say( L"numerical formating works" );
|
||||
say( L"numerical formating works" );
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -359,7 +375,7 @@ static void test_util()
|
||||
int i;
|
||||
|
||||
say( L"Testing utility library" );
|
||||
|
||||
|
||||
for( i=0; i<18; i++ )
|
||||
{
|
||||
long t1, t2;
|
||||
@@ -376,40 +392,174 @@ static void test_util()
|
||||
}
|
||||
|
||||
sb_test();
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
int i;
|
||||
for( i=2; i<10000000; i*=2 )
|
||||
{
|
||||
|
||||
|
||||
printf( "%d", i );
|
||||
|
||||
|
||||
t1 = get_time();
|
||||
|
||||
|
||||
if(!hash_test(i))
|
||||
exit(0);
|
||||
|
||||
|
||||
t2 = get_time();
|
||||
|
||||
|
||||
printf( " %d\n", (t2-t1)/i );
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
*/
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test the escaping/unescaping code by escaping/unescaping random
|
||||
strings and verifying that the original string comes back.
|
||||
*/
|
||||
static void test_escape()
|
||||
{
|
||||
int i;
|
||||
string_buffer_t sb;
|
||||
|
||||
say( L"Testing escaping and unescaping" );
|
||||
|
||||
sb_init( &sb );
|
||||
|
||||
for( i=0; i<ESCAPE_TEST_COUNT; i++ )
|
||||
{
|
||||
wchar_t *o, *e, *u;
|
||||
|
||||
sb_clear( &sb );
|
||||
while( rand() % ESCAPE_TEST_LENGTH )
|
||||
{
|
||||
sb_append_char( &sb, (rand() %ESCAPE_TEST_CHAR) +1 );
|
||||
}
|
||||
o = (wchar_t *)sb.buff;
|
||||
e = escape(o, 1);
|
||||
u = unescape( e, 0 );
|
||||
if( !o || !e || !u )
|
||||
{
|
||||
err( L"Escaping cycle of string %ls produced null pointer on %ls", o, e?L"unescaping":L"escaping" );
|
||||
|
||||
}
|
||||
|
||||
|
||||
if( wcscmp(o, u) )
|
||||
{
|
||||
err( L"Escaping cycle of string %ls produced different string %ls", o, u );
|
||||
|
||||
|
||||
}
|
||||
free( e );
|
||||
free( u );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Test wide/narrow conversion by creating random strings and
|
||||
verifying that the original string comes back thorugh double
|
||||
conversion.
|
||||
*/
|
||||
static void test_convert()
|
||||
{
|
||||
/* char o[] =
|
||||
{
|
||||
-17, -128, -121, -68, 0
|
||||
}
|
||||
;
|
||||
|
||||
wchar_t *w = str2wcs(o);
|
||||
char *n = wcs2str(w);
|
||||
|
||||
int i;
|
||||
|
||||
for( i=0; o[i]; i++ )
|
||||
{
|
||||
bitprint(o[i]);;
|
||||
//wprintf(L"%d ", o[i]);
|
||||
}
|
||||
wprintf(L"\n");
|
||||
|
||||
for( i=0; w[i]; i++ )
|
||||
{
|
||||
wbitprint(w[i]);;
|
||||
//wprintf(L"%d ", w[i]);
|
||||
}
|
||||
wprintf(L"\n");
|
||||
|
||||
for( i=0; n[i]; i++ )
|
||||
{
|
||||
bitprint(n[i]);;
|
||||
//wprintf(L"%d ", n[i]);
|
||||
}
|
||||
wprintf(L"\n");
|
||||
|
||||
return;
|
||||
*/
|
||||
|
||||
|
||||
int i;
|
||||
buffer_t sb;
|
||||
|
||||
say( L"Testing wide/narrow string conversion" );
|
||||
|
||||
b_init( &sb );
|
||||
|
||||
for( i=0; i<ESCAPE_TEST_COUNT; i++ )
|
||||
{
|
||||
wchar_t *w;
|
||||
char *o, *n;
|
||||
|
||||
char c;
|
||||
|
||||
sb.used=0;
|
||||
|
||||
while( rand() % ESCAPE_TEST_LENGTH )
|
||||
{
|
||||
c = rand ();
|
||||
b_append( &sb, &c, 1 );
|
||||
}
|
||||
c = 0;
|
||||
b_append( &sb, &c, 1 );
|
||||
|
||||
o = (char *)sb.buff;
|
||||
w = str2wcs(o);
|
||||
n = wcs2str(w);
|
||||
|
||||
if( !o || !w || !n )
|
||||
{
|
||||
err( L"Conversion cycle of string %s produced null pointer on %s", o, w?L"str2wcs":L"wcs2str" );
|
||||
}
|
||||
|
||||
if( strcmp(o, n) )
|
||||
{
|
||||
err( L"%d: Conversion cycle of string %s produced different string %s", i, o, n );
|
||||
}
|
||||
free( w );
|
||||
free( n );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Test the tokenizer
|
||||
*/
|
||||
static void test_tok()
|
||||
{
|
||||
tokenizer t;
|
||||
|
||||
|
||||
say( L"Testing tokenizer" );
|
||||
|
||||
|
||||
|
||||
say( L"Testing invalid input" );
|
||||
tok_init( &t, 0, 0 );
|
||||
|
||||
@@ -417,13 +567,13 @@ static void test_tok()
|
||||
{
|
||||
err(L"Invalid input to tokenizer was undetected" );
|
||||
}
|
||||
|
||||
|
||||
say( L"Testing use of broken tokenizer" );
|
||||
if( !tok_has_next( &t ) )
|
||||
{
|
||||
err( L"tok_has_next() should return 1 once on broken tokenizer" );
|
||||
}
|
||||
|
||||
|
||||
tok_next( &t );
|
||||
if( tok_last_type( &t ) != TOK_ERROR )
|
||||
{
|
||||
@@ -435,17 +585,17 @@ static void test_tok()
|
||||
*/
|
||||
say( L"Test destruction of broken tokenizer" );
|
||||
tok_destroy( &t );
|
||||
|
||||
|
||||
{
|
||||
|
||||
wchar_t *str = L"string <redirection 2>&1 'nested \"quoted\" '(string containing subshells ){and,brackets}$as[$well (as variable arrays)]";
|
||||
const int types[] =
|
||||
const int types[] =
|
||||
{
|
||||
TOK_STRING, TOK_REDIRECT_IN, TOK_STRING, TOK_REDIRECT_FD, TOK_STRING, TOK_STRING, TOK_END
|
||||
}
|
||||
;
|
||||
int i;
|
||||
|
||||
|
||||
say( L"Test correct tokenization" );
|
||||
|
||||
for( i=0, tok_init( &t, str, 0 ); i<(sizeof(types)/sizeof(int)); i++,tok_next( &t ) )
|
||||
@@ -453,7 +603,7 @@ static void test_tok()
|
||||
if( types[i] != tok_last_type( &t ) )
|
||||
{
|
||||
err( L"Tokenization error:");
|
||||
wprintf( L"Token number %d of string \n'%ls'\n, expected token type %ls, got token '%ls' of type %ls\n",
|
||||
wprintf( L"Token number %d of string \n'%ls'\n, expected token type %ls, got token '%ls' of type %ls\n",
|
||||
i+1,
|
||||
str,
|
||||
tok_get_desc(types[i]),
|
||||
@@ -462,9 +612,9 @@ static void test_tok()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -473,8 +623,8 @@ static void test_tok()
|
||||
static void test_parser()
|
||||
{
|
||||
say( L"Testing parser" );
|
||||
|
||||
|
||||
|
||||
|
||||
say( L"Testing null input to parser" );
|
||||
if( !parser_test( 0, 0, 0, 0 ) )
|
||||
{
|
||||
@@ -484,51 +634,51 @@ static void test_parser()
|
||||
say( L"Testing block nesting" );
|
||||
if( !parser_test( L"if; end", 0, 0, 0 ) )
|
||||
{
|
||||
err( L"Incomplete if statement undetected" );
|
||||
err( L"Incomplete if statement undetected" );
|
||||
}
|
||||
if( !parser_test( L"if test; echo", 0, 0, 0 ) )
|
||||
{
|
||||
err( L"Missing end undetected" );
|
||||
err( L"Missing end undetected" );
|
||||
}
|
||||
if( !parser_test( L"if test; end; end", 0, 0, 0 ) )
|
||||
{
|
||||
err( L"Unbalanced end undetected" );
|
||||
err( L"Unbalanced end undetected" );
|
||||
}
|
||||
|
||||
say( L"Testing detection of invalid use of builtin commands" );
|
||||
if( !parser_test( L"case foo", 0, 0, 0 ) )
|
||||
{
|
||||
err( L"'case' command outside of block context undetected" );
|
||||
err( L"'case' command outside of block context undetected" );
|
||||
}
|
||||
if( !parser_test( L"switch ggg; if true; case foo;end;end", 0, 0, 0 ) )
|
||||
{
|
||||
err( L"'case' command outside of switch block context undetected" );
|
||||
err( L"'case' command outside of switch block context undetected" );
|
||||
}
|
||||
if( !parser_test( L"else", 0, 0, 0 ) )
|
||||
{
|
||||
err( L"'else' command outside of conditional block context undetected" );
|
||||
err( L"'else' command outside of conditional block context undetected" );
|
||||
}
|
||||
if( !parser_test( L"break", 0, 0, 0 ) )
|
||||
{
|
||||
err( L"'break' command outside of loop block context undetected" );
|
||||
err( L"'break' command outside of loop block context undetected" );
|
||||
}
|
||||
if( !parser_test( L"exec ls|less", 0, 0, 0 ) || !parser_test( L"echo|return", 0, 0, 0 ))
|
||||
{
|
||||
err( L"Invalid pipe command undetected" );
|
||||
}
|
||||
err( L"Invalid pipe command undetected" );
|
||||
}
|
||||
|
||||
say( L"Testing basic evaluation" );
|
||||
if( !eval( 0, 0, TOP ) )
|
||||
{
|
||||
err( L"Null input when evaluating undetected" );
|
||||
}
|
||||
}
|
||||
if( !eval( L"ls", 0, WHILE ) )
|
||||
{
|
||||
err( L"Invalid block mode when evaluating undetected" );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Perform parameter expansion and test if the output equals the zero-terminated parameter list supplied.
|
||||
|
||||
@@ -538,42 +688,42 @@ static void test_parser()
|
||||
|
||||
static int expand_test( const wchar_t *in, int flags, ... )
|
||||
{
|
||||
array_list_t out;
|
||||
array_list_t out;
|
||||
va_list va;
|
||||
int i=0;
|
||||
int res=1;
|
||||
wchar_t *arg;
|
||||
|
||||
|
||||
al_init( &out );
|
||||
if( expand_string( 0, wcsdup(in), &out, flags) )
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
va_start( va, flags );
|
||||
|
||||
while( (arg=va_arg(va, wchar_t *) )!= 0 )
|
||||
while( (arg=va_arg(va, wchar_t *) )!= 0 )
|
||||
{
|
||||
if( al_get_count( &out ) == i )
|
||||
{
|
||||
res=0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( wcscmp( al_get( &out, i ),arg) != 0 )
|
||||
{
|
||||
res=0;
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
|
||||
i++;
|
||||
}
|
||||
va_end( va );
|
||||
|
||||
|
||||
al_foreach( &out, &free );
|
||||
return res;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -582,7 +732,7 @@ static int expand_test( const wchar_t *in, int flags, ... )
|
||||
static void test_expand()
|
||||
{
|
||||
say( L"Testing parameter expansion" );
|
||||
|
||||
|
||||
if( !expand_test( L"foo", 0, L"foo", 0 ))
|
||||
{
|
||||
err( L"Strings do not expand to themselves" );
|
||||
@@ -597,9 +747,32 @@ static void test_expand()
|
||||
{
|
||||
err( L"Cannot skip wildcard expansion" );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Test path functions
|
||||
*/
|
||||
static void test_path()
|
||||
{
|
||||
say( L"Testing path functions" );
|
||||
|
||||
void *context = halloc( 0, 0 );
|
||||
|
||||
|
||||
wchar_t *can = path_make_canonical( context, L"//foo//////bar/" );
|
||||
|
||||
if( wcscmp( can, L"/foo/bar" ) )
|
||||
{
|
||||
err( L"Bug in canonical PATH code" );
|
||||
}
|
||||
|
||||
halloc_free( context );
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Test speed of completion calculations
|
||||
*/
|
||||
@@ -612,81 +785,86 @@ void perf_complete()
|
||||
double t;
|
||||
wchar_t str[3]=
|
||||
{
|
||||
0, 0, 0
|
||||
0, 0, 0
|
||||
}
|
||||
;
|
||||
int i;
|
||||
|
||||
|
||||
|
||||
|
||||
say( L"Testing completion performance" );
|
||||
al_init( &out );
|
||||
|
||||
|
||||
reader_push(L"");
|
||||
say( L"Here we go" );
|
||||
|
||||
|
||||
t1 = get_time();
|
||||
|
||||
|
||||
|
||||
|
||||
for( c=L'a'; c<=L'z'; c++ )
|
||||
{
|
||||
str[0]=c;
|
||||
reader_set_buffer( str, 0 );
|
||||
|
||||
|
||||
complete( str, &out );
|
||||
|
||||
|
||||
matches += al_get_count( &out );
|
||||
|
||||
|
||||
al_foreach( &out, &free );
|
||||
al_truncate( &out, 0 );
|
||||
}
|
||||
t2=get_time();
|
||||
|
||||
|
||||
t = (double)(t2-t1)/(1000000*26);
|
||||
|
||||
|
||||
say( L"One letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
|
||||
|
||||
|
||||
matches=0;
|
||||
t1 = get_time();
|
||||
for( i=0; i<LAPS; i++ )
|
||||
{
|
||||
str[0]='a'+(rand()%26);
|
||||
str[1]='a'+(rand()%26);
|
||||
|
||||
|
||||
reader_set_buffer( str, 0 );
|
||||
|
||||
|
||||
complete( str, &out );
|
||||
|
||||
|
||||
matches += al_get_count( &out );
|
||||
|
||||
|
||||
al_foreach( &out, &free );
|
||||
al_truncate( &out, 0 );
|
||||
}
|
||||
t2=get_time();
|
||||
|
||||
|
||||
t = (double)(t2-t1)/(1000000*LAPS);
|
||||
|
||||
|
||||
say( L"Two letter command completion took %f seconds per completion, %f microseconds/match", t, (double)(t2-t1)/matches );
|
||||
|
||||
|
||||
al_destroy( &out );
|
||||
|
||||
reader_pop();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Main test
|
||||
Main test
|
||||
*/
|
||||
int main( int argc, char **argv )
|
||||
{
|
||||
setlocale( LC_ALL, "" );
|
||||
srand( time( 0 ) );
|
||||
|
||||
program_name=L"(ignore)";
|
||||
|
||||
|
||||
say( L"Testing low-level functionality");
|
||||
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();
|
||||
proc_init();
|
||||
halloc_util_init();
|
||||
event_init();
|
||||
event_init();
|
||||
parser_init();
|
||||
function_init();
|
||||
builtin_init();
|
||||
@@ -694,10 +872,13 @@ int main( int argc, char **argv )
|
||||
env_init();
|
||||
|
||||
test_util();
|
||||
test_escape();
|
||||
test_convert();
|
||||
test_tok();
|
||||
test_parser();
|
||||
test_expand();
|
||||
|
||||
test_path();
|
||||
|
||||
say( L"Encountered %d errors in low-level tests", err_count );
|
||||
|
||||
/*
|
||||
@@ -705,9 +886,9 @@ int main( int argc, char **argv )
|
||||
*/
|
||||
// say( L"Testing performance" );
|
||||
// perf_complete();
|
||||
|
||||
|
||||
env_destroy();
|
||||
reader_destroy();
|
||||
reader_destroy();
|
||||
parser_destroy();
|
||||
function_destroy();
|
||||
builtin_destroy();
|
||||
@@ -715,5 +896,5 @@ int main( int argc, char **argv )
|
||||
event_destroy();
|
||||
proc_destroy();
|
||||
halloc_util_destroy();
|
||||
|
||||
|
||||
}
|
||||
|
||||
184
fishd.c
184
fishd.c
@@ -78,7 +78,7 @@ time the original barrier request was sent have been received.
|
||||
/**
|
||||
Maximum length of socket filename
|
||||
*/
|
||||
#ifndef UNIX_PATH_MAX
|
||||
#ifndef UNIX_PATH_MAX
|
||||
#define UNIX_PATH_MAX 100
|
||||
#endif
|
||||
|
||||
@@ -182,7 +182,7 @@ static char *get_socket_filename()
|
||||
}
|
||||
|
||||
/**
|
||||
Signal handler for the term signal.
|
||||
Signal handler for the term signal.
|
||||
*/
|
||||
static void handle_term( int signal )
|
||||
{
|
||||
@@ -192,17 +192,17 @@ static void handle_term( int signal )
|
||||
|
||||
/**
|
||||
Acquire the lock for the socket
|
||||
Returns the name of the lock file if successful or
|
||||
Returns the name of the lock file if successful or
|
||||
NULL if unable to obtain lock.
|
||||
The returned string must be free()d after unlink()ing the file to release
|
||||
The returned string must be free()d after unlink()ing the file to release
|
||||
the lock
|
||||
*/
|
||||
static char *acquire_socket_lock( const char *sock_name )
|
||||
{
|
||||
int len = strlen( sock_name );
|
||||
char *lockfile = malloc( len + strlen( LOCKPOSTFIX ) + 1 );
|
||||
|
||||
if( lockfile == NULL )
|
||||
|
||||
if( lockfile == NULL )
|
||||
{
|
||||
wperror( L"acquire_socket_lock" );
|
||||
exit( EXIT_FAILURE );
|
||||
@@ -237,13 +237,13 @@ static int get_socket()
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
debug( 4, L"Acquired lockfile: %s", lockfile );
|
||||
|
||||
|
||||
local.sun_family = AF_UNIX;
|
||||
strcpy( local.sun_path, sock_name );
|
||||
len = sizeof(local);
|
||||
|
||||
|
||||
debug(1, L"Connect to socket at %s", sock_name);
|
||||
|
||||
|
||||
if( ( s = socket( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 )
|
||||
{
|
||||
wperror( L"socket" );
|
||||
@@ -262,7 +262,7 @@ static int get_socket()
|
||||
exitcode = 0;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
|
||||
unlink( local.sun_path );
|
||||
if( bind( s, (struct sockaddr *)&local, len ) == -1 )
|
||||
{
|
||||
@@ -288,9 +288,9 @@ static int get_socket()
|
||||
/*
|
||||
End critical section protected by lock
|
||||
*/
|
||||
|
||||
|
||||
free( lockfile );
|
||||
|
||||
|
||||
free( sock_name );
|
||||
|
||||
if( doexit )
|
||||
@@ -311,24 +311,24 @@ static void broadcast( int type, const wchar_t *key, const wchar_t *val )
|
||||
|
||||
if( !conn )
|
||||
return;
|
||||
|
||||
|
||||
msg = create_message( type, key, val );
|
||||
|
||||
|
||||
/*
|
||||
Don't merge these loops, or try_send_all can free the message
|
||||
prematurely
|
||||
*/
|
||||
|
||||
|
||||
for( c = conn; c; c=c->next )
|
||||
{
|
||||
msg->count++;
|
||||
q_put( &c->unsent, msg );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for( c = conn; c; c=c->next )
|
||||
{
|
||||
try_send_all( c );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,7 +345,7 @@ static void daemonize()
|
||||
debug( 0, L"Could not put fishd in background. Quitting" );
|
||||
wperror( L"fork" );
|
||||
exit(1);
|
||||
|
||||
|
||||
case 0:
|
||||
{
|
||||
/*
|
||||
@@ -366,19 +366,19 @@ static void daemonize()
|
||||
sigaction( SIGTERM, &act, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
{
|
||||
debug( 0, L"Parent process exiting (This is normal)" );
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Put ourself in out own processing group
|
||||
*/
|
||||
setsid();
|
||||
|
||||
|
||||
/*
|
||||
Close stdin and stdout. We only use stderr, anyway.
|
||||
*/
|
||||
@@ -394,7 +394,7 @@ static wchar_t *fishd_env_get( wchar_t *key )
|
||||
{
|
||||
char *nres, *nkey;
|
||||
wchar_t *res;
|
||||
|
||||
|
||||
nkey = wcs2str( key );
|
||||
nres = getenv( nkey );
|
||||
free( nkey );
|
||||
@@ -407,7 +407,7 @@ static wchar_t *fishd_env_get( wchar_t *key )
|
||||
res = env_universal_common_get( key );
|
||||
if( res )
|
||||
res = wcsdup( res );
|
||||
|
||||
|
||||
return env_universal_common_get( key );
|
||||
}
|
||||
}
|
||||
@@ -423,7 +423,7 @@ static wchar_t *fishd_get_config()
|
||||
wchar_t *xdg_dir, *home;
|
||||
int done = 0;
|
||||
wchar_t *res = 0;
|
||||
|
||||
|
||||
xdg_dir = fishd_env_get( L"XDG_CONFIG_HOME" );
|
||||
if( xdg_dir )
|
||||
{
|
||||
@@ -439,7 +439,7 @@ static wchar_t *fishd_get_config()
|
||||
free( xdg_dir );
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
home = fishd_env_get( L"HOME" );
|
||||
if( home )
|
||||
{
|
||||
@@ -455,7 +455,7 @@ static wchar_t *fishd_get_config()
|
||||
free( home );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( done )
|
||||
{
|
||||
return res;
|
||||
@@ -465,7 +465,7 @@ static wchar_t *fishd_get_config()
|
||||
debug( 0, _(L"Unable to create a configuration directory for fish. Your personal settings will not be saved. Please set the $XDG_CONFIG_HOME variable to a directory where the current user has write access." ));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -475,22 +475,22 @@ static void load_or_save( int save)
|
||||
{
|
||||
char *name;
|
||||
wchar_t *wdir = fishd_get_config();
|
||||
char *dir;
|
||||
char *dir;
|
||||
char hostname[HOSTNAME_LEN];
|
||||
connection_t c;
|
||||
int fd;
|
||||
|
||||
|
||||
if( !wdir )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
dir = wcs2str( wdir );
|
||||
|
||||
free( wdir );
|
||||
|
||||
|
||||
gethostname( hostname, HOSTNAME_LEN );
|
||||
|
||||
|
||||
name = malloc( strlen(dir)+ strlen(FILE)+ strlen(hostname) + 2 );
|
||||
strcpy( name, dir );
|
||||
strcat( name, "/" );
|
||||
@@ -499,20 +499,20 @@ static void load_or_save( int save)
|
||||
|
||||
free( dir );
|
||||
|
||||
|
||||
debug( 4, L"Open file for %s: '%s'",
|
||||
save?"saving":"loading",
|
||||
|
||||
debug( 4, L"Open file for %s: '%s'",
|
||||
save?"saving":"loading",
|
||||
name );
|
||||
|
||||
|
||||
fd = open( name, save?(O_CREAT | O_TRUNC | O_WRONLY):O_RDONLY, 0600);
|
||||
|
||||
|
||||
free( name );
|
||||
|
||||
|
||||
if( fd == -1 )
|
||||
{
|
||||
debug( 1, L"Could not open load/save file. No previous saves?" );
|
||||
wperror( L"open" );
|
||||
return;
|
||||
return;
|
||||
}
|
||||
debug( 4, L"File open on fd %d", c.fd );
|
||||
|
||||
@@ -520,14 +520,14 @@ static void load_or_save( int save)
|
||||
|
||||
if( save )
|
||||
{
|
||||
|
||||
write( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
|
||||
|
||||
write_loop( c.fd, SAVE_MSG, strlen(SAVE_MSG) );
|
||||
enqueue_all( &c );
|
||||
}
|
||||
else
|
||||
read_message( &c );
|
||||
|
||||
connection_destroy( &c );
|
||||
connection_destroy( &c );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -553,10 +553,10 @@ static void init()
|
||||
{
|
||||
|
||||
sock = get_socket();
|
||||
daemonize();
|
||||
daemonize();
|
||||
env_universal_common_init( &broadcast );
|
||||
|
||||
load();
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,13 +569,13 @@ int main( int argc, char ** argv )
|
||||
socklen_t t;
|
||||
int max_fd;
|
||||
int update_count=0;
|
||||
|
||||
|
||||
fd_set read_fd, write_fd;
|
||||
|
||||
halloc_util_init();
|
||||
|
||||
|
||||
program_name=L"fishd";
|
||||
wsetlocale( LC_ALL, L"" );
|
||||
wsetlocale( LC_ALL, L"" );
|
||||
|
||||
/*
|
||||
Parse options
|
||||
@@ -586,57 +586,57 @@ int main( int argc, char ** argv )
|
||||
long_options[] =
|
||||
{
|
||||
{
|
||||
"help", no_argument, 0, 'h'
|
||||
"help", no_argument, 0, 'h'
|
||||
}
|
||||
,
|
||||
{
|
||||
"version", no_argument, 0, 'v'
|
||||
"version", no_argument, 0, 'v'
|
||||
}
|
||||
,
|
||||
{
|
||||
0, 0, 0, 0
|
||||
{
|
||||
0, 0, 0, 0
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
int opt_index = 0;
|
||||
|
||||
|
||||
int opt = getopt_long( argc,
|
||||
argv,
|
||||
argv,
|
||||
GETOPT_STRING,
|
||||
long_options,
|
||||
long_options,
|
||||
&opt_index );
|
||||
|
||||
|
||||
if( opt == -1 )
|
||||
break;
|
||||
|
||||
|
||||
switch( opt )
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
print_help( argv[0], 1 );
|
||||
exit(0);
|
||||
|
||||
exit(0);
|
||||
|
||||
case 'v':
|
||||
debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION );
|
||||
exit( 0 );
|
||||
|
||||
exit( 0 );
|
||||
|
||||
case '?':
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
init();
|
||||
while(1)
|
||||
while(1)
|
||||
{
|
||||
connection_t *c;
|
||||
int res;
|
||||
|
||||
t = sizeof( remote );
|
||||
|
||||
t = sizeof( remote );
|
||||
|
||||
FD_ZERO( &read_fd );
|
||||
FD_ZERO( &write_fd );
|
||||
FD_SET( sock, &read_fd );
|
||||
@@ -645,7 +645,7 @@ int main( int argc, char ** argv )
|
||||
{
|
||||
FD_SET( c->fd, &read_fd );
|
||||
max_fd = maxi( max_fd, c->fd+1);
|
||||
|
||||
|
||||
if( ! q_empty( &c->unsent ) )
|
||||
{
|
||||
FD_SET( c->fd, &write_fd );
|
||||
@@ -661,22 +661,22 @@ int main( int argc, char ** argv )
|
||||
save();
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
if( res != -1 )
|
||||
break;
|
||||
|
||||
|
||||
if( errno != EINTR )
|
||||
{
|
||||
wperror( L"select" );
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( FD_ISSET( sock, &read_fd ) )
|
||||
{
|
||||
if( (child_socket =
|
||||
accept( sock,
|
||||
(struct sockaddr *)&remote,
|
||||
if( (child_socket =
|
||||
accept( sock,
|
||||
(struct sockaddr *)&remote,
|
||||
&t) ) == -1) {
|
||||
wperror( L"accept" );
|
||||
exit(1);
|
||||
@@ -688,20 +688,20 @@ int main( int argc, char ** argv )
|
||||
if( fcntl( child_socket, F_SETFL, O_NONBLOCK ) != 0 )
|
||||
{
|
||||
wperror( L"fcntl" );
|
||||
close( child_socket );
|
||||
close( child_socket );
|
||||
}
|
||||
else
|
||||
{
|
||||
connection_t *new = malloc( sizeof(connection_t));
|
||||
connection_init( new, child_socket );
|
||||
connection_init( new, child_socket );
|
||||
new->next = conn;
|
||||
send( new->fd, GREETING, strlen(GREETING), MSG_DONTWAIT );
|
||||
enqueue_all( new );
|
||||
enqueue_all( new );
|
||||
conn=new;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for( c=conn; c; c=c->next )
|
||||
{
|
||||
if( FD_ISSET( c->fd, &write_fd ) )
|
||||
@@ -709,7 +709,7 @@ int main( int argc, char ** argv )
|
||||
try_send_all( c );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for( c=conn; c; c=c->next )
|
||||
{
|
||||
if( FD_ISSET( c->fd, &read_fd ) )
|
||||
@@ -728,10 +728,10 @@ int main( int argc, char ** argv )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
connection_t *prev=0;
|
||||
c=conn;
|
||||
|
||||
|
||||
while( c )
|
||||
{
|
||||
if( c->killme )
|
||||
@@ -745,7 +745,7 @@ int main( int argc, char ** argv )
|
||||
if( !msg->count )
|
||||
free( msg );
|
||||
}
|
||||
|
||||
|
||||
connection_destroy( c );
|
||||
if( prev )
|
||||
{
|
||||
@@ -755,11 +755,11 @@ int main( int argc, char ** argv )
|
||||
{
|
||||
conn=c->next;
|
||||
}
|
||||
|
||||
|
||||
free(c);
|
||||
|
||||
|
||||
c=(prev?prev->next:conn);
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -771,10 +771,10 @@ int main( int argc, char ** argv )
|
||||
if( !conn )
|
||||
{
|
||||
debug( 0, L"No more clients. Quitting" );
|
||||
save();
|
||||
save();
|
||||
env_universal_common_destroy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
halloc_util_destroy();
|
||||
|
||||
272
function.c
272
function.c
@@ -28,6 +28,7 @@
|
||||
#include "event.h"
|
||||
#include "reader.h"
|
||||
#include "parse_util.h"
|
||||
#include "parser_keywords.h"
|
||||
#include "env.h"
|
||||
#include "expand.h"
|
||||
#include "halloc.h"
|
||||
@@ -40,9 +41,9 @@
|
||||
typedef struct
|
||||
{
|
||||
/** Function definition */
|
||||
wchar_t *cmd;
|
||||
wchar_t *definition;
|
||||
/** Function description */
|
||||
wchar_t *desc;
|
||||
wchar_t *description;
|
||||
/**
|
||||
File where this function was defined
|
||||
*/
|
||||
@@ -50,14 +51,26 @@ typedef struct
|
||||
/**
|
||||
Line where definition started
|
||||
*/
|
||||
int definition_offset;
|
||||
|
||||
int definition_offset;
|
||||
|
||||
/**
|
||||
List of all named arguments for this function
|
||||
*/
|
||||
array_list_t *named_arguments;
|
||||
|
||||
|
||||
/**
|
||||
Flag for specifying that this function was automatically loaded
|
||||
*/
|
||||
int is_autoload;
|
||||
|
||||
/**
|
||||
Set to non-zero if invoking this function shadows the variables
|
||||
of the underlying function.
|
||||
*/
|
||||
int shadows;
|
||||
}
|
||||
function_data_t;
|
||||
function_internal_data_t;
|
||||
|
||||
/**
|
||||
Table containing all functions
|
||||
@@ -79,12 +92,12 @@ 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 );
|
||||
function_internal_data_t *data;
|
||||
data = (function_internal_data_t *)hash_get( &function, name );
|
||||
if( data && !data->is_autoload )
|
||||
return 0;
|
||||
|
||||
is_autoload = 1;
|
||||
|
||||
is_autoload = 1;
|
||||
res = parse_util_load( name,
|
||||
L"fish_function_path",
|
||||
&function_remove,
|
||||
@@ -100,13 +113,13 @@ static int load( const wchar_t *name )
|
||||
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 );
|
||||
|
||||
tokenize_variable_array( path_var, &path_list );
|
||||
@@ -116,7 +129,7 @@ static void autoload_names( array_list_t *out, int get_hidden )
|
||||
DIR *dir = wopendir( ndir );
|
||||
if( !dir )
|
||||
continue;
|
||||
|
||||
|
||||
struct wdirent *next;
|
||||
while( (next=wreaddir(dir))!=0 )
|
||||
{
|
||||
@@ -124,7 +137,7 @@ static void autoload_names( array_list_t *out, int get_hidden )
|
||||
wchar_t *suffix;
|
||||
if( !get_hidden && fn[0] == L'_' )
|
||||
continue;
|
||||
|
||||
|
||||
suffix = wcsrchr( fn, L'.' );
|
||||
if( suffix && (wcscmp( suffix, L".fish" ) == 0 ) )
|
||||
{
|
||||
@@ -135,7 +148,7 @@ static void autoload_names( array_list_t *out, int get_hidden )
|
||||
DIE_MEM();
|
||||
al_push( out, dup );
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
al_foreach( &path_list, &free );
|
||||
@@ -149,6 +162,9 @@ void function_init()
|
||||
&hash_wcs_cmp );
|
||||
}
|
||||
|
||||
/**
|
||||
Clear specified value, but not key
|
||||
*/
|
||||
static void clear_entry( void *key, void *value )
|
||||
{
|
||||
halloc_free( value );
|
||||
@@ -161,47 +177,92 @@ void function_destroy()
|
||||
}
|
||||
|
||||
|
||||
void function_add( const wchar_t *name,
|
||||
const wchar_t *val,
|
||||
const wchar_t *desc,
|
||||
array_list_t *events )
|
||||
void function_add( function_data_t *data )
|
||||
{
|
||||
int i;
|
||||
wchar_t *cmd_end;
|
||||
function_data_t *d;
|
||||
|
||||
CHECK( name, );
|
||||
CHECK( val, );
|
||||
|
||||
function_remove( name );
|
||||
|
||||
d = halloc( 0, sizeof( function_data_t ) );
|
||||
function_internal_data_t *d;
|
||||
|
||||
CHECK( data->name, );
|
||||
CHECK( data->definition, );
|
||||
|
||||
function_remove( data->name );
|
||||
|
||||
d = halloc( 0, sizeof( function_internal_data_t ) );
|
||||
d->definition_offset = parse_util_lineno( parser_get_buffer(), current_block->tok_pos )-1;
|
||||
d->cmd = halloc_wcsdup( d, val );
|
||||
|
||||
cmd_end = d->cmd + wcslen(d->cmd)-1;
|
||||
|
||||
d->desc = desc?halloc_wcsdup( d, desc ):0;
|
||||
d->definition = halloc_wcsdup( d, data->definition );
|
||||
|
||||
if( data->named_arguments )
|
||||
{
|
||||
d->named_arguments = al_halloc( d );
|
||||
|
||||
for( i=0; i<al_get_count( data->named_arguments ); i++ )
|
||||
{
|
||||
al_push( d->named_arguments, halloc_wcsdup( d, (wchar_t *)al_get( data->named_arguments, i ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
cmd_end = d->definition + wcslen(d->definition)-1;
|
||||
|
||||
d->description = data->description?halloc_wcsdup( d, data->description ):0;
|
||||
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++ )
|
||||
d->shadows = data->shadows;
|
||||
|
||||
hash_put( &function, intern(data->name), d );
|
||||
|
||||
for( i=0; i<al_get_count( data->events ); i++ )
|
||||
{
|
||||
event_add_handler( (event_t *)al_get( events, i ) );
|
||||
event_add_handler( (event_t *)al_get( data->events, i ) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int function_copy( const wchar_t *name, const wchar_t *new_name )
|
||||
{
|
||||
int i;
|
||||
function_internal_data_t *d, *orig_d;
|
||||
|
||||
CHECK( name, 0 );
|
||||
CHECK( new_name, 0 );
|
||||
|
||||
orig_d = (function_internal_data_t *)hash_get(&function, name);
|
||||
if( !orig_d )
|
||||
return 0;
|
||||
|
||||
d = halloc(0, sizeof( function_internal_data_t ) );
|
||||
d->definition_offset = orig_d->definition_offset;
|
||||
d->definition = halloc_wcsdup( d, orig_d->definition );
|
||||
if( orig_d->named_arguments )
|
||||
{
|
||||
d->named_arguments = al_halloc( d );
|
||||
for( i=0; i<al_get_count( orig_d->named_arguments ); i++ )
|
||||
{
|
||||
al_push( d->named_arguments, halloc_wcsdup( d, (wchar_t *)al_get( orig_d->named_arguments, i ) ) );
|
||||
}
|
||||
d->description = orig_d->description?halloc_wcsdup(d, orig_d->description):0;
|
||||
d->shadows = orig_d->shadows;
|
||||
|
||||
// This new instance of the function shouldn't be tied to the def
|
||||
// file of the original.
|
||||
d->definition_file = 0;
|
||||
d->is_autoload = 0;
|
||||
}
|
||||
|
||||
hash_put( &function, intern(new_name), d );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int function_exists( const wchar_t *cmd )
|
||||
{
|
||||
|
||||
|
||||
CHECK( cmd, 0 );
|
||||
|
||||
if( parser_is_reserved(cmd) )
|
||||
|
||||
if( parser_keywords_is_reserved(cmd) )
|
||||
return 0;
|
||||
|
||||
|
||||
load( cmd );
|
||||
return (hash_get(&function, cmd) != 0 );
|
||||
}
|
||||
@@ -210,9 +271,9 @@ void function_remove( const wchar_t *name )
|
||||
{
|
||||
void *key;
|
||||
void *dv;
|
||||
function_data_t *d;
|
||||
function_internal_data_t *d;
|
||||
event_t ev;
|
||||
|
||||
|
||||
CHECK( name, );
|
||||
|
||||
hash_remove( &function,
|
||||
@@ -220,13 +281,13 @@ void function_remove( const wchar_t *name )
|
||||
&key,
|
||||
&dv );
|
||||
|
||||
d=(function_data_t *)dv;
|
||||
|
||||
d=(function_internal_data_t *)dv;
|
||||
|
||||
if( !key )
|
||||
return;
|
||||
|
||||
ev.type=EVENT_ANY;
|
||||
ev.function_name=name;
|
||||
ev.function_name=name;
|
||||
event_remove( &ev );
|
||||
|
||||
halloc_free( d );
|
||||
@@ -241,47 +302,74 @@ void function_remove( const wchar_t *name )
|
||||
parse_util_unload( name, L"fish_function_path", 0 );
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t *function_get_definition( const wchar_t *argv )
|
||||
|
||||
const wchar_t *function_get_definition( const wchar_t *name )
|
||||
{
|
||||
function_data_t *data;
|
||||
|
||||
CHECK( argv, 0 );
|
||||
|
||||
load( argv );
|
||||
data = (function_data_t *)hash_get( &function, argv );
|
||||
function_internal_data_t *data;
|
||||
|
||||
CHECK( name, 0 );
|
||||
|
||||
load( name );
|
||||
data = (function_internal_data_t *)hash_get( &function, name );
|
||||
if( data == 0 )
|
||||
return 0;
|
||||
return data->cmd;
|
||||
return data->definition;
|
||||
}
|
||||
|
||||
const wchar_t *function_get_desc( const wchar_t *argv )
|
||||
|
||||
array_list_t *function_get_named_arguments( const wchar_t *name )
|
||||
{
|
||||
function_data_t *data;
|
||||
|
||||
CHECK( argv, 0 );
|
||||
|
||||
load( argv );
|
||||
data = (function_data_t *)hash_get( &function, argv );
|
||||
function_internal_data_t *data;
|
||||
|
||||
CHECK( name, 0 );
|
||||
|
||||
load( name );
|
||||
data = (function_internal_data_t *)hash_get( &function, name );
|
||||
if( data == 0 )
|
||||
return 0;
|
||||
|
||||
return _(data->desc);
|
||||
return data->named_arguments;
|
||||
}
|
||||
|
||||
int function_get_shadows( const wchar_t *name )
|
||||
{
|
||||
function_internal_data_t *data;
|
||||
|
||||
CHECK( name, 0 );
|
||||
|
||||
load( name );
|
||||
data = (function_internal_data_t *)hash_get( &function, name );
|
||||
if( data == 0 )
|
||||
return 0;
|
||||
return data->shadows;
|
||||
}
|
||||
|
||||
|
||||
const wchar_t *function_get_desc( const wchar_t *name )
|
||||
{
|
||||
function_internal_data_t *data;
|
||||
|
||||
CHECK( name, 0 );
|
||||
|
||||
load( name );
|
||||
data = (function_internal_data_t *)hash_get( &function, name );
|
||||
if( data == 0 )
|
||||
return 0;
|
||||
|
||||
return _(data->description);
|
||||
}
|
||||
|
||||
void function_set_desc( const wchar_t *name, const wchar_t *desc )
|
||||
{
|
||||
function_data_t *data;
|
||||
|
||||
function_internal_data_t *data;
|
||||
|
||||
CHECK( name, );
|
||||
CHECK( desc, );
|
||||
|
||||
|
||||
load( name );
|
||||
data = (function_data_t *)hash_get( &function, name );
|
||||
data = (function_internal_data_t *)hash_get( &function, name );
|
||||
if( data == 0 )
|
||||
return;
|
||||
|
||||
data->desc = halloc_wcsdup( data, desc );
|
||||
data->description = halloc_wcsdup( data, desc );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,6 +378,10 @@ void function_set_desc( const wchar_t *name, const wchar_t *desc )
|
||||
static int al_contains_str( array_list_t *list, const wchar_t * str )
|
||||
{
|
||||
int i;
|
||||
|
||||
CHECK( list, 0 );
|
||||
CHECK( str, 0 );
|
||||
|
||||
for( i=0; i<al_get_count( list ); i++ )
|
||||
{
|
||||
if( wcscmp( al_get( list, i ), str) == 0 )
|
||||
@@ -299,9 +391,9 @@ static int al_contains_str( array_list_t *list, const wchar_t * str )
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Helper function for removing hidden functions
|
||||
Helper function for removing hidden functions
|
||||
*/
|
||||
static void get_names_internal( void *key,
|
||||
void *val,
|
||||
@@ -315,14 +407,14 @@ static void get_names_internal( void *key,
|
||||
}
|
||||
|
||||
/**
|
||||
Helper function for removing hidden functions
|
||||
Helper function for removing hidden functions
|
||||
*/
|
||||
static void get_names_internal_all( void *key,
|
||||
void *val,
|
||||
void *aux )
|
||||
{
|
||||
wchar_t *name = (wchar_t *)key;
|
||||
|
||||
|
||||
if( !al_contains_str( (array_list_t *)aux, name ) )
|
||||
{
|
||||
al_push( (array_list_t *)aux, name );
|
||||
@@ -332,9 +424,9 @@ static void get_names_internal_all( void *key,
|
||||
void function_get_names( array_list_t *list, int get_hidden )
|
||||
{
|
||||
CHECK( list, );
|
||||
|
||||
|
||||
autoload_names( list, get_hidden );
|
||||
|
||||
|
||||
if( get_hidden )
|
||||
{
|
||||
hash_foreach2( &function, &get_names_internal_all, list );
|
||||
@@ -343,33 +435,33 @@ void function_get_names( array_list_t *list, int get_hidden )
|
||||
{
|
||||
hash_foreach2( &function, &get_names_internal, list );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
const wchar_t *function_get_definition_file( const wchar_t *argv )
|
||||
const wchar_t *function_get_definition_file( const wchar_t *name )
|
||||
{
|
||||
function_data_t *data;
|
||||
function_internal_data_t *data;
|
||||
|
||||
CHECK( argv, 0 );
|
||||
|
||||
data = (function_data_t *)hash_get( &function, argv );
|
||||
CHECK( name, 0 );
|
||||
|
||||
data = (function_internal_data_t *)hash_get( &function, name );
|
||||
if( data == 0 )
|
||||
return 0;
|
||||
|
||||
|
||||
return data->definition_file;
|
||||
}
|
||||
|
||||
|
||||
int function_get_definition_offset( const wchar_t *argv )
|
||||
int function_get_definition_offset( const wchar_t *name )
|
||||
{
|
||||
function_data_t *data;
|
||||
function_internal_data_t *data;
|
||||
|
||||
CHECK( argv, -1 );
|
||||
|
||||
data = (function_data_t *)hash_get( &function, argv );
|
||||
CHECK( name, -1 );
|
||||
|
||||
data = (function_internal_data_t *)hash_get( &function, name );
|
||||
if( data == 0 )
|
||||
return -1;
|
||||
|
||||
|
||||
return data->definition_offset;
|
||||
}
|
||||
|
||||
|
||||
67
function.h
67
function.h
@@ -1,4 +1,4 @@
|
||||
/** \file function.h
|
||||
/** \file function.h
|
||||
|
||||
Prototypes for functions for storing and retrieving function
|
||||
information. These functions also take care of autoloading
|
||||
@@ -15,7 +15,45 @@
|
||||
#include "util.h"
|
||||
|
||||
/**
|
||||
Initialize function data
|
||||
Structure describing a function. This is used by the parser to
|
||||
store data on a function while parsing it. It is not used
|
||||
internally to store functions, the function_internal_data_t
|
||||
structure is used for that purpose. Parhaps these two should be
|
||||
merged.
|
||||
*/
|
||||
typedef struct function_data
|
||||
{
|
||||
/**
|
||||
Name of function
|
||||
*/
|
||||
wchar_t *name;
|
||||
/**
|
||||
Description of function
|
||||
*/
|
||||
wchar_t *description;
|
||||
/**
|
||||
Function definition
|
||||
*/
|
||||
wchar_t *definition;
|
||||
/**
|
||||
List of all event handlers for this function
|
||||
*/
|
||||
array_list_t *events;
|
||||
/**
|
||||
List of all named arguments for this function
|
||||
*/
|
||||
array_list_t *named_arguments;
|
||||
/**
|
||||
Set to non-zero if invoking this function shadows the variables
|
||||
of the underlying function.
|
||||
*/
|
||||
int shadows;
|
||||
}
|
||||
function_data_t;
|
||||
|
||||
|
||||
/**
|
||||
Initialize function data
|
||||
*/
|
||||
void function_init();
|
||||
|
||||
@@ -28,10 +66,7 @@ void function_destroy();
|
||||
Add an function. The parameters values are copied and should be
|
||||
freed by the caller.
|
||||
*/
|
||||
void function_add( const wchar_t *name,
|
||||
const wchar_t *val,
|
||||
const wchar_t *desc,
|
||||
array_list_t *events );
|
||||
void function_add( function_data_t *data );
|
||||
|
||||
/**
|
||||
Remove the function with the specified name.
|
||||
@@ -61,11 +96,11 @@ int function_exists( const wchar_t *name );
|
||||
/**
|
||||
Insert all function names into l. These are not copies of the
|
||||
strings and should not be freed after use.
|
||||
|
||||
|
||||
\param list the list to add the names to
|
||||
\param get_hidden whether to include hidden functions, i.e. ones starting with an underscore
|
||||
*/
|
||||
void function_get_names( array_list_t *list,
|
||||
void function_get_names( array_list_t *list,
|
||||
int get_hidden );
|
||||
|
||||
/**
|
||||
@@ -86,4 +121,20 @@ const wchar_t *function_get_definition_file( const wchar_t *name );
|
||||
*/
|
||||
int function_get_definition_offset( const wchar_t *name );
|
||||
|
||||
/**
|
||||
Returns a list of all named arguments of the specified function.
|
||||
*/
|
||||
array_list_t *function_get_named_arguments( const wchar_t *name );
|
||||
|
||||
/**
|
||||
Returns whether this function shadows variables of the underlying function
|
||||
*/
|
||||
int function_get_shadows( const wchar_t *name );
|
||||
|
||||
/**
|
||||
Creates a new function using the same definition as the specified function.
|
||||
Returns non-zero if copy is successful.
|
||||
*/
|
||||
int function_copy( const wchar_t *name, const wchar_t *new_name );
|
||||
|
||||
#endif
|
||||
|
||||
60
halloc.c
60
halloc.c
@@ -70,7 +70,7 @@ typedef struct halloc
|
||||
/**
|
||||
Memory scratch area used to fullfil smaller memory allocations
|
||||
*/
|
||||
void *scratch;
|
||||
char *scratch;
|
||||
/**
|
||||
Amount of free space in the scratch area
|
||||
*/
|
||||
@@ -78,15 +78,21 @@ typedef struct halloc
|
||||
}
|
||||
halloc_t;
|
||||
|
||||
static void *align_ptr( void *in )
|
||||
/**
|
||||
Allign the specified pointer
|
||||
*/
|
||||
static char *align_ptr( char *in )
|
||||
{
|
||||
unsigned long step = maxi(sizeof(double),sizeof(void *));
|
||||
unsigned long inc = step-1;
|
||||
unsigned long long_in = (long)in;
|
||||
unsigned long long_out = ((long_in+inc)/step)*step;
|
||||
return (void *)long_out;
|
||||
return (char *)long_out;
|
||||
}
|
||||
|
||||
/**
|
||||
Allign specifies size_t
|
||||
*/
|
||||
static size_t align_sz( size_t in )
|
||||
{
|
||||
size_t step = maxi(sizeof(double),sizeof(void *));
|
||||
@@ -119,37 +125,37 @@ static void halloc_report()
|
||||
{
|
||||
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",
|
||||
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) );
|
||||
parent_count+alloc_count, (double)alloc_spill/(parent_count+alloc_count) );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void *halloc( void *context, size_t size )
|
||||
{
|
||||
{
|
||||
halloc_t *me, *parent;
|
||||
if( context )
|
||||
{
|
||||
void *res;
|
||||
void *aligned;
|
||||
|
||||
char *res;
|
||||
char *aligned;
|
||||
|
||||
#ifdef HALLOC_DEBUG
|
||||
|
||||
|
||||
if( !child_count )
|
||||
{
|
||||
pid = getpid();
|
||||
atexit( &halloc_report );
|
||||
}
|
||||
|
||||
|
||||
child_count++;
|
||||
child_size += size;
|
||||
#endif
|
||||
#endif
|
||||
parent = halloc_from_data( context );
|
||||
|
||||
/*
|
||||
Align memory address
|
||||
Align memory address
|
||||
*/
|
||||
aligned = align_ptr( parent->scratch );
|
||||
|
||||
@@ -157,7 +163,7 @@ void *halloc( void *context, size_t size )
|
||||
|
||||
if( parent->scratch_free < 0 )
|
||||
parent->scratch_free=0;
|
||||
|
||||
|
||||
parent->scratch = aligned;
|
||||
|
||||
if( size <= parent->scratch_free )
|
||||
@@ -171,8 +177,8 @@ void *halloc( void *context, size_t size )
|
||||
|
||||
#ifdef HALLOC_DEBUG
|
||||
alloc_count++;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
if( parent->scratch_free < HALLOC_SCRAP_SIZE )
|
||||
{
|
||||
#ifdef HALLOC_DEBUG
|
||||
@@ -190,25 +196,25 @@ void *halloc( void *context, size_t size )
|
||||
if( !res )
|
||||
DIE_MEM();
|
||||
}
|
||||
al_push( &parent->children, &late_free );
|
||||
al_push_func( &parent->children, &late_free );
|
||||
al_push( &parent->children, res );
|
||||
|
||||
|
||||
}
|
||||
return res;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
me = (halloc_t *)calloc( 1, align_sz(sizeof(halloc_t)) + align_sz(size) + HALLOC_BLOCK_SIZE );
|
||||
|
||||
|
||||
if( !me )
|
||||
DIE_MEM();
|
||||
#ifdef HALLOC_DEBUG
|
||||
parent_count++;
|
||||
#endif
|
||||
#endif
|
||||
me->scratch = ((char *)me) + align_sz(sizeof(halloc_t)) + align_sz(size);
|
||||
me->scratch_free = HALLOC_BLOCK_SIZE;
|
||||
|
||||
|
||||
al_init( &me->children );
|
||||
return ((char *)me) + align_sz(sizeof(halloc_t));
|
||||
}
|
||||
@@ -219,9 +225,9 @@ void halloc_register_function( void *context, void (*func)(void *), void *data )
|
||||
halloc_t *me;
|
||||
if( !context )
|
||||
return;
|
||||
|
||||
|
||||
me = halloc_from_data( context );
|
||||
al_push( &me->children, func );
|
||||
al_push_func( &me->children, func );
|
||||
al_push( &me->children, data );
|
||||
}
|
||||
|
||||
@@ -229,11 +235,11 @@ void halloc_free( void *context )
|
||||
{
|
||||
halloc_t *me;
|
||||
int i;
|
||||
|
||||
|
||||
if( !context )
|
||||
return;
|
||||
|
||||
|
||||
|
||||
me = halloc_from_data( context );
|
||||
|
||||
#ifdef HALLOC_DEBUG
|
||||
@@ -248,7 +254,7 @@ void halloc_free( void *context )
|
||||
}
|
||||
for( i=0; i<al_get_count(&me->children); i+=2 )
|
||||
{
|
||||
void (*func)(void *) = (void (*)(void *))al_get( &me->children, i );
|
||||
void (*func)(void *) = (void (*)(void *))al_get_func( &me->children, i );
|
||||
void * data = (void *)al_get( &me->children, i+1 );
|
||||
if( func == &late_free )
|
||||
free( data );
|
||||
|
||||
2
halloc.h
2
halloc.h
@@ -1,4 +1,4 @@
|
||||
/** \file halloc.h
|
||||
/** \file halloc.h
|
||||
|
||||
A hierarchical memory allocation system. Works mostly like talloc
|
||||
used in Samba, except that an arbitrary block allocated with
|
||||
|
||||
@@ -37,7 +37,7 @@ array_list_t *al_halloc( void *context )
|
||||
if( !res )
|
||||
DIE_MEM();
|
||||
al_init( res );
|
||||
halloc_register_function( context, (void (*)(void *)) &al_destroy, res );
|
||||
halloc_register_function( context?context:res, (void (*)(void *)) &al_destroy, res );
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ string_buffer_t *sb_halloc( void *context )
|
||||
if( !res )
|
||||
DIE_MEM();
|
||||
sb_init( res );
|
||||
halloc_register_function( context, (void (*)(void *)) &sb_destroy, res );
|
||||
halloc_register_function( context?context:res, (void (*)(void *)) &sb_destroy, res );
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ void *halloc_register( void *context, void *data )
|
||||
{
|
||||
if( !data )
|
||||
return 0;
|
||||
|
||||
|
||||
halloc_register_function( context, &free, data );
|
||||
return data;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ wchar_t *halloc_wcsdup( void *context, const wchar_t *in )
|
||||
{
|
||||
size_t len=wcslen(in);
|
||||
wchar_t *out = halloc( context, sizeof( wchar_t)*(len+1));
|
||||
|
||||
|
||||
if( out == 0 )
|
||||
{
|
||||
DIE_MEM();
|
||||
@@ -95,6 +95,6 @@ wchar_t *halloc_wcsndup( void * context, const wchar_t *in, int c )
|
||||
DIE_MEM();
|
||||
}
|
||||
wcslcpy( res, in, c+1 );
|
||||
res[c] = L'\0';
|
||||
return res;
|
||||
res[c] = L'\0';
|
||||
return res;
|
||||
}
|
||||
|
||||
388
highlight.c
388
highlight.c
@@ -22,6 +22,7 @@
|
||||
#include "proc.h"
|
||||
#include "parser.h"
|
||||
#include "parse_util.h"
|
||||
#include "parser_keywords.h"
|
||||
#include "builtin.h"
|
||||
#include "function.h"
|
||||
#include "env.h"
|
||||
@@ -40,16 +41,15 @@
|
||||
*/
|
||||
#define VAR_COUNT ( sizeof(highlight_var)/sizeof(wchar_t *) )
|
||||
|
||||
static void highlight_universal_internal( wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
array_list_t *error );
|
||||
|
||||
static void highlight_universal_internal( wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
array_list_t *error );
|
||||
|
||||
/**
|
||||
The environment variables used to specify the color of different tokens.
|
||||
*/
|
||||
static wchar_t *highlight_var[] =
|
||||
static wchar_t *highlight_var[] =
|
||||
{
|
||||
L"fish_color_normal",
|
||||
L"fish_color_error",
|
||||
@@ -68,7 +68,7 @@ static wchar_t *highlight_var[] =
|
||||
;
|
||||
|
||||
/**
|
||||
Tests if the specified string is the prefix of any valid path in the system.
|
||||
Tests if the specified string is the prefix of any valid path in the system.
|
||||
|
||||
\return zero it this is not a valid prefix, non-zero otherwise
|
||||
*/
|
||||
@@ -85,15 +85,15 @@ static int is_potential_path( const wchar_t *path )
|
||||
if( tilde )
|
||||
{
|
||||
halloc_register( context, tilde );
|
||||
|
||||
|
||||
unescaped = unescape( tilde, 1 );
|
||||
if( unescaped )
|
||||
{
|
||||
|
||||
|
||||
// debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
|
||||
|
||||
|
||||
halloc_register( context, unescaped );
|
||||
|
||||
|
||||
for( in = out = unescaped; *in; in++ )
|
||||
{
|
||||
switch( *in )
|
||||
@@ -109,25 +109,25 @@ static int is_potential_path( const wchar_t *path )
|
||||
case ANY_STRING_RECURSIVE:
|
||||
{
|
||||
has_magic = 1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case INTERNAL_SEPARATOR:
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
*(out++) = *in;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
*out = 0;
|
||||
|
||||
|
||||
if( !has_magic && wcslen( unescaped ) )
|
||||
{
|
||||
int must_be_dir = 0;
|
||||
@@ -146,10 +146,10 @@ static int is_potential_path( const wchar_t *path )
|
||||
{
|
||||
wchar_t *dir_name, *base;
|
||||
struct wdirent *ent;
|
||||
|
||||
|
||||
dir_name = wdirname( halloc_wcsdup(context, unescaped) );
|
||||
base = wbasename( halloc_wcsdup(context, unescaped) );
|
||||
|
||||
base = wbasename( halloc_wcsdup(context, unescaped) );
|
||||
|
||||
if( (wcscmp( dir_name, L"/" ) == 0 ) &&
|
||||
(wcscmp( base, L"/" ) == 0 ) )
|
||||
{
|
||||
@@ -157,7 +157,7 @@ static int is_potential_path( const wchar_t *path )
|
||||
}
|
||||
else if( (dir = wopendir( dir_name )) )
|
||||
{
|
||||
|
||||
|
||||
while( (ent = wreaddir( dir )) )
|
||||
{
|
||||
if( wcsncmp( ent->d_name, base, wcslen(base) ) == 0 )
|
||||
@@ -166,19 +166,19 @@ static int is_potential_path( const wchar_t *path )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
closedir( dir );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
halloc_free( context );
|
||||
|
||||
|
||||
return res;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ int highlight_get_color( int highlight )
|
||||
int i;
|
||||
int idx=0;
|
||||
int result = 0;
|
||||
|
||||
|
||||
if( highlight < 0 )
|
||||
return FISH_COLOR_NORMAL;
|
||||
if( highlight >= (1<<VAR_COUNT) )
|
||||
@@ -202,34 +202,34 @@ int highlight_get_color( int highlight )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
wchar_t *val = env_get( highlight_var[idx]);
|
||||
|
||||
// debug( 1, L"%d -> %d -> %ls", highlight, idx, val );
|
||||
|
||||
// debug( 1, L"%d -> %d -> %ls", highlight, idx, val );
|
||||
|
||||
if( val == 0 )
|
||||
val = env_get( highlight_var[0]);
|
||||
|
||||
|
||||
if( val )
|
||||
result = output_color_code( val );
|
||||
|
||||
|
||||
if( highlight & HIGHLIGHT_VALID_PATH )
|
||||
{
|
||||
wchar_t *val2 = env_get( L"fish_color_valid_path" );
|
||||
int result2 = output_color_code( val2 );
|
||||
if( result == FISH_COLOR_NORMAL )
|
||||
result = result2;
|
||||
else
|
||||
else
|
||||
{
|
||||
if( result2 & FISH_COLOR_BOLD )
|
||||
result |= FISH_COLOR_BOLD;
|
||||
if( result2 & FISH_COLOR_UNDERLINE )
|
||||
result |= FISH_COLOR_UNDERLINE;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return result;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -240,16 +240,16 @@ static void highlight_param( const wchar_t * buff,
|
||||
int pos,
|
||||
array_list_t *error )
|
||||
{
|
||||
|
||||
|
||||
int mode = 0;
|
||||
|
||||
|
||||
int mode = 0;
|
||||
int in_pos, len = wcslen( buff );
|
||||
int bracket_count=0;
|
||||
wchar_t c;
|
||||
int normal_status = *color;
|
||||
|
||||
|
||||
for( in_pos=0;
|
||||
in_pos<len;
|
||||
in_pos<len;
|
||||
in_pos++ )
|
||||
{
|
||||
c = buff[in_pos];
|
||||
@@ -265,7 +265,7 @@ static void highlight_param( const wchar_t * buff,
|
||||
{
|
||||
int start_pos = in_pos;
|
||||
in_pos++;
|
||||
|
||||
|
||||
if( wcschr( L"~%", buff[in_pos] ) )
|
||||
{
|
||||
if( in_pos == 1 )
|
||||
@@ -282,21 +282,26 @@ static void highlight_param( const wchar_t * buff,
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
}
|
||||
else if( wcschr( L"nrtbe*?$(){}'\"<>^ \\#;|&", buff[in_pos] ) )
|
||||
else if( wcschr( L"abefnrtv*?$(){}[]'\"<>^ \\#;|&", buff[in_pos] ) )
|
||||
{
|
||||
color[start_pos]=HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+1]=normal_status;
|
||||
}
|
||||
else if( wcschr( L"c", buff[in_pos] ) )
|
||||
{
|
||||
color[start_pos]=HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+2]=normal_status;
|
||||
}
|
||||
else if( wcschr( L"uUxX01234567", buff[in_pos] ) )
|
||||
{
|
||||
int i;
|
||||
long long res=0;
|
||||
int chars=2;
|
||||
int base=16;
|
||||
|
||||
|
||||
int byte = 0;
|
||||
wchar_t max_val = ASCII_MAX;
|
||||
|
||||
|
||||
switch( buff[in_pos] )
|
||||
{
|
||||
case L'u':
|
||||
@@ -305,62 +310,62 @@ static void highlight_param( const wchar_t * buff,
|
||||
max_val = UCS2_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case L'U':
|
||||
{
|
||||
chars=8;
|
||||
max_val = WCHAR_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case L'x':
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case L'X':
|
||||
{
|
||||
byte=1;
|
||||
max_val = BYTE_MAX;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
{
|
||||
base=8;
|
||||
chars=3;
|
||||
in_pos--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for( i=0; i<chars; i++ )
|
||||
{
|
||||
int d = convert_digit( buff[++in_pos],base);
|
||||
|
||||
|
||||
if( d < 0 )
|
||||
{
|
||||
in_pos--;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
res=(res*base)|d;
|
||||
}
|
||||
|
||||
if( (res <= max_val) )
|
||||
{
|
||||
color[start_pos] = HIGHLIGHT_ESCAPE;
|
||||
color[in_pos+1] = normal_status;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
color[start_pos] = HIGHLIGHT_ERROR;
|
||||
color[in_pos+1] = normal_status;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
switch( buff[in_pos]){
|
||||
case L'~':
|
||||
@@ -376,9 +381,9 @@ static void highlight_param( const wchar_t * buff,
|
||||
|
||||
case L'$':
|
||||
{
|
||||
wchar_t n = buff[in_pos+1];
|
||||
wchar_t n = buff[in_pos+1];
|
||||
color[in_pos] = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
|
||||
color[in_pos+1] = normal_status;
|
||||
color[in_pos+1] = normal_status;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -392,21 +397,21 @@ static void highlight_param( const wchar_t * buff,
|
||||
color[in_pos+1] = normal_status;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case L'{':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_OPERATOR;
|
||||
color[in_pos+1] = normal_status;
|
||||
bracket_count++;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case L'}':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_OPERATOR;
|
||||
color[in_pos+1] = normal_status;
|
||||
bracket_count--;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
case L',':
|
||||
@@ -417,16 +422,16 @@ static void highlight_param( const wchar_t * buff,
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case L'\'':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_QUOTE;
|
||||
mode = 1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case L'\"':
|
||||
{
|
||||
color[in_pos] = HIGHLIGHT_QUOTE;
|
||||
@@ -435,7 +440,7 @@ static void highlight_param( const wchar_t * buff,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -456,21 +461,21 @@ static void highlight_param( const wchar_t * buff,
|
||||
color[in_pos+1] = HIGHLIGHT_QUOTE;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case 0:
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
if( c == L'\'' )
|
||||
{
|
||||
mode = 0;
|
||||
color[in_pos+1] = normal_status;
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -487,7 +492,7 @@ static void highlight_param( const wchar_t * buff,
|
||||
color[in_pos+1] = normal_status;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case '\\':
|
||||
{
|
||||
int start_pos = in_pos;
|
||||
@@ -497,7 +502,7 @@ static void highlight_param( const wchar_t * buff,
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
case '\\':
|
||||
case L'$':
|
||||
case '"':
|
||||
@@ -509,26 +514,40 @@ static void highlight_param( const wchar_t * buff,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case '$':
|
||||
{
|
||||
wchar_t n = buff[in_pos+1];
|
||||
color[in_pos] = (n==L'$'||wcsvarchr(n))? HIGHLIGHT_OPERATOR:HIGHLIGHT_ERROR;
|
||||
color[in_pos+1] = HIGHLIGHT_QUOTE;
|
||||
color[in_pos+1] = HIGHLIGHT_QUOTE;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int has_expand_reserved( wchar_t *str )
|
||||
{
|
||||
while( *str )
|
||||
{
|
||||
if( *str >= EXPAND_RESERVED &&
|
||||
*str <= EXPAND_RESERVED_END )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void highlight_shell( wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
|
||||
void highlight_shell( wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
array_list_t *error )
|
||||
{
|
||||
tokenizer tok;
|
||||
@@ -540,29 +559,29 @@ void highlight_shell( wchar_t * buff,
|
||||
|
||||
void *context;
|
||||
wchar_t *cmd=0;
|
||||
int accept_switches = 1;
|
||||
|
||||
int accept_switches = 1;
|
||||
|
||||
int use_function = 1;
|
||||
int use_command = 1;
|
||||
int use_builtin = 1;
|
||||
|
||||
|
||||
CHECK( buff, );
|
||||
CHECK( color, );
|
||||
|
||||
|
||||
len = wcslen(buff);
|
||||
|
||||
|
||||
if( !len )
|
||||
return;
|
||||
|
||||
|
||||
context = halloc( 0, 0 );
|
||||
|
||||
|
||||
for( i=0; buff[i] != 0; i++ )
|
||||
color[i] = -1;
|
||||
|
||||
|
||||
for( tok_init( &tok, buff, TOK_SHOW_COMMENTS );
|
||||
tok_has_next( &tok );
|
||||
tok_next( &tok ) )
|
||||
{
|
||||
{
|
||||
int last_type = tok_last_type( &tok );
|
||||
int prev_argc=0;
|
||||
|
||||
@@ -572,7 +591,7 @@ void highlight_shell( wchar_t * buff,
|
||||
{
|
||||
if( had_cmd )
|
||||
{
|
||||
|
||||
|
||||
/*Parameter */
|
||||
wchar_t *param = tok_last( &tok );
|
||||
if( param[0] == L'-' )
|
||||
@@ -597,41 +616,44 @@ void highlight_shell( wchar_t * buff,
|
||||
else
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
if( cmd && (wcscmp( cmd, L"cd" ) == 0) )
|
||||
{
|
||||
wchar_t *dir = expand_one( context,
|
||||
wcsdup(tok_last( &tok )),
|
||||
EXPAND_SKIP_CMDSUBST );
|
||||
wchar_t *dir = expand_one( context,
|
||||
wcsdup(tok_last( &tok )),
|
||||
EXPAND_SKIP_CMDSUBST );
|
||||
if( dir )
|
||||
{
|
||||
if( !path_get_cdpath( context, dir ) )
|
||||
int is_long_help = wcsncmp(dir,L"--help", wcslen(dir) );
|
||||
int is_short_help = wcsncmp(dir,L"-h", wcslen(dir) );
|
||||
|
||||
if( !is_long_help && !is_short_help && !path_get_cdpath( context, dir ) )
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
highlight_param( param,
|
||||
&color[tok_get_pos( &tok )],
|
||||
pos-tok_get_pos( &tok ),
|
||||
pos-tok_get_pos( &tok ),
|
||||
error );
|
||||
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
prev_argc=0;
|
||||
|
||||
|
||||
/*
|
||||
Command. First check that the command actually exists.
|
||||
*/
|
||||
cmd = expand_one( context,
|
||||
wcsdup(tok_last( &tok )),
|
||||
EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
|
||||
|
||||
if( cmd == 0 )
|
||||
cmd = expand_one( context,
|
||||
wcsdup(tok_last( &tok )),
|
||||
EXPAND_SKIP_CMDSUBST | EXPAND_SKIP_VARIABLES);
|
||||
|
||||
if( (cmd == 0) || has_expand_reserved( cmd ) )
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
}
|
||||
@@ -642,11 +664,11 @@ void highlight_shell( wchar_t * buff,
|
||||
int mark = tok_get_pos( &tok );
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_COMMAND;
|
||||
|
||||
if( parser_is_subcommand( cmd ) )
|
||||
if( parser_keywords_is_subcommand( cmd ) )
|
||||
{
|
||||
|
||||
|
||||
int sw;
|
||||
|
||||
|
||||
if( wcscmp( cmd, L"builtin" )==0)
|
||||
{
|
||||
use_function = 0;
|
||||
@@ -661,13 +683,13 @@ void highlight_shell( wchar_t * buff,
|
||||
}
|
||||
|
||||
tok_next( &tok );
|
||||
|
||||
sw = parser_is_switch( tok_last( &tok ) );
|
||||
|
||||
if( !parser_is_block( cmd ) &&
|
||||
|
||||
sw = parser_keywords_is_switch( tok_last( &tok ) );
|
||||
|
||||
if( !parser_keywords_is_block( cmd ) &&
|
||||
sw == ARG_SWITCH )
|
||||
{
|
||||
/*
|
||||
/*
|
||||
The 'builtin' and 'command' builtins
|
||||
are normally followed by another
|
||||
command, but if they are invoked
|
||||
@@ -685,7 +707,7 @@ void highlight_shell( wchar_t * buff,
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_PARAM;
|
||||
mark = tok_get_pos( &tok );
|
||||
}
|
||||
|
||||
|
||||
is_subcommand = 1;
|
||||
}
|
||||
tok_set_pos( &tok, mark );
|
||||
@@ -708,7 +730,7 @@ void highlight_shell( wchar_t * buff,
|
||||
*/
|
||||
if( use_builtin )
|
||||
is_cmd |= builtin_exists( cmd );
|
||||
|
||||
|
||||
if( use_function )
|
||||
is_cmd |= function_exists( cmd );
|
||||
|
||||
@@ -721,22 +743,22 @@ void highlight_shell( wchar_t * buff,
|
||||
*/
|
||||
if( use_command )
|
||||
is_cmd |= !!(tmp=path_get_path( context, cmd ));
|
||||
|
||||
/*
|
||||
|
||||
/*
|
||||
Could not find the command. Maybe it is
|
||||
a path for a implicit cd command.
|
||||
*/
|
||||
if( use_builtin || (use_function && function_exists( L"cd") ) )
|
||||
is_cmd |= !!(tmp=path_get_cdpath( context, cmd ));
|
||||
|
||||
|
||||
if( is_cmd )
|
||||
{
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_COMMAND;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( error )
|
||||
al_push( error, wcsdupcat2 ( L"Unknown command \'", cmd, L"\'", (void *)0 ));
|
||||
al_push( error, wcsdupcat ( L"Unknown command \'", cmd, L"\'" ));
|
||||
color[ tok_get_pos( &tok ) ] = (HIGHLIGHT_ERROR);
|
||||
}
|
||||
had_cmd = 1;
|
||||
@@ -744,14 +766,15 @@ void highlight_shell( wchar_t * buff,
|
||||
|
||||
if( had_cmd )
|
||||
{
|
||||
last_cmd = halloc_wcsdup( context, tok_last( &tok ) );
|
||||
last_cmd = halloc_wcsdup( context, tok_last( &tok ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case TOK_REDIRECT_NOCLOB:
|
||||
case TOK_REDIRECT_OUT:
|
||||
case TOK_REDIRECT_IN:
|
||||
case TOK_REDIRECT_APPEND:
|
||||
@@ -764,9 +787,9 @@ void highlight_shell( wchar_t * buff,
|
||||
al_push( error, wcsdup ( L"Redirection without a command" ) );
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
wchar_t *target=0;
|
||||
|
||||
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_REDIRECTION;
|
||||
tok_next( &tok );
|
||||
|
||||
@@ -780,7 +803,7 @@ void highlight_shell( wchar_t * buff,
|
||||
{
|
||||
target = expand_one( context, wcsdup( tok_last( &tok ) ), EXPAND_SKIP_CMDSUBST);
|
||||
/*
|
||||
Redirect filename may contain a cmdsubst.
|
||||
Redirect filename may contain a cmdsubst.
|
||||
If so, it will be ignored/not flagged.
|
||||
*/
|
||||
}
|
||||
@@ -791,7 +814,7 @@ void highlight_shell( wchar_t * buff,
|
||||
if( error )
|
||||
al_push( error, wcsdup ( L"Invalid redirection" ) );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if( target != 0 )
|
||||
@@ -799,7 +822,7 @@ void highlight_shell( wchar_t * buff,
|
||||
wchar_t *dir = halloc_wcsdup( context, target );
|
||||
wchar_t *dir_end = wcsrchr( dir, L'/' );
|
||||
struct stat buff;
|
||||
/*
|
||||
/*
|
||||
If file is in directory other than '.', check
|
||||
that the directory exists.
|
||||
*/
|
||||
@@ -810,29 +833,38 @@ void highlight_shell( wchar_t * buff,
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
if( error )
|
||||
al_push( error, wcsdupcat2( L"Directory \'", dir, L"\' does not exist", (void *)0 ) );
|
||||
|
||||
al_push( error, wcsdupcat( L"Directory \'", dir, L"\' does not exist" ) );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
If the file is read from or appended to, check
|
||||
if it exists.
|
||||
*/
|
||||
if( last_type == TOK_REDIRECT_IN ||
|
||||
last_type == TOK_REDIRECT_APPEND )
|
||||
if( last_type == TOK_REDIRECT_IN ||
|
||||
last_type == TOK_REDIRECT_APPEND )
|
||||
{
|
||||
if( wstat( target, &buff ) == -1 )
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
if( error )
|
||||
al_push( error, wcsdupcat2( L"File \'", target, L"\' does not exist", (void *)0 ) );
|
||||
al_push( error, wcsdupcat( L"File \'", target, L"\' does not exist" ) );
|
||||
}
|
||||
}
|
||||
if( last_type == TOK_REDIRECT_NOCLOB )
|
||||
{
|
||||
if( wstat( target, &buff ) != -1 )
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
if( error )
|
||||
al_push( error, wcsdupcat( L"File \'", target, L"\' exists" ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case TOK_PIPE:
|
||||
case TOK_BACKGROUND:
|
||||
{
|
||||
@@ -847,14 +879,14 @@ void highlight_shell( wchar_t * buff,
|
||||
}
|
||||
else
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
if( error )
|
||||
al_push( error, wcsdup ( L"No job to put in background" ) );
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case TOK_END:
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_END;
|
||||
@@ -865,13 +897,13 @@ void highlight_shell( wchar_t * buff,
|
||||
accept_switches = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case TOK_COMMENT:
|
||||
{
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_COMMENT;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case TOK_ERROR:
|
||||
default:
|
||||
{
|
||||
@@ -881,13 +913,13 @@ void highlight_shell( wchar_t * buff,
|
||||
if( error )
|
||||
al_push( error, wcsdup ( tok_last( &tok) ) );
|
||||
color[ tok_get_pos( &tok ) ] = HIGHLIGHT_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
tok_destroy( &tok );
|
||||
|
||||
/*
|
||||
Locate and syntax highlight cmdsubsts recursively
|
||||
*/
|
||||
@@ -895,32 +927,32 @@ void highlight_shell( wchar_t * buff,
|
||||
wchar_t *buffcpy = halloc_wcsdup( context, buff );
|
||||
wchar_t *subpos=buffcpy;
|
||||
int done=0;
|
||||
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
wchar_t *begin, *end;
|
||||
|
||||
if( parse_util_locate_cmdsubst( subpos,
|
||||
&begin,
|
||||
|
||||
if( parse_util_locate_cmdsubst( subpos,
|
||||
&begin,
|
||||
&end,
|
||||
1) <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( !*end )
|
||||
done=1;
|
||||
else
|
||||
*end=0;
|
||||
|
||||
|
||||
highlight_shell( begin+1, color +(begin-buffcpy)+1, -1, error );
|
||||
color[end-buffcpy]=HIGHLIGHT_OPERATOR;
|
||||
|
||||
|
||||
if( done )
|
||||
break;
|
||||
|
||||
subpos = end+1;
|
||||
|
||||
|
||||
subpos = end+1;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -943,15 +975,15 @@ void highlight_shell( wchar_t * buff,
|
||||
|
||||
if( pos >= 0 && pos <= len )
|
||||
{
|
||||
|
||||
|
||||
wchar_t *tok_begin, *tok_end;
|
||||
wchar_t *token;
|
||||
|
||||
|
||||
parse_util_token_extent( buff, pos, &tok_begin, &tok_end, 0, 0 );
|
||||
if( tok_begin && tok_end )
|
||||
{
|
||||
token = halloc_wcsndup( context, tok_begin, tok_end-tok_begin );
|
||||
|
||||
|
||||
if( is_potential_path( token ) )
|
||||
{
|
||||
for( i=tok_begin-buff; i < (tok_end-buff); i++ )
|
||||
@@ -961,7 +993,7 @@ void highlight_shell( wchar_t * buff,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
highlight_universal_internal( buff, color, pos, error );
|
||||
|
||||
@@ -977,21 +1009,21 @@ void highlight_shell( wchar_t * buff,
|
||||
}
|
||||
|
||||
halloc_free( context );
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Perform quote and parenthesis highlighting on the specified string.
|
||||
*/
|
||||
static void highlight_universal_internal( wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
static void highlight_universal_internal( wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
array_list_t *error )
|
||||
{
|
||||
|
||||
|
||||
if( (pos >= 0) && (pos < wcslen(buff)) )
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
Highlight matching quotes
|
||||
*/
|
||||
@@ -1000,14 +1032,14 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
|
||||
array_list_t l;
|
||||
al_init( &l );
|
||||
|
||||
|
||||
int level=0;
|
||||
wchar_t prev_q=0;
|
||||
|
||||
|
||||
wchar_t *str=buff;
|
||||
|
||||
int match_found=0;
|
||||
|
||||
|
||||
while(*str)
|
||||
{
|
||||
switch( *str )
|
||||
@@ -1028,7 +1060,7 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
if( prev_q == *str )
|
||||
{
|
||||
long pos1, pos2;
|
||||
|
||||
|
||||
level--;
|
||||
pos1 = al_pop_long( &l );
|
||||
pos2 = str-buff;
|
||||
@@ -1037,7 +1069,7 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
color[pos1]|=HIGHLIGHT_MATCH<<16;
|
||||
color[pos2]|=HIGHLIGHT_MATCH<<16;
|
||||
match_found = 1;
|
||||
|
||||
|
||||
}
|
||||
prev_q = *str==L'\"'?L'\'':L'\"';
|
||||
}
|
||||
@@ -1048,7 +1080,7 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
prev_q = *str;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
if( (*str == L'\0'))
|
||||
@@ -1058,7 +1090,7 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
}
|
||||
|
||||
al_destroy( &l );
|
||||
|
||||
|
||||
if( !match_found )
|
||||
color[pos] = HIGHLIGHT_ERROR<<16;
|
||||
}
|
||||
@@ -1073,7 +1105,7 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
wchar_t inc_char = buff[pos];
|
||||
int level = 0;
|
||||
wchar_t *str = &buff[pos];
|
||||
int match_found=0;
|
||||
int match_found=0;
|
||||
|
||||
while( (str >= buff) && *str)
|
||||
{
|
||||
@@ -1091,22 +1123,22 @@ static void highlight_universal_internal( wchar_t * buff,
|
||||
}
|
||||
str+= step;
|
||||
}
|
||||
|
||||
|
||||
if( !match_found )
|
||||
color[pos] = HIGHLIGHT_ERROR<<16;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void highlight_universal( wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
void highlight_universal( wchar_t * buff,
|
||||
int *color,
|
||||
int pos,
|
||||
array_list_t *error )
|
||||
{
|
||||
int i;
|
||||
|
||||
|
||||
for( i=0; buff[i]; i++ )
|
||||
color[i] = 0;
|
||||
|
||||
|
||||
highlight_universal_internal( buff, color, pos, error );
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
/**
|
||||
Internal value representing highlighting of an IO redirection
|
||||
*/
|
||||
#define HIGHLIGHT_REDIRECTION 0x800
|
||||
#define HIGHLIGHT_REDIRECTION 0x800
|
||||
/**
|
||||
Internal value representing highlighting a potentially valid path
|
||||
*/
|
||||
@@ -68,7 +68,7 @@
|
||||
for each character in buff.
|
||||
|
||||
\param buff The buffer on which to perform syntax highlighting
|
||||
\param color The array in wchich to store the color codes. The first 8 bits are used for fg color, the next 8 bits for bg color.
|
||||
\param color The array in wchich to store the color codes. The first 8 bits are used for fg color, the next 8 bits for bg color.
|
||||
\param pos the cursor position. Used for quote matching, etc.
|
||||
\param error a list in which a description of each error will be inserted. May be 0, in whcich case no error descriptions will be generated.
|
||||
*/
|
||||
@@ -80,7 +80,7 @@ void highlight_shell( wchar_t * buff, int *color, int pos, array_list_t *error )
|
||||
for each character in buff.
|
||||
|
||||
\param buff The buffer on which to perform syntax highlighting
|
||||
\param color The array in wchich to store the color codes. The first 8 bits are used for fg color, the next 8 bits for bg color.
|
||||
\param color The array in wchich to store the color codes. The first 8 bits are used for fg color, the next 8 bits for bg color.
|
||||
\param pos the cursor position. Used for quote matching, etc.
|
||||
\param error a list in which a description of each error will be inserted. May be 0, in whcich case no error descriptions will be generated.
|
||||
*/
|
||||
@@ -90,7 +90,7 @@ void highlight_universal( wchar_t * buff, int *color, int pos, array_list_t *err
|
||||
Translate from HIGHLIGHT_* to FISH_COLOR_* according to environment
|
||||
variables. Defaults to FISH_COLOR_NORMAL.
|
||||
|
||||
Example:
|
||||
Example:
|
||||
|
||||
If the environment variable FISH_FISH_COLOR_ERROR is set to 'red', a
|
||||
call to highlight_get_color( HIGHLIGHT_ERROR) will return
|
||||
|
||||
234
history.c
234
history.c
@@ -43,13 +43,13 @@
|
||||
/**
|
||||
A struct representiong a history list
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
The name of this list. Used for picking a suitable filename and for switching modes.
|
||||
*/
|
||||
const wchar_t *name;
|
||||
|
||||
|
||||
/**
|
||||
The items of the list. Each entry may be either a pointer to an
|
||||
item_t struct or a pointer to an mmaped memory region where a
|
||||
@@ -66,12 +66,12 @@ typedef struct
|
||||
this session.
|
||||
*/
|
||||
hash_table_t session_item;
|
||||
|
||||
|
||||
/**
|
||||
The current history position
|
||||
*/
|
||||
int pos;
|
||||
|
||||
|
||||
/**
|
||||
This flag is set nonzero if the file containing earlier saves has ben mmaped in
|
||||
*/
|
||||
@@ -91,7 +91,7 @@ typedef struct
|
||||
A list of indices of all previous search maches. This is used to eliminate duplicate search results.
|
||||
*/
|
||||
array_list_t used;
|
||||
|
||||
|
||||
/**
|
||||
Timestamp of last save
|
||||
*/
|
||||
@@ -114,13 +114,13 @@ typedef struct
|
||||
/**
|
||||
This struct represents a history item
|
||||
*/
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
The actual contents of the entry
|
||||
*/
|
||||
wchar_t *data;
|
||||
|
||||
|
||||
/**
|
||||
Original creation time for the entry
|
||||
*/
|
||||
@@ -154,7 +154,7 @@ static int hash_item_cmp( void *v1, void *v2 )
|
||||
{
|
||||
item_t *i1 = (item_t *)v1;
|
||||
item_t *i2 = (item_t *)v2;
|
||||
return (i1->timestamp == i2->timestamp) && (wcscmp( i1->data, i2->data )==0);
|
||||
return (i1->timestamp == i2->timestamp) && (wcscmp( i1->data, i2->data )==0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +198,7 @@ static wchar_t *history_escape_newlines( wchar_t *in )
|
||||
*/
|
||||
sb_append_char( out, L'\n' );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else if( *in == L'\n' )
|
||||
{
|
||||
@@ -209,7 +209,7 @@ static wchar_t *history_escape_newlines( wchar_t *in )
|
||||
{
|
||||
sb_append_char( out, *in );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return (wchar_t *)out->buff;
|
||||
}
|
||||
@@ -252,15 +252,18 @@ static wchar_t *history_unescape_newlines( wchar_t *in )
|
||||
return (wchar_t *)out->buff;
|
||||
}
|
||||
|
||||
/**
|
||||
Check if the specified item is already loaded
|
||||
*/
|
||||
static int item_is_new( history_mode_t *m, void *d )
|
||||
{
|
||||
{
|
||||
char *begin = (char *)d;
|
||||
|
||||
if( !m->has_loaded || !m->mmap_start || (m->mmap_start == MAP_FAILED ) )
|
||||
{
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
if( (begin < m->mmap_start) || (begin > (m->mmap_start+m->mmap_length) ) )
|
||||
{
|
||||
return 1;
|
||||
@@ -274,7 +277,7 @@ static int item_is_new( history_mode_t *m, void *d )
|
||||
Later calls to this function may erase the output of a previous call to this function.
|
||||
*/
|
||||
static item_t *item_get( history_mode_t *m, void *d )
|
||||
{
|
||||
{
|
||||
char *begin = (char *)d;
|
||||
|
||||
if( item_is_new( m, d ) )
|
||||
@@ -283,18 +286,18 @@ static item_t *item_get( history_mode_t *m, void *d )
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
char *end = m->mmap_start + m->mmap_length;
|
||||
char *pos=begin;
|
||||
|
||||
int was_backslash = 0;
|
||||
|
||||
int was_backslash = 0;
|
||||
static string_buffer_t *out = 0;
|
||||
static item_t narrow_item;
|
||||
int first_char = 1;
|
||||
int first_char = 1;
|
||||
int timestamp_mode = 0;
|
||||
|
||||
narrow_item.timestamp = 0;
|
||||
|
||||
|
||||
if( !out )
|
||||
{
|
||||
out = sb_halloc( global_context );
|
||||
@@ -307,17 +310,17 @@ static item_t *item_get( history_mode_t *m, void *d )
|
||||
{
|
||||
sb_clear( out );
|
||||
}
|
||||
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
wchar_t c;
|
||||
mbstate_t state;
|
||||
size_t res;
|
||||
|
||||
|
||||
memset( &state, 0, sizeof(state) );
|
||||
|
||||
|
||||
res = mbrtowc( &c, pos, end-pos, &state );
|
||||
|
||||
|
||||
if( res == (size_t)-1 )
|
||||
{
|
||||
pos++;
|
||||
@@ -333,7 +336,7 @@ static item_t *item_get( history_mode_t *m, void *d )
|
||||
continue;
|
||||
}
|
||||
pos += res;
|
||||
|
||||
|
||||
if( c == L'\n' )
|
||||
{
|
||||
if( timestamp_mode )
|
||||
@@ -342,21 +345,21 @@ static item_t *item_get( history_mode_t *m, void *d )
|
||||
while( *time_string && !iswdigit(*time_string))
|
||||
time_string++;
|
||||
errno=0;
|
||||
|
||||
|
||||
if( *time_string )
|
||||
{
|
||||
time_t tm;
|
||||
wchar_t *end;
|
||||
|
||||
|
||||
errno = 0;
|
||||
tm = (time_t)wcstol( time_string, &end, 10 );
|
||||
|
||||
|
||||
if( tm && !errno && !*end )
|
||||
{
|
||||
narrow_item.timestamp = tm;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
sb_clear( out );
|
||||
timestamp_mode = 0;
|
||||
@@ -365,21 +368,21 @@ static item_t *item_get( history_mode_t *m, void *d )
|
||||
if( !was_backslash )
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if( first_char )
|
||||
{
|
||||
if( c == L'#' )
|
||||
if( c == L'#' )
|
||||
timestamp_mode = 1;
|
||||
}
|
||||
|
||||
|
||||
first_char = 0;
|
||||
|
||||
|
||||
sb_append_char( out, c );
|
||||
|
||||
|
||||
was_backslash = ( (c == L'\\') && !was_backslash);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
narrow_item.data = history_unescape_newlines((wchar_t *)out->buff);
|
||||
return &narrow_item;
|
||||
}
|
||||
@@ -401,25 +404,28 @@ static int item_write( FILE *f, history_mode_t *m, void *v )
|
||||
static void history_destroy_mode( history_mode_t *m )
|
||||
{
|
||||
halloc_free( m->item_context );
|
||||
|
||||
|
||||
if( m->mmap_start && (m->mmap_start != MAP_FAILED ))
|
||||
{
|
||||
munmap( m->mmap_start, m->mmap_length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Free all memory used by specified mistory mode
|
||||
*/
|
||||
static void history_destroy_mode_wrapper( void *n, history_mode_t *m )
|
||||
{
|
||||
halloc_free( m );
|
||||
}
|
||||
|
||||
/**
|
||||
Create a new empty mode with the specified name.
|
||||
Create a new empty mode with the specified name.
|
||||
The mode is a halloc context, and the entire mode can be destroyed using halloc_free().
|
||||
*/
|
||||
static history_mode_t *history_create_mode( const wchar_t *name )
|
||||
{
|
||||
{
|
||||
history_mode_t *new_mode = halloc( 0, sizeof( history_mode_t ));
|
||||
|
||||
new_mode->name = intern(name);
|
||||
@@ -428,16 +434,16 @@ static history_mode_t *history_create_mode( const wchar_t *name )
|
||||
al_init( &new_mode->used );
|
||||
halloc_register_function( new_mode, (void (*)(void *))&al_destroy, &new_mode->item );
|
||||
halloc_register_function( new_mode, (void (*)(void *))&al_destroy, &new_mode->used );
|
||||
|
||||
|
||||
hash_init( &new_mode->session_item, &hash_item_func, &hash_item_cmp );
|
||||
halloc_register_function( new_mode, (void (*)(void *))&hash_destroy, &new_mode->session_item );
|
||||
|
||||
|
||||
new_mode->save_timestamp=time(0);
|
||||
new_mode->item_context = halloc( 0,0 );
|
||||
|
||||
halloc_register_function( new_mode, (void (*)(void *))&history_destroy_mode, new_mode );
|
||||
|
||||
return new_mode;
|
||||
return new_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -458,17 +464,17 @@ static int history_test( const wchar_t *needle, const wchar_t *haystack )
|
||||
static wchar_t *history_filename( void *context, const wchar_t *name, const wchar_t *suffix )
|
||||
{
|
||||
wchar_t *path;
|
||||
wchar_t *res;
|
||||
wchar_t *res;
|
||||
|
||||
if( !current_mode )
|
||||
return 0;
|
||||
|
||||
|
||||
path = path_get_config( context );
|
||||
|
||||
if( !path )
|
||||
return 0;
|
||||
|
||||
res = wcsdupcat2( path, L"/", name, L"_history", suffix?suffix:(void *)0, (void *)0 );
|
||||
|
||||
res = wcsdupcat( path, L"/", name, L"_history", suffix?suffix:(void *)0);
|
||||
halloc_register_function( context, &free, res );
|
||||
return res;
|
||||
}
|
||||
@@ -477,24 +483,24 @@ static wchar_t *history_filename( void *context, const wchar_t *name, const wcha
|
||||
Go through the mmaped region and insert pointers to suitable loacations into the item list
|
||||
*/
|
||||
static void history_populate_from_mmap( history_mode_t *m )
|
||||
{
|
||||
{
|
||||
char *begin = m->mmap_start;
|
||||
char *end = begin + m->mmap_length;
|
||||
char *pos;
|
||||
|
||||
|
||||
array_list_t old_item;
|
||||
array_list_t session_item_list;
|
||||
int ignore_newline = 0;
|
||||
int do_push = 1;
|
||||
|
||||
|
||||
al_init( &old_item );
|
||||
al_init( &session_item_list );
|
||||
al_push_all( &old_item, &m->item );
|
||||
al_truncate( &m->item, 0 );
|
||||
|
||||
|
||||
for( pos = begin; pos <end; pos++ )
|
||||
{
|
||||
|
||||
|
||||
if( do_push )
|
||||
{
|
||||
item_t *i;
|
||||
@@ -503,14 +509,14 @@ static void history_populate_from_mmap( history_mode_t *m )
|
||||
ignore_newline = *pos == '#';
|
||||
|
||||
i = item_get( m, pos );
|
||||
|
||||
|
||||
if( (i_orig=hash_get( ¤t_mode->session_item, i ) ) )
|
||||
{
|
||||
/*
|
||||
This item comes from this session. Insert the
|
||||
original item at the end of the item list.
|
||||
*/
|
||||
al_push( &session_item_list, i_orig );
|
||||
al_push( &session_item_list, i_orig );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -519,10 +525,10 @@ static void history_populate_from_mmap( history_mode_t *m )
|
||||
*/
|
||||
al_push( &m->item, pos );
|
||||
}
|
||||
|
||||
|
||||
do_push = 0;
|
||||
}
|
||||
|
||||
|
||||
switch( *pos )
|
||||
{
|
||||
case '\\':
|
||||
@@ -530,7 +536,7 @@ static void history_populate_from_mmap( history_mode_t *m )
|
||||
pos++;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case '\n':
|
||||
{
|
||||
if( ignore_newline )
|
||||
@@ -540,12 +546,12 @@ static void history_populate_from_mmap( history_mode_t *m )
|
||||
else
|
||||
{
|
||||
do_push = 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
al_push_all( &m->item, &session_item_list );
|
||||
m->pos += al_get_count( &m->item );
|
||||
al_push_all( &m->item, &old_item );
|
||||
@@ -562,20 +568,20 @@ static void history_load( history_mode_t *m )
|
||||
{
|
||||
int fd;
|
||||
int ok=0;
|
||||
|
||||
|
||||
void *context;
|
||||
wchar_t *filename;
|
||||
|
||||
if( !m )
|
||||
return;
|
||||
|
||||
return;
|
||||
|
||||
m->has_loaded=1;
|
||||
|
||||
signal_block();
|
||||
|
||||
context = halloc( 0, 0 );
|
||||
filename = history_filename( context, m->name, 0 );
|
||||
|
||||
|
||||
if( filename )
|
||||
{
|
||||
if( ( fd = wopen( filename, O_RDONLY ) ) > 0 )
|
||||
@@ -596,7 +602,7 @@ static void history_load( history_mode_t *m )
|
||||
close( fd );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
halloc_free( context );
|
||||
signal_unblock();
|
||||
}
|
||||
@@ -627,12 +633,12 @@ static void history_save_mode( void *n, history_mode_t *m )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( !has_new )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
signal_block();
|
||||
|
||||
/*
|
||||
@@ -641,19 +647,19 @@ static void history_save_mode( void *n, history_mode_t *m )
|
||||
*/
|
||||
on_disk = history_create_mode( m->name );
|
||||
history_load( on_disk );
|
||||
|
||||
|
||||
tmp_name = history_filename( on_disk, m->name, L".tmp" );
|
||||
|
||||
if( tmp_name )
|
||||
{
|
||||
tmp_name = wcsdup(tmp_name );
|
||||
|
||||
|
||||
if( (out=wfopen( tmp_name, "w" ) ) )
|
||||
{
|
||||
hash_table_t mine;
|
||||
|
||||
|
||||
hash_init( &mine, &hash_item_func, &hash_item_cmp );
|
||||
|
||||
|
||||
for( i=0; i<al_get_count(&m->item); i++ )
|
||||
{
|
||||
void *ptr = al_get( &m->item, i );
|
||||
@@ -663,7 +669,7 @@ static void history_save_mode( void *n, history_mode_t *m )
|
||||
hash_put( &mine, item_get( m, ptr ), L"" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Re-save the old history
|
||||
*/
|
||||
@@ -679,14 +685,14 @@ static void history_save_mode( void *n, history_mode_t *m )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
hash_destroy( &mine );
|
||||
|
||||
|
||||
/*
|
||||
Add our own items last
|
||||
*/
|
||||
*/
|
||||
for( i=0; ok && (i<al_get_count(&m->item)); i++ )
|
||||
{
|
||||
void *ptr = al_get( &m->item, i );
|
||||
@@ -694,12 +700,12 @@ static void history_save_mode( void *n, history_mode_t *m )
|
||||
if( is_new )
|
||||
{
|
||||
if( item_write( out, m, ptr ) == -1 )
|
||||
{
|
||||
{
|
||||
ok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( fclose( out ) || !ok )
|
||||
{
|
||||
/*
|
||||
@@ -714,8 +720,8 @@ static void history_save_mode( void *n, history_mode_t *m )
|
||||
}
|
||||
}
|
||||
free( tmp_name );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
halloc_free( on_disk);
|
||||
|
||||
if( ok )
|
||||
@@ -727,23 +733,23 @@ static void history_save_mode( void *n, history_mode_t *m )
|
||||
hash table. On reload, they will be automatically inserted at
|
||||
the end of the history list.
|
||||
*/
|
||||
|
||||
|
||||
if( m->mmap_start && (m->mmap_start != MAP_FAILED ) )
|
||||
{
|
||||
munmap( m->mmap_start, m->mmap_length );
|
||||
}
|
||||
|
||||
|
||||
al_truncate( &m->item, 0 );
|
||||
al_truncate( &m->used, 0 );
|
||||
m->pos = 0;
|
||||
m->has_loaded = 0;
|
||||
m->mmap_start=0;
|
||||
m->mmap_length=0;
|
||||
|
||||
|
||||
m->save_timestamp=time(0);
|
||||
m->new_count = 0;
|
||||
}
|
||||
|
||||
|
||||
signal_unblock();
|
||||
}
|
||||
|
||||
@@ -751,27 +757,27 @@ static void history_save_mode( void *n, history_mode_t *m )
|
||||
void history_add( const wchar_t *str )
|
||||
{
|
||||
item_t *i;
|
||||
|
||||
|
||||
if( !current_mode )
|
||||
return;
|
||||
|
||||
|
||||
i = halloc( current_mode->item_context, sizeof(item_t));
|
||||
i->data = (wchar_t *)halloc_wcsdup( current_mode->item_context, str );
|
||||
i->timestamp = time(0);
|
||||
|
||||
|
||||
al_push( ¤t_mode->item, i );
|
||||
hash_put( ¤t_mode->session_item, i, i );
|
||||
|
||||
|
||||
al_truncate( ¤t_mode->used, 0 );
|
||||
current_mode->pos = al_get_count( ¤t_mode->item );
|
||||
|
||||
current_mode->new_count++;
|
||||
|
||||
|
||||
if( (time(0) > current_mode->save_timestamp+SAVE_INTERVAL) || (current_mode->new_count >= SAVE_COUNT) )
|
||||
{
|
||||
history_save_mode( 0, current_mode );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -790,9 +796,9 @@ static int history_is_used( const wchar_t *str )
|
||||
if( wcscmp( it->data, str ) == 0 )
|
||||
{
|
||||
res = 1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -807,11 +813,11 @@ const wchar_t *history_prev_match( const wchar_t *needle )
|
||||
{
|
||||
item_t *i = item_get( current_mode, al_get( ¤t_mode->item, current_mode->pos ) );
|
||||
wchar_t *haystack = (wchar_t *)i->data;
|
||||
|
||||
|
||||
if( history_test( needle, haystack ) )
|
||||
{
|
||||
int is_used;
|
||||
|
||||
|
||||
/*
|
||||
This is ugly. Whenever we call item_get(),
|
||||
there is a chance that the return value of any
|
||||
@@ -823,11 +829,11 @@ const wchar_t *history_prev_match( const wchar_t *needle )
|
||||
*/
|
||||
|
||||
haystack = wcsdup(haystack );
|
||||
|
||||
|
||||
is_used = history_is_used( haystack );
|
||||
|
||||
|
||||
free( haystack );
|
||||
|
||||
|
||||
if( !is_used )
|
||||
{
|
||||
i = item_get( current_mode, al_get( ¤t_mode->item, current_mode->pos ) );
|
||||
@@ -837,7 +843,7 @@ const wchar_t *history_prev_match( const wchar_t *needle )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( !current_mode->has_loaded )
|
||||
{
|
||||
/*
|
||||
@@ -858,9 +864,9 @@ const wchar_t *history_prev_match( const wchar_t *needle )
|
||||
if( al_peek_long( ¤t_mode->used ) != -1 )
|
||||
al_push_long( ¤t_mode->used, -1 );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return needle;
|
||||
}
|
||||
|
||||
@@ -871,7 +877,7 @@ wchar_t *history_get( int idx )
|
||||
|
||||
if( !current_mode )
|
||||
return 0;
|
||||
|
||||
|
||||
len = al_get_count( ¤t_mode->item );
|
||||
|
||||
if( (idx >= len ) && !current_mode->has_loaded )
|
||||
@@ -879,13 +885,13 @@ wchar_t *history_get( int idx )
|
||||
history_load( current_mode );
|
||||
len = al_get_count( ¤t_mode->item );
|
||||
}
|
||||
|
||||
|
||||
if( idx < 0 )
|
||||
return 0;
|
||||
|
||||
|
||||
if( idx >= len )
|
||||
return 0;
|
||||
|
||||
|
||||
return item_get( current_mode, al_get( ¤t_mode->item, len - 1 - idx ) )->data;
|
||||
}
|
||||
|
||||
@@ -897,9 +903,9 @@ void history_first()
|
||||
{
|
||||
history_load( current_mode );
|
||||
}
|
||||
|
||||
|
||||
current_mode->pos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void history_reset()
|
||||
@@ -911,7 +917,7 @@ void history_reset()
|
||||
Clear list of search matches
|
||||
*/
|
||||
al_truncate( ¤t_mode->used, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const wchar_t *history_next_match( const wchar_t *needle)
|
||||
@@ -933,7 +939,7 @@ const wchar_t *history_next_match( const wchar_t *needle)
|
||||
return i->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
The used-list is empty. Set position to 'past end of list'
|
||||
and return the search string.
|
||||
@@ -941,7 +947,7 @@ const wchar_t *history_next_match( const wchar_t *needle)
|
||||
current_mode->pos = al_get_count( ¤t_mode->item );
|
||||
|
||||
}
|
||||
return needle;
|
||||
return needle;
|
||||
}
|
||||
|
||||
|
||||
@@ -950,16 +956,16 @@ void history_set_mode( const wchar_t *name )
|
||||
if( !mode_table )
|
||||
{
|
||||
mode_table = malloc( sizeof(hash_table_t ));
|
||||
hash_init( mode_table, &hash_wcs_func, &hash_wcs_cmp );
|
||||
hash_init( mode_table, &hash_wcs_func, &hash_wcs_cmp );
|
||||
}
|
||||
|
||||
|
||||
current_mode = (history_mode_t *)hash_get( mode_table, name );
|
||||
|
||||
|
||||
if( !current_mode )
|
||||
{
|
||||
current_mode = history_create_mode( name );
|
||||
hash_put( mode_table, name, current_mode );
|
||||
}
|
||||
hash_put( mode_table, name, current_mode );
|
||||
}
|
||||
}
|
||||
|
||||
void history_init()
|
||||
|
||||
@@ -50,7 +50,7 @@ void history_reset();
|
||||
|
||||
/**
|
||||
Find next history item starting with str. If this moves past
|
||||
the end of the history, str is returned.
|
||||
the end of the history, str is returned.
|
||||
*/
|
||||
const wchar_t *history_next_match( const wchar_t *str);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user