summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.editorconfig4
-rw-r--r--.gitignore2
-rw-r--r--ChangeLog1811
-rw-r--r--Completion/BSD/Command/_kld2
-rw-r--r--Completion/BSD/Command/_mixerctl11
-rw-r--r--Completion/BSD/Command/_portsnap2
-rw-r--r--Completion/BSD/Type/_jails5
-rw-r--r--Completion/Base/Completer/_expand2
-rw-r--r--Completion/Base/Completer/_external_pwds39
-rw-r--r--Completion/Base/Completer/_history7
-rw-r--r--Completion/Base/Core/_main_complete38
-rw-r--r--Completion/Base/Utility/_arguments2
-rw-r--r--Completion/Base/Utility/_call_program4
-rw-r--r--Completion/Base/Utility/_describe35
-rw-r--r--Completion/Base/Utility/_sequence22
-rw-r--r--Completion/Base/Utility/_store_cache11
-rw-r--r--Completion/Base/Widget/_complete_debug2
-rw-r--r--Completion/Darwin/Command/_defaults3
-rw-r--r--Completion/Darwin/Command/_fink7
-rw-r--r--Completion/Debian/Command/_apt1
-rw-r--r--Completion/Debian/Command/_apt-file100
-rw-r--r--Completion/Debian/Command/_apt-move7
-rw-r--r--Completion/Debian/Command/_bts8
-rw-r--r--Completion/Debian/Command/_dak31
-rw-r--r--Completion/Debian/Command/_dchroot8
-rw-r--r--Completion/Debian/Command/_dchroot-dsa8
-rw-r--r--Completion/Debian/Command/_dpkg-buildpackage2
-rw-r--r--Completion/Debian/Command/_dpkg-repack2
-rw-r--r--Completion/Debian/Command/_lintian2
-rw-r--r--Completion/Debian/Command/_madison2
-rw-r--r--Completion/Debian/Command/_make-kpkg6
-rw-r--r--Completion/Debian/Command/_pbuilder4
-rw-r--r--Completion/Debian/Command/_reprepro25
-rw-r--r--Completion/Debian/Command/_svn-buildpackage4
-rw-r--r--Completion/Debian/Command/_update-alternatives2
-rw-r--r--Completion/Debian/Command/_vim-addons65
-rw-r--r--Completion/Debian/Type/_deb_architectures9
-rw-r--r--Completion/Linux/Command/_docker410
-rw-r--r--Completion/Linux/Command/_modutils2
-rw-r--r--Completion/Linux/Command/_qdbus114
-rw-r--r--Completion/Linux/Command/_strace1
-rw-r--r--Completion/Linux/Command/_sysstat77
-rw-r--r--Completion/Mandriva/Command/_rebootin36
-rw-r--r--Completion/Mandriva/Command/_urpmi47
-rw-r--r--Completion/Redhat/Command/_rpm29
-rw-r--r--Completion/Redhat/Command/_yum10
-rw-r--r--Completion/Solaris/Command/_beadm135
-rw-r--r--Completion/Solaris/Command/_gcore31
-rw-r--r--Completion/Solaris/Command/_ps77
-rw-r--r--Completion/Solaris/Command/_ptree26
-rw-r--r--Completion/Solaris/Type/_be_name17
-rw-r--r--Completion/Solaris/Type/_zones8
-rw-r--r--Completion/Unix/Command/_adb1
-rw-r--r--Completion/Unix/Command/_arp8
-rw-r--r--Completion/Unix/Command/_at12
-rw-r--r--Completion/Unix/Command/_bittorrent24
-rw-r--r--Completion/Unix/Command/_bogofilter20
-rw-r--r--Completion/Unix/Command/_bpython12
-rw-r--r--Completion/Unix/Command/_bzr64
-rw-r--r--Completion/Unix/Command/_cabal9
-rw-r--r--Completion/Unix/Command/_cdrdao246
-rw-r--r--Completion/Unix/Command/_chmod48
-rw-r--r--Completion/Unix/Command/_chown25
-rw-r--r--Completion/Unix/Command/_cmp33
-rw-r--r--Completion/Unix/Command/_comm17
-rw-r--r--Completion/Unix/Command/_cp75
-rw-r--r--Completion/Unix/Command/_cpio27
-rw-r--r--Completion/Unix/Command/_cut78
-rw-r--r--Completion/Unix/Command/_cvs13
-rw-r--r--Completion/Unix/Command/_date23
-rw-r--r--Completion/Unix/Command/_df23
-rw-r--r--Completion/Unix/Command/_django25
-rw-r--r--Completion/Unix/Command/_du83
-rw-r--r--Completion/Unix/Command/_ecasound28
-rw-r--r--Completion/Unix/Command/_elfdump47
-rw-r--r--Completion/Unix/Command/_ffmpeg36
-rw-r--r--Completion/Unix/Command/_find201
-rw-r--r--Completion/Unix/Command/_fuser94
-rw-r--r--Completion/Unix/Command/_gcc4
-rw-r--r--Completion/Unix/Command/_gcore50
-rwxr-xr-xCompletion/Unix/Command/_getent2
-rw-r--r--Completion/Unix/Command/_git273
-rw-r--r--Completion/Unix/Command/_global16
-rw-r--r--Completion/Unix/Command/_gpg126
-rw-r--r--Completion/Unix/Command/_grep2
-rw-r--r--Completion/Unix/Command/_hg25
-rw-r--r--Completion/Unix/Command/_iconv29
-rw-r--r--Completion/Unix/Command/_id60
-rw-r--r--Completion/Unix/Command/_ip10
-rw-r--r--Completion/Unix/Command/_join46
-rw-r--r--Completion/Unix/Command/_last66
-rw-r--r--Completion/Unix/Command/_ldd41
-rw-r--r--Completion/Unix/Command/_less8
-rw-r--r--Completion/Unix/Command/_lha51
-rw-r--r--Completion/Unix/Command/_ln27
-rw-r--r--Completion/Unix/Command/_ls44
-rw-r--r--Completion/Unix/Command/_lsof48
-rw-r--r--Completion/Unix/Command/_mail6
-rw-r--r--Completion/Unix/Command/_make12
-rw-r--r--Completion/Unix/Command/_md5sum5
-rw-r--r--Completion/Unix/Command/_metaflac25
-rw-r--r--Completion/Unix/Command/_mkdir66
-rw-r--r--Completion/Unix/Command/_module8
-rw-r--r--Completion/Unix/Command/_monotone36
-rw-r--r--Completion/Unix/Command/_mosh3
-rw-r--r--Completion/Unix/Command/_mount24
-rw-r--r--Completion/Unix/Command/_mpc18
-rw-r--r--Completion/Unix/Command/_mtr10
-rw-r--r--Completion/Unix/Command/_mysqldiff3
-rw-r--r--Completion/Unix/Command/_netcat19
-rw-r--r--Completion/Unix/Command/_nl40
-rw-r--r--Completion/Unix/Command/_nm53
-rw-r--r--Completion/Unix/Command/_notmuch5
-rw-r--r--Completion/Unix/Command/_od28
-rw-r--r--Completion/Unix/Command/_patch4
-rw-r--r--Completion/Unix/Command/_pgrep4
-rw-r--r--Completion/Unix/Command/_ping34
-rw-r--r--Completion/Unix/Command/_pkg-config24
-rw-r--r--Completion/Unix/Command/_prove6
-rw-r--r--Completion/Unix/Command/_ps188
-rw-r--r--Completion/Unix/Command/_pydoc42
-rw-r--r--Completion/Unix/Command/_python15
-rw-r--r--Completion/Unix/Command/_rar10
-rw-r--r--Completion/Unix/Command/_readelf62
-rw-r--r--Completion/Unix/Command/_ri4
-rw-r--r--Completion/Unix/Command/_rm15
-rw-r--r--Completion/Unix/Command/_rsync4
-rw-r--r--Completion/Unix/Command/_rubber45
-rw-r--r--Completion/Unix/Command/_ruby2
-rw-r--r--Completion/Unix/Command/_runit73
-rw-r--r--Completion/Unix/Command/_sablotron16
-rw-r--r--Completion/Unix/Command/_screen31
-rw-r--r--Completion/Unix/Command/_sed42
-rw-r--r--Completion/Unix/Command/_sh3
-rw-r--r--Completion/Unix/Command/_sort107
-rw-r--r--Completion/Unix/Command/_stgit4
-rw-r--r--Completion/Unix/Command/_strip10
-rw-r--r--Completion/Unix/Command/_su21
-rw-r--r--Completion/Unix/Command/_sudo65
-rw-r--r--Completion/Unix/Command/_systemd4
-rw-r--r--Completion/Unix/Command/_telnet24
-rw-r--r--Completion/Unix/Command/_tidy4
-rw-r--r--Completion/Unix/Command/_tmux13
-rw-r--r--Completion/Unix/Command/_uname116
-rw-r--r--Completion/Unix/Command/_uniq4
-rw-r--r--Completion/Unix/Command/_user_admin1
-rw-r--r--Completion/Unix/Command/_vcsh88
-rw-r--r--Completion/Unix/Command/_vim2
-rw-r--r--Completion/Unix/Command/_wc26
-rw-r--r--Completion/Unix/Command/_xargs74
-rw-r--r--Completion/Unix/Command/_xxd45
-rw-r--r--Completion/Unix/Command/_zpool13
-rw-r--r--Completion/Unix/Type/_cmdstring6
-rw-r--r--Completion/Unix/Type/_diff_options13
-rw-r--r--Completion/Unix/Type/_directories2
-rw-r--r--Completion/Unix/Type/_file_systems17
-rw-r--r--Completion/Unix/Type/_files6
-rw-r--r--Completion/Unix/Type/_find_net_interfaces42
-rw-r--r--Completion/Unix/Type/_net_interfaces41
-rw-r--r--Completion/Unix/Type/_path_files9
-rw-r--r--Completion/Unix/Type/_pdf2
-rw-r--r--Completion/Unix/Type/_perl_modules2
-rw-r--r--Completion/Unix/Type/_pids2
-rw-r--r--Completion/Unix/Type/_python_modules44
-rw-r--r--Completion/Unix/Type/_users4
-rw-r--r--Completion/X/Command/_rdesktop71
-rw-r--r--Completion/X/Command/_urxvt4
-rw-r--r--Completion/X/Command/_x_utils31
-rw-r--r--Completion/X/Command/_xautolock25
-rw-r--r--Completion/Zsh/Command/_bindkey1
-rw-r--r--Completion/Zsh/Command/_command15
-rw-r--r--Completion/Zsh/Command/_emulate6
-rw-r--r--Completion/Zsh/Command/_fc86
-rw-r--r--Completion/Zsh/Command/_tcpsys18
-rw-r--r--Completion/Zsh/Command/_typeset2
-rw-r--r--Completion/Zsh/Command/_unhash11
-rw-r--r--Completion/Zsh/Command/_which3
-rw-r--r--Completion/Zsh/Command/_zattr9
-rw-r--r--Completion/Zsh/Command/_zle8
-rw-r--r--Completion/Zsh/Command/_zmodload42
-rw-r--r--Completion/Zsh/Command/_zstyle47
-rw-r--r--Completion/Zsh/Context/_brace_parameter110
-rw-r--r--Completion/Zsh/Context/_subscript2
-rw-r--r--Completion/Zsh/Function/_add-zsh-hook24
-rw-r--r--Completion/Zsh/Function/_zcalc7
-rw-r--r--Completion/Zsh/Type/_globflags11
-rw-r--r--Completion/Zsh/Type/_globquals2
-rw-r--r--Completion/Zsh/Type/_history_modifiers1
-rw-r--r--Completion/compaudit1
-rw-r--r--Completion/compinit11
-rw-r--r--Completion/compinstall15
-rw-r--r--Completion/openSUSE/Command/_SUSEconfig24
-rw-r--r--Completion/openSUSE/Command/_yast (renamed from Completion/Linux/Command/_yast)7
-rw-r--r--Completion/openSUSE/Command/_yast230
-rw-r--r--Config/version.mk4
-rw-r--r--Doc/META-FAQ.yo1
-rw-r--r--Doc/Makefile.in2
-rw-r--r--Doc/Zsh/arith.yo12
-rw-r--r--Doc/Zsh/builtins.yo230
-rw-r--r--Doc/Zsh/calsys.yo35
-rw-r--r--Doc/Zsh/compsys.yo100
-rw-r--r--Doc/Zsh/contrib.yo143
-rw-r--r--Doc/Zsh/expn.yo22
-rw-r--r--Doc/Zsh/ftp_sites.yo14
-rw-r--r--Doc/Zsh/func.yo8
-rw-r--r--Doc/Zsh/grammar.yo49
-rw-r--r--Doc/Zsh/manual.yo9
-rw-r--r--Doc/Zsh/metafaq.yo18
-rw-r--r--Doc/Zsh/mod_datetime.yo55
-rw-r--r--Doc/Zsh/mod_db_gdbm.yo51
-rw-r--r--Doc/Zsh/mod_files.yo5
-rw-r--r--Doc/Zsh/mod_system.yo3
-rw-r--r--Doc/Zsh/options.yo51
-rw-r--r--Doc/Zsh/params.yo210
-rw-r--r--Doc/Zsh/prompt.yo11
-rw-r--r--Doc/Zsh/roadmap.yo6
-rw-r--r--Doc/Zsh/zle.yo221
-rw-r--r--Doc/zman.yo1
-rw-r--r--Doc/ztexi.yo1
-rw-r--r--Etc/FAQ.yo59
-rw-r--r--Etc/zsh-development-guide11
-rw-r--r--Functions/Calendar/after67
-rw-r--r--Functions/Calendar/before67
-rw-r--r--Functions/Calendar/calendar4
-rw-r--r--Functions/Misc/run-help-ip42
-rw-r--r--Functions/Misc/tetriscurses386
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_git18
-rw-r--r--Functions/VCS_Info/Backends/VCS_INFO_get_data_hg17
-rw-r--r--Functions/VCS_Info/VCS_INFO_quilt30
-rw-r--r--Functions/VCS_Info/vcs_info1
-rw-r--r--Functions/Zftp/zfcd_match8
-rw-r--r--Functions/Zftp/zfcget11
-rw-r--r--Functions/Zftp/zfcput10
-rw-r--r--Functions/Zftp/zffcache5
-rw-r--r--Functions/Zftp/zfget_match9
-rw-r--r--Functions/Zftp/zfrglob15
-rw-r--r--Functions/Zftp/zftransfer9
-rw-r--r--Functions/Zftp/zftype6
-rw-r--r--Functions/Zftp/zfuget15
-rw-r--r--Functions/Zftp/zfuput15
-rw-r--r--Functions/Zle/edit-command-line12
-rw-r--r--NEWS72
-rw-r--r--README102
-rw-r--r--Src/Builtins/rlimits.c2
-rw-r--r--Src/Builtins/sched.c2
-rw-r--r--Src/Modules/attr.c67
-rw-r--r--Src/Modules/datetime.c21
-rw-r--r--Src/Modules/db_gdbm.c184
-rw-r--r--Src/Modules/langinfo.c3
-rw-r--r--Src/Modules/tcp.c4
-rw-r--r--Src/Modules/zftp.c1
-rw-r--r--Src/Modules/zpty.c6
-rw-r--r--Src/Modules/zselect.c2
-rw-r--r--Src/Modules/zutil.c8
-rw-r--r--Src/Zle/compcore.c8
-rw-r--r--Src/Zle/compctl.c26
-rw-r--r--Src/Zle/complist.c28
-rw-r--r--Src/Zle/compmatch.c3
-rw-r--r--Src/Zle/compresult.c7
-rw-r--r--Src/Zle/computil.c3
-rw-r--r--Src/Zle/iwidgets.list55
-rw-r--r--Src/Zle/textobjects.c322
-rw-r--r--Src/Zle/zle.h21
-rw-r--r--Src/Zle/zle.mdd3
-rw-r--r--Src/Zle/zle_bindings.c10
-rw-r--r--Src/Zle/zle_hist.c28
-rw-r--r--Src/Zle/zle_keymap.c59
-rw-r--r--Src/Zle/zle_main.c72
-rw-r--r--Src/Zle/zle_misc.c238
-rw-r--r--Src/Zle/zle_move.c61
-rw-r--r--Src/Zle/zle_params.c2
-rw-r--r--Src/Zle/zle_refresh.c26
-rw-r--r--Src/Zle/zle_tricky.c62
-rw-r--r--Src/Zle/zle_utils.c105
-rw-r--r--Src/Zle/zle_vi.c411
-rw-r--r--Src/Zle/zle_word.c113
-rw-r--r--Src/builtin.c297
-rw-r--r--Src/compat.c17
-rw-r--r--Src/context.c116
-rw-r--r--Src/exec.c239
-rw-r--r--Src/glob.c27
-rw-r--r--Src/hashtable.c14
-rw-r--r--Src/hist.c357
-rw-r--r--Src/init.c70
-rw-r--r--Src/input.c99
-rw-r--r--Src/jobs.c180
-rw-r--r--Src/lex.c770
-rw-r--r--Src/linklist.c4
-rw-r--r--Src/loop.c51
-rw-r--r--Src/math.c60
-rw-r--r--Src/mem.c4
-rw-r--r--Src/module.c9
-rw-r--r--Src/options.c12
-rw-r--r--Src/params.c74
-rw-r--r--Src/parse.c152
-rw-r--r--Src/pattern.c2
-rw-r--r--Src/prompt.c9
-rw-r--r--Src/signals.c46
-rw-r--r--Src/sort.c2
-rw-r--r--Src/subst.c120
-rw-r--r--Src/text.c19
-rw-r--r--Src/utils.c240
-rw-r--r--Src/watch.c27
-rw-r--r--Src/zsh.h158
-rw-r--r--Src/zsh.mdd14
-rw-r--r--Src/ztype.h6
-rw-r--r--Test/A02alias.ztst39
-rw-r--r--Test/A04redirect.ztst34
-rw-r--r--Test/A05execution.ztst46
-rw-r--r--Test/A06assign.ztst38
-rw-r--r--Test/A07control.ztst53
-rw-r--r--Test/B02typeset.ztst17
-rw-r--r--Test/B06fc.ztst14
-rw-r--r--Test/B07emulate.ztst4
-rw-r--r--Test/C01arith.ztst103
-rw-r--r--Test/C02cond.ztst38
-rw-r--r--Test/C04funcdef.ztst12
-rw-r--r--Test/D02glob.ztst2
-rw-r--r--Test/D04parameter.ztst65
-rw-r--r--Test/D07multibyte.ztst20
-rw-r--r--Test/D08cmdsubst.ztst42
-rw-r--r--Test/E01options.ztst39
-rw-r--r--Test/V07pcre.ztst4
-rw-r--r--Test/V08zpty.ztst3
-rw-r--r--Test/W01history.ztst60
-rw-r--r--Test/X02zlevi.ztst491
-rw-r--r--Test/Y01completion.ztst4
-rw-r--r--Test/Y02compmatch.ztst4
-rw-r--r--Test/Y03arguments.ztst4
-rw-r--r--Test/comptest16
-rw-r--r--configure.ac58
331 files changed, 12133 insertions, 4423 deletions
diff --git a/.editorconfig b/.editorconfig
index 145dc3740..808512ec0 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -6,6 +6,10 @@ root = true
end_of_line = lf
tab_width = 8
indent_size = 2
+indent_style = tab
+
+[ChangeLog]
+indent_size = 8
[*.[ch]]
indent_size = 4
diff --git a/.gitignore b/.gitignore
index 4ae315baa..08f90a29e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -102,6 +102,7 @@ Src/tags
Src/TAGS
Src/version.h
Src/zsh
+Src/zsh.exe
Src/zshcurses.h
Src/zshpaths.h
Src/zshterm.h
@@ -149,3 +150,4 @@ Src/Zle/zle_things.h
Src/Zle/zle_widget.h
Test/*.tmp
+/.project
diff --git a/ChangeLog b/ChangeLog
index 2d25d1d6b..afcb1a034 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,7 +1,1810 @@
+2015-05-05 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: Config/version.mk, Etc/FAQ.yo: update for
+ 5.0.7-dev-2, including updated FAQ source for newer YODL.
+
+ * 35032: Src/jobs.c: update job status with process status if
+ process detected as continued.
+
+2015-05-05 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted: fix descriptions in previous commit (cosmetic).
+
+ * 35033: Completion/Zsh/Function/_zcalc: trivial completion.
+
+2015-05-04 Oliver Kiddle <opk@zsh.org>
+
+ * 35029: Src/Zle/zle_word.c, Test/X02zlevi.ztst:
+ improvements to newline handling for vi-mode word movement
+
+2015-05-04 Mikael Magnusson <mikachu@gmail.com>
+
+ * 35021: Src/builtin.c: Fix two bugs in typeset_setbase
+
+2015-05-03 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 35018 (corrected): NEWS: news.
+
+2015-05-03 Oliver Kiddle <opk@zsh.org>
+
+ 35011: Completion/BSD/Type/_jails, Completion/Solaris/Command/_beadm,
+ Completion/Solaris/Type/_be_name, Completion/Solaris/Type/_zones,
+ Completion/Unix/Command/_chmod, Completion/Unix/Command/_chown,
+ Completion/Unix/Command/_cmp, Completion/Unix/Command/_comm,
+ Completion/Unix/Command/_cp, Completion/Unix/Command/_cut,
+ Completion/Unix/Command/_date, Completion/Unix/Command/_du,
+ Completion/Unix/Command/_elfdump, Completion/Unix/Command/_find,
+ Completion/Unix/Command/_fuser, Completion/Unix/Command/_gcore,
+ Completion/Unix/Command/_grep, Completion/Unix/Command/_iconv,
+ Completion/Unix/Command/_id, Completion/Unix/Command/_join,
+ Completion/Unix/Command/_last, Completion/Unix/Command/_ldd,
+ Completion/Unix/Command/_ls, Completion/Unix/Command/_md5sum,
+ Completion/Unix/Command/_mkdir, Completion/Unix/Command/_nl,
+ Completion/Unix/Command/_nm, Completion/Unix/Command/_od,
+ Completion/Unix/Command/_patch, Completion/Unix/Command/_ping,
+ Completion/Unix/Command/_ps, Completion/Unix/Command/_readelf,
+ Completion/Unix/Command/_rm, Completion/Unix/Command/_sed,
+ Completion/Unix/Command/_sort, Completion/Unix/Command/_uname,
+ Completion/Unix/Command/_uniq, Completion/Unix/Command/_wc,
+ Completion/Unix/Command/_xargs, Completion/Unix/Type/_diff_options,
+ Completion/Unix/Type/_file_systems: update completions for some
+ common Unix commands, in particular improving FreeBSD support
+
+2015-05-01 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 35009: README, Etc/FAQ.yo: updates for 5.0.8.
+
+2015-05-01 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 35008: Doc/Zsh/builtins.yo: clarify description of 'exec' and
+ 'return'
+
+2015-05-01 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 35007: Doc/Zsh/zle.yo: note about scope of ZLE parameters.
+
+2015-04-29 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34992: Doc/Zsh/builtins.yo, Src/builtin.c, Src/params.c,
+ Test/B02typeset.ztst: With POSXIBUILTINS, parameters can be
+ marked readonly if unset and in any case can't subsequently be
+ marked not readonly.
+
+2015-04-28 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34989: Src/exec.c: AUTOCD needs to pass -- to cd to avoid
+ directory being treated as option.
+
+2015-04-28 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Jared Ahern: 34980: Completion/Unix/Command/_make: expanding
+ make variables was somewhat broken.
+
+ * Jared Ahern: 34980: Completion/Unix/Command/_make: match
+ additional forms of assignment in makefiles.
+
+ * 34979: Src/exec.c: preserve job text in shell job fix code.
+
+ * 34977: Src/zsh.mdd: more reliable test for whether
+ preprocessor is GNU.
+
+2015-04-25 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34966: Src/hashtable.c: "whence -v" for a function reports
+ whether the function is autoloaded or its source file when known
+
+ * 34965: Src/glob.c: consistent use of zalloc/zrealloc/zfree
+
+ * 34961: Completion/Unix/Command/_mkdir: avoid _message because
+ it aborts completer list too early
+
+ * 34961: Completion/Base/Completer/_history: unquote history words
+ when command line has a quote
+
+ * 34961: Completion/compaudit: properly handle the case of finding
+ no files when searching $fpath and $_compdir
+
+ * 34961: Doc/Zsh/compsys.yo: minor wording clarification
+
+ * 34961: Src/Modules/datetime.c: $TZ is implicitly local in
+ builtin strftime (originally workers/34602 from workers/34596)
+
+ * 34961: Src/hist.c: clean up decl's of quote() and quotebreak()
+
+ * 34961: Doc/Zsh/mod_system.yo: sysparams[pid] and sysparams[ppid]
+ added to variables index
+
+ * 34961: Src/compat.c, Src/init.c: replace a couple of free() with
+ zfree() for consistency.
+
+ * 34961: Completion/Base/Completer/_expand: add backslash to alias
+ expansion matching (related to workers/32186)
+
+ * 34961: Test/D02glob.ztst: test for breadth-first glob with (Y1)
+ qualifier (originally workers/32726)
+
+2015-04-24 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34955: Src/exec.c: list_pipe_job needs saving and restoring
+ with some other similar variables in execlist() in order
+ to stop source() messing up job control.
+
+2015-04-24 Mikael Magnusson <mikachu@gmail.com>
+
+ * Oliver: 34940: Completion/Zsh/Command/_fc: fix typo breaking
+ completion for history
+
+2015-04-17 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34921: Src/parse.c: handle error in recursive par_event().
+
+2015-04-17 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34920: Etc/zsh-development-guide: info on git pull.
+
+2015-04-17 Daniel Hahler <git@thequod.de>
+
+ * 34899: Completion/Unix/Command/_vim: completion: _vim: add
+ nvim to #compdef
+
+2015-04-17 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34919: Src/Zle/zle_hist.c, Src/Zle/zle_misc.c: similar cases
+ with send-break and push-input.
+
+ * 34905: Src/Zle/zle_keymap.c, Src/lex.c, Src/parse.c: suppress
+ parse errors resulting from keyboard interruption.
+
+2015-04-16 Mikael Magnusson <mikachu@gmail.com>
+
+ * 34902: Doc/Zsh/compsys.yo, Doc/Zsh/contrib.yo, Doc/Zsh/zle.yo:
+ explain the numeric argument and be consistent about what we
+ call it.
+
+2015-04-15 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34901: Test/A04redirect.ztst: Test for the foregoing.
+
+ * 34900: Src/exec.c: assignment before an "exec" with
+ a redirection, with and without POSIXBUILTINS.
+
+2015-04-15 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted: Src/math.c: rewrite last commit to look more
+ like other uses of Nularg.
+
+ * 34892 (slightly tweaked): Src/math.c, Test/C01arith.ztst: fix
+ math evaluation with empty expression resulting from substitution.
+
+ * 34887: Src/exec, Test/E01options.ztst: assignments before
+ "command special-builtin/func" in POSIX_BUILTINS mode behave as
+ normal command. Tidy up case handling in code and add test.
+
+2015-04-13 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * users/20159: Completion/Zsh/Command/_zstyle: completion: zstyle:
+ Add 'show-ambiguity'
+
+ * 34886: Completion/Unix/Command/_git: completion: git: Complete
+ rebase --exec argument
+
+ * 34885: Completion/Unix/Command/_git: completion: git: Sort
+ "commit object" completions most recent first
+
+ * 34885: Completion/Unix/Command/_git: completion: git: Fix
+ another instance of the 34671 bug fixed in 34814
+
+2015-04-13 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Han Pingtian: 34880: Doc/Zsh/options.yo: POSIX_TRAPS doc.
+
+ * Han Pingtian: 34875: Doc/Zsh/options.yo: CSH_JUNKIE_HISTORY doc.
+
+ * Han Pingtian: users/20078: Doc/Zsh/options.yo: HIST_BEEP doc.
+
+2015-04-10 Clint Adams <clint@zsh.org>
+
+ * 34874: Completion/Unix/Command/_cabal: completion for cabal
+ command from cabal-install.
+
+2015-04-10 Daniel Hahler <git@thequod.de>
+
+ * 34748: Completion/Unix/Command/_git: completion: git: update
+ list of builtintools
+
+2015-04-07 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34850: Doc/zman.yo, Doc/ztexi.yo, Doc/META-FAQ.yo,
+ Doc/Zsh/contrib.yo, Doc/Zsh/ftp_sites.yo, Doc/Zsh/manual.yo,
+ Doc/Zsh/metafaq.yo, Doc/Zsh/roadmap.yo: make URLs in html/pdf
+ docs clickable
+
+2015-04-06 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34851: Src/builtin.c: fix thinko from 34093 that short-circuited
+ some "whence -m" searches
+
+2015-04-03 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34837: Src/glob.c: avoid loss of original file path when applying
+ colon-modifiers in glob qualifiers, that path is still needed for
+ later stat() when sorting.
+
+2015-04-03 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34840: Doc/Zsh/prompt.yo: minor format fixes
+
+2015-04-02 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34836: Doc/Zsh/prompt.yo: fix description of '%-0<<'
+
+2015-04-01 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34814: Completion/Unix/Command/_git: completion: git: Fix
+ bug introduced by 34671 [based on patch by Daniel Hahler]
+
+2015-03-31 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * users/20058: Completion/Unix/Command/_ip,
+ Completion/Unix/Type/_find_net_interfaces,
+ Completion/Unix/Type/_net_interfaces: improve matching of
+ devices already on command line in ip completion.
+
+2015-03-31 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Han Pingtian: 34822: Doc/Zsh/options.yo: correction to
+ GLOB_SUBST doc.
+
+2015-03-29 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34817: Src/hist.c, Src/lex.c: catch some errors earlier when
+ handling history to avoid knock-on errors and doing too much
+ processing.
+
+2015-03-29 Theo Buehler <theo@math.ethz.ch>
+
+ * 34792: Src/Modules/langinfo.c: langinfo: Fix pointer type
+
+2015-03-29 Daniel Hahler <git@thequod.de>
+
+ * 34762: Completion/Unix/Command/_git: completion: git: add
+ short option for '--dir-diff' (_git-difftool)
+
+2015-03-28 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34804: Src/lex.c: refine 34734 POSIX_ALIAS change to preserve
+ old behavior of [[ ]] conditionals
+
+ * 34781: Src/lex.c, Test/A02alias.ztst: add implicit space after
+ alias expansion of tokens that form words without spacing; fixes
+ crash when using completion immediately following such an alias
+
+2015-03-27 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34788: Src/lex.c: refine errflag handling in cmd_or_math()
+
+2015-03-27 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Han Pingtian: 34785: Doc/Zsh/options.yo: fix typo in SHINSTDIN.
+
+ * 34787: Test/W01history.ztst: new tests.
+
+2015-03-26 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34784: Src/input.c, Src/zsh.h: fix old bug with history
+ selection.
+
+2015-03-25 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34779: Test/A02alias.ztst: tests for 34776
+
+ * unposted: Test/W01history.ztst: change an F: to a comment
+
+2015-03-25 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * Han Pingtian: 34769: incorrect description of process time
+ calculation.
+
+2015-03-25 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34776: Src/hist.c, Src/zsh.h: suppressing alias expansions
+ from history now uses same mechanism as everyone else.
+
+2015-03-25 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34774: Test/W01history.ztst, Test/comptest: fix %prep and use
+ read from a no-op pipe to force wait for the timeout
+
+2015-03-23 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34772: Test/W01history.ztst, Test/comptest: add new test
+ suite file for history; fix "read" usage in comptest for case
+ where there is no TTY
+
+2015-03-22 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34759: Src/hist.c, Src/lex.c: safer implementation.
+
+ * 34758: Src/hist.c, Src/lex.c: more problems with history
+ interaction with command substitution: rewind over input history
+ text when necessary.
+
+2015-03-21 Barton E. Schaefer <schaefer@zsh.org>
+
+ * users/20034: Completion/Base/Core/_main_complete: adjust
+ PREFIX and SUFFIX for unambiguous_cursor on second completion
+ attempt with GLOB_COMPLETE
+
+2015-03-20 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34753 / 34754: Test/C02cond.ztst: work around lack
+ of separate file times with NFS.
+
+ * 34752: Src/input.c: history expansion in command substitution
+ *still* didn't work although the command put back into the
+ history was correct.
+
+2015-03-19 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34742: Src/hist.c: history expansion in command substitution
+ didn't work. Discriminate the case of an alias expansion
+ more carefully.
+
+2015-03-19 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34739: Completion/Unix/Command/_git: git completion: Fix
+ regression in ce80a92 (workers/34638)
+
+2015-03-18 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34734: Doc/Zsh/grammar.yo, Src/lex.c, Test/A02alias.ztst:
+ restrict token aliasing (34641) to global aliases; tighten
+ up POSIX_ALIASES to better match spec; update Aliasing doc
+ to cover this and clarify older behavior
+
+2015-03-18 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34732: configure.ac: turn off fixed site function directory if
+ site function directory explicitly disabled.
+
+2015-03-17 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted: NEWS: rewrite the foregoing.
+
+2015-03-16 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34725: NEWS: note thhat common site function directory
+ may be overridden by configuration.
+
+ * 34721: Doc/Zsh/calsys.yo, Functions/Calendar/after,
+ Functions/Calendar/before: new glob qualifier functions.
+
+2015-03-16 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34671 plus tweaks: Completion/Base/Utility/_describe
+ Completion/Unix/Command/_git Doc/Zsh/compsys.yo: Add -1 -2 -J -V
+ -x to _describe, use them to sort 'git --fixup' hash completions
+
+ * 34671: Completion/Unix/Command/_git: git completion: only
+ offer recent commits' tags/heads for --fixup
+
+2015-03-15 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34712: Doc/Zsh/grammar.yo: clarify words that may be aliased
+
+2015-03-15 Mikael Magnusson <mikachu@gmail.com>
+
+ * unposted: Completion/Zsh/Command/_zattr: Fix completion of
+ attributes for files with pattern characters.
+
+2015-03-10 Peter Stephenson <p.stephenson@samsung.com>
+
+ * users/19985: Doc/Zsh/params.yo: improve doc of substring
+ subscripting further.
+
+2015-03-09 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34673: Functions/VCS_Info/Backends/VCS_INFO_get_data_git:
+ vcs_info git: Fix error message when rebase hasn't started
+
+ * 34693: Completion/Unix/Command/_sudo: sudo completion: Don't
+ false positive 'sudo -e' detection
+
+ * 34693: Completion/Linux/Command/_strace: _strace: Fix variable
+ leakage of $sys_calls
+
+2015-03-07 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * Daniel Hahler: 34638 with tweaks: Completion/Unix/Command/_git:
+ git completion: complete commit hashes and --fixup
+
+2015-03-05 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34643: Doc/Zsh/builtins.yo, Doc/Zsh/zle.yo: clarify which
+ escape sequences are recognized by print and bindkey builtins.
+
+2015-03-06 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34653: Doc/Zsh/zle.yo, Src/Zle/zle_main.c: move aborted vared
+ lines to ZLE_VARED_ABORTED.
+
+ * 34657: Doc/Zsh/params.yo: document the effect of substring
+ subscripting better.
+
+2015-03-05 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34654: Completion/Redhat/Command/_rpm: complete absolute file
+ names after -q --whatprovides.
+
+ * 34651: Src/lex.c: avoid core dump if no lexical token.
+
+ * Daniel Shahaf: 34647: Completion/Zsh/Function/_add-zsh-hook:
+ new completion.
+
+2015-03-05 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34636: Src/compat.c, Src/pattern.c, Src/utils.c, Src/ztype.c,
+ configure.ac: replace broken isprint() on Mac OS X.
+
+2015-03-04 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34641: Src/lex.c, Test/A02alias.ztst: make it possible to
+ alias tokens.
+
+ * Daniel Shahaf: 34640: Doc/Zsh/compsys.yo: clarify
+ documentation for _guard function.
+
+2015-03-03 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Matthew Martin: 34637: Completion/BSD/Command/_mixerctl:
+ new completion.
+
+2015-02-28 Barton E. Schaefer <schaefer@zsh.org>
+
+ * users/19934: Doc/Zsh/params.yo: document %D{...} for WATCHFMT
+
+2015-02-27 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34634: Src/glob.c: avoid infinite recursion on (/)# extendedglob
+
+2015-02-27 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34588: Completion/Unix/Command/_user_admin: Complete
+ 'usermod -a'
+
+2015-02-23 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34623: Src/hist.c: free history more often in previous case.
+
+2015-02-23 Mikael Magnusson <mikachu@gmail.com>
+
+ * 34615 + 34619: Src/hist.c: Remeta one frame earlier
+
+2015-02-22 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34606: Src/subst.c, Test/C01arith.ztst: fix up arithmetic
+ nested in parameter substitution.
+
+ * 34604: Src/hist.c: Work around problem with changes in Meta
+ affecting history file when read in.
+
+2015-02-21 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34597: Doc/Zsh/mod_datetime.yo: Revise strftime description to
+ correctly explain timezone handling and note signed int rollover
+
+2015-02-20 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34590: Src/exec.c, Src/text.c: queue_signals() around more
+ scopes that manipulate global state
+
+2015-02-20 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34587: Src/utils.c, Test/D07multibyte.ztst: ensure multibyte
+ characters don't overflow into tokens and add test.
+
+2015-02-19 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34568: Src/Module.c: use META_HEAPDUP when passing dlerror()
+ string to metafy()
+
+2015-02-19 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted: Config/version.mk: Mikael says it's 2015,
+ apparently.
+
+ * 34573: Src/subst.c: safer handling of failure to perform
+ command substitution.
+
+ * 34570: Config/version.mk, Src/lex.c, Src/subst.c, Src/zsh.h,
+ Test/C01arith.ztst: mark arithmetic substitutions with tokens
+ so the substitution code knows what to do.
+
+2015-02-17 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34563: Src/input.c: Fix up memory allocation in 34560.
+
+2015-02-16 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34560: Src/input. Src/lex.c, Src/zsh.h, Test/C01arith.ztst:
+ case of $(( that turned into a $(...) and a (...) with
+ multiple lines read before it found out.
+
+ * 34558: Doc/Zsh/func.yo: preexec doc erroneously claimed $1
+ was empty if line removed from history.
+
+2015-02-15 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34551: Src/builtin.c: Avoid adding an extra "/" to the
+ target path in cd_try_chdir() when the current directory is "/"
+
+2015-02-14 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34543: Src/input.c, Src/lex.c: Fix crash on garbage bytes
+ inside $(...)
+
+2015-02-14 Mikael Magnusson <mikachu@gmail.com>
+
+ * unposted: Doc/Zsh/prompt.yo: Fix typo from 28487.
+
+2015-02-13 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34546: Src/exec.c, Test/D04parameter.ztst: fix another
+ oddity with $_ and anonymous functions and add tests.
+
+2015-02-13 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34530: Src/exec.c, Test/E01options.ztst: revised fix
+ for PRINT_EXIT_VALUE from anonymous functions.
+
+2015-02-12 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34519: Src/exec.c: handle $_ with arguments to anonymous
+ function.
+
+2015-02-12 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34514: Src/exec.c, Src/parse.c, Test/E01options.ztst:
+ Back out 34485, an alternate solution needs to be worked
+ out. (Tweaked to keep the unrelated hunk of the E01 test.)
+
+ * 34476: Completion/Base/Utility/_store_cache: change the
+ assignment format to avoid potentially expensive lexical
+ analysis of the array values
+
+2015-02-11 Peter Stephenson <p.stephenson@samsung.com>
+
+ * users/19850: Doc/Zsh/params.yo, Src/watch.c: watch variable
+ supports patterns for user, tty and host names.
+
+2015-02-10 Mikael Magnusson <mikachu@gmail.com>
+
+ * 34488: Src/builtin.c: Fix use-after-free for print -zf and
+ print -sf
+
+ * 34490: Src/builtin.c: Fix leak on print -zf/-sf error
+
+2015-02-09 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34485: Src/exec.c, Src/parse.c, Test/E01options.ztst:
+ rationalise some more anonymous function behaviour:
+ don't try to handle as "simple" case as there are too
+ many hidden problems; pull out some post-execution
+ functions to common cases in execcmd().
+
+2015-02-09 Mikael Magnusson <mikachu@gmail.com>
+
+ * 34466: Src/utils.c: Fix double unmeta in rm verification
+
+2015-02-08 Daniel Hahler <git@thequod.de>
+
+ * 34469: Completion/Unix/Command/_git: git completion: add "stash"
+ from refs/stash to __git_heads
+
+ * 34470: Completion/Unix/Command/_adb: completion: adb: add
+ "sideload" command
+
+ * 34467: Completion/Unix/Command/_git: completion: git: minor doc
+ fixes
+
+ * 34468: Completion/Unix/Command/_git: completion: git: stash:
+ handle 'save' being the default
+
+2015-02-07 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34464: Completion/Unix/Command/_mtr: Update mtr completion
+ to mtr 0.82
+
+2015-02-03 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34456: _arguments: lopts should be initialized as an array
+
+2015-02-06 Peter Stephenson <p.stephenson@samsung.com>
+
+ * users/19825: Doc/Zsh/manual.yo: clear statement that zsh is
+ not by default POSIX compatible.
+
+2015-02-03 Barton E. Schaefer <schaefer@zsh.org>
+
+ * unposted: Doc/Zsh/builtins.yo: fix formatting of "--".
+
+2015-02-03 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34451: Src/mem.c: use mmap() also on Mac OS X
+
+2015-02-03 Peter Stephenson <p.stephenson@samsung.com>
+
+ * users/19800: Doc/Zsh/params.yo: more help on $HISTORY_IGNORE.
+
+ * 34455: Src/Modules/db_gdbm.c: some further parameter bug fixes
+ including memory leak and unsetting old parameter too late.
+
+2015-02-02 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34447: Src/Modules/db_gdbm.c: fix assignment of key-value array
+ to ztie'd parameter.
+
+2015-02-02 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34444: Completion/Unix/Command/_git: git completion: minor
+ improvements to 'commit' and 'rebase'
+
+2015-02-01 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34446: Doc/Zsh/mod_db_gdbm.yo, Src/Modules/db_gdbm.c: add
+ "ztie -r" and "zuntie -u", update documentation for this and
+ for 34430,34439.
+
+2015-02-01 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34411: Completion/Unix/Command/_hg: _hg completion: Complete
+ bookmark names for -r
+
+2015-01-30 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34439: Src/Modules/db_gdbm.c: unset parameter that's about to
+ be tied when necessary.
+
+2015-01-30 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34435: Completion/Unix/Command/_sh,
+ Completion/Unix/Type/_cmdstring, Completion/Zsh/Command/_emulate:
+ updated emulate completion; _cmdstring factors out use of
+ quoted command string.
+
+2015-01-29 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34430: Src/Modules/db_gdbm.c, Src/params.c: various bug fixes
+ and safety additions for gdbm tied hashes.
+
+2015-01-28 Barton E. Schaefer <schaefer@zsh.org>
+
+ * unposted: Doc/Zsh/builtins.yo: fix other typeset doc errors
+
+ * 34421: Doc/Zsh/builtins.yo: clean up typeset documentation
+
+2015-01-28 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34415: Completion/Unix/Type/_python_modules,
+ Completion/Unix/Command/_python, Completion/Unix/Command/_pydoc:
+ cache list of all python modules
+
+2015-01-28 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34423: _ruby: fix a typo
+
+2015-01-27 Frank Terbeck <ft@bewatermyfriend.org>
+
+ * 34419: Doc/Zsh/contrib.yo: vcs_info documentation: Fix wording
+
+2015-01-27 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Daniel Shahaf: 34412: Completion/Unix/Command/_chown: complete
+ all groups if running as sudo.
+
+2015-01-27 Mikael Magnusson <mikachu@gmail.com>
+
+ * 34382: Src/module.c: Handle NULL return from dlerror() more
+ gracefully
+
+ * 34387: Src/module.c: Avoid loading the main zsh binary as
+ a module
+
+2015-01-26 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34403: Src/utils.c: refine 34399 to avoid settyinfo() when the
+ input descriptor is not a TTY
+
+2015-01-26 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34402: Src/Modules/db_gdbm.c: make unsetting a tied gdbm
+ variable work and hence allow tied variables in nested scope.
+ Untying still doesn't uncover scope properly.
+
+2015-01-25 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34399: Src/utils.c: fix polltty thinko from 34365
+
+ * 34389: Src/hist.c: fix parsing of ">!" when read from histfile
+ with HIST_LEX_WORDS in effect
+
+2015-01-25 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34365: configure.ac, Src/hist.c, Src/utils.c; random doubling
+ backoff on history lock failure. Add zsleep() to provide
+ microsecond sleeps, via nanosleep() available else select() in
+ tty_poll().
+
+ * 34369: Daniel Shahaf: document error / warning codes.
+
+ * 34383: Src/utils.c: new ztrdup() shoud be dupstring().
+
+2015-01-25 Oliver Kiddle <opk@zsh.org>
+
+ * 34373, 34374: Completion/Unix/Command/_chown,
+ Completion/Unix/Command/_ln, Completion/Unix/Type/_directories,
+ Completion/Zsh/Command/_command, Completion/Zsh/Command/_fc,
+ Completion/Zsh/Command/_typeset, Completion/Zsh/Command/_unhash,
+ Completion/Zsh/Command/_which, Completion/Zsh/Command/_zle,
+ Completion/Zsh/Command/_zstyle, Completion/Zsh/Context/_subscript,
+ Completion/Zsh/Type/_globflags, Doc/Zsh/builtins.yo,
+ Completion/Zsh/Context/_brace_parameter,
+ Completion/Zsh/Type/_history_modifiers: update completion of
+ builtin commands, modifiers, parameter and globbing flags
+
+2015-01-25 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34381: Doc/Zsh/contrib.yo: vcs_info: Documentation update
+
+2015-01-25 Frank Terbeck <ft@bewatermyfriend.org>
+
+ * unposted: ChangeLog: Forgot X-Seq: numbers with Daniel's last
+ few patches
+
+2015-01-25 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34366: Doc/Zsh/contrib.yo,
+ Functions/VCS_Info/Backends/VCS_INFO_get_data_hg: vcs_info hg:
+ Support inactive bookmarks
+
+ * 34367: Completion/Zsh/Command/_zstyle: _zstyle vcs_info: Unbreak
+ branchformat completion
+
+ * 34368: Completion/Zsh/Command/_zstyle: _zstyle vcs_info
+ completion: Add missing styles
+
+2015-01-24 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34350, 34353: Doc/Makefile.in, Doc/Zsh/mod_db_gdbm.yo,
+ Src/Modules/db_gdbm.c: document zsh/db/gdbm module, clean up a few
+ things in the code. Still core dumps if the tied parameter is
+ forced to be a local and is not untied before end of scope.
+
+2015-01-23 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34335: _yum: fix bugs in _yum_all_pkgs
+
+2015-01-22 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34331: Src/builtin.c, Src/utils.c: don't trip over
+ NULL pointer in cd in rare cases where file system goes AWOL.
+
+2015-01-22 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34344: Test/V07pcre.ztst: fix 34338, builtins need loading too
+
+ * 34338: Test/V07pcre.ztst: check feature availability
+
+2015-01-22 Marc Finet <m.dreadlock@gmail.com>
+
+ * 34333: Functions/VCS_Info/VCS_INFO_quilt: fix unapplied
+ detection in subdir
+
+2015-01-22 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34327: _perl_modules: fix cache identifier used in
+ _cache_invalid
+
+2015-01-20 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34329: Doc/Zsh/builtins.yo, Src/builtin.c: add -S option
+ to which and where.
+
+ * users/19756: Test/A04redirect.ztst: add test for case of
+ closing file descriptor with no error message.
+
+ * users/19751: Src/exec.c, Test/A04redirect.ztst: remove error
+ on closing file descriptors via number but keep it for those
+ controlled by variable.
+
+2015-01-18 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34322: Src/Zle/compctl.c, Src/Zle/compresult.c, Src/exec.c,
+ Src/init.c, Src/lex.c, Src/params.c, Src/prompt.c, Src/subst.c,
+ Src/utils.c, Test/D04parameter.ztst: update interface to
+ parsestr()/parsestrnoerr() to ensure correct token string
+ is passed back.
+
+ * 34320: Src/hist.c, Src/lex.c: alias expansion in history of
+ command substitution.
+
+2015-01-17 Axel Beckert <abe@deuxchevaux.org>
+
+ * 34314: Wieland Hoffmann: Completion/Unix/Command/_git: Change
+ one --validate to --no-validate
+
+2015-01-16 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: Src/hist.c: fix another dubious comment.
+
+ * unposted: Src/hist.c: improve confusing comment in previous
+ commit.
+
+ * 34313: Src/hist.c, Src/lex.c: need to turn off history
+ word markers when parsing command substitution.
+
+2015-01-16 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34304: Src/lex.c: improve use of new command substitution
+ parsing in completion.
+
+2015-01-15 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34290 (correcting typo): README: note FORCE_FLOAT behaviour change.
+
+ * 34280: Doc/Zsh/options.yo, Src/math.c, Test/C01arith.ztst:
+ make FORCE_FLOAT option also cover variables when read for
+ use in arithmetic expressions.
+
+ * 34287 (see 34286 from Markus Trippelsdorf): Src/zsh.mdd:
+ use -E argument for generating signal names if gcc is
+ preprocessor.
+
+2015-01-14 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34283: Test/X02zlevi.ztst: also needs zpty.
+
+ * 34275: Test/V08zpty.ztst, Test/Y01completion.ztst,
+ Test/Y02compmatch.ztst, Test/Y03arguments.ztst: assume zpty
+ doesn't work under Cygwin.
+
+2015-01-13 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34273: Doc/Zsh/compsys.yo: use a sufficient number of colons
+ in example style patterns to assure fixed strings can't match
+ the wrong field positions
+
+2015-01-13 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: README: fix deliberate error in previous update.
+
+2015-01-13 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34260: Eric Cook: Completion/Unix/Command/_ip: relax
+ restriction on interface names.
+
+ * 34259: Eric Cook: Completion/Unix/Command/_ip: fix variable
+ declarations.
+
+2015-01-12 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted: .gitignore: add Src/zsh.exe for Cygwin.
+
+ * 34255: README, Src/math.c, Test/C01arith.ztst: propagate type
+ from variable assignment. Also note 34230 in README.
+
+ * 34253: Doc/Zsh/contrib.yo: warning on integer arithmetic
+ for zcalc, c.f. 34194.
+
+2015-01-11 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34247: Test/C01arith.ztst: regression test for 34230.
+
+ * 34230: Src/math.c: call fmod() for modulo with floats
+
+2015-01-11 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34234: Src/lex.c, Src/zsh.h: use structures for normal and raw
+ lexical buffer state.
+
+ * 34233: Completion/Linux/Command/_qdbus: add _qdbus "$@" trick.
+
+2015-01-10 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: Test/C04funcdef.ztst: test for the foregoing
+
+ * 34220: Src/input.c: new $(...) parsing didn't back up over
+ alias expansions.
+
+ * unposted: Src/context.c: update copyright.
+
+ * 34195: Thomas Mitterfellner: Completion/Linux/Command/_qdbus:
+ new completion.
+
+2015-01-10 Barton E. Schaefer <schaefer@zsh.org>
+
+ * unposted (cf. 34218): Completion/Base/Widget/_complete_debug,
+ Completion/compinstall, Functions/Calendar/calendar,
+ Functions/Zftp/zfget_match: remove -m from zmodload calls
+
+ * 34212, 34313: Src/builtin.c: do not change unset-ness of special
+ parameters when exporting them
+
+2015-01-09 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34202: Completion/Base/Widget/_complete_debug,
+ Completion/compinstall, Functions/Calendar/calendar,
+ Functions/Zftp/zfget_match: safe tempfile creation part 3
+
+ * users/19721: Doc/Zsh/compsys.yo: clarify context vs. style
+
+2015-01-09 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34194: Doc/Zsh/arith.yo: add paragraph about integer
+ promotion.
+
+ * 34189: Src/Zle/compcore.c, Src/Zle/compctl.c,
+ Src/Zle/textobjects.c, Src/Zle/zle_tricky.c, Src/builtin.c,
+ Src/context.c, Src/exec.c, Src/hist.c, Src/init.c, Src/lex.c,
+ Src/parse.c, Src/signals.c, Src/zsh.h, Src/zsh.mdd:
+ vain attempt to make context save and restore neater and
+ control the status variables thereby managed.
+
+2015-01-09 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34182: Doc/Zsh/mod_files.yo: to add zf_* builtins you can
+ use zmodload -m -F.
+
+2015-01-09 Mikael Magnusson <mikachu@gmail.com>
+
+ * 30568: Doc/Zsh/contrib.yo, Functions/Misc/tetriscurses: Add
+ tetriscurses contrib function, port of tetris to zcurses
+
+2015-01-08 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 34160: Src/init.c, Src/input.c, Src/lex.c, Src/parse.c,
+ Src/zsh.h, Test/D08cmdsubst.ztst: fix the problem that command
+ and similar substitutions weren't properly parsed so could end
+ prematurely. Use improved resolution in context save and restore
+ to allow parsing the substitution while tracking the string.
+
+2015-01-07 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34154 (tweaked per 34155): Src/builtin.c: reorder bin_print() to
+ avoid leaking the output descriptor when incorrect/incompatible
+ options were passed
+
+2015-01-07 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 34144: Src/Zle/zle_tricky.c, Src/Zle/complist.c: allocate
+ origline by ztrdup(), not by dupstring()
+
+2015-01-06 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34122: Src/module.c: allow NULL third argument as intended
+
+2015-01-06 Mikael Magnusson <mikachu@gmail.com>
+
+ * 34138: Src/utils.c: wcs_nicechar: only deref widthp if it
+ was given
+
+ * 34120: Src/Zle/compctl.c, Src/jobs.c: Check contents instead
+ of array
+
+ * 34108: Src/utils.c: Don't leak ifs stuff
+
+ * 34107: Src/hist.c: getsubsargs: free ptr1 before returning
+
+ * 34134: Src/exec.c: anon funcs: don't leak shf and related data
+
+ * 34112: Src/builtin.c: typeset: fix leak of oldval
+
+ * 34106: Src/hist.c: use zhtricat instead of tricat
+
+ * 34113: Src/builtin.c: whence: use dupstring to not leak memory
+
+ * 34119: Src/Zle/complist.c: Fix leak of string in clnicezputs
+
+ * 34105: Src/subst.c: remove dead code
+
+ * 34121: Src/Zle/compresult.c: Remove unneeded NULL check
+
+ * 34104: Src/Zle/compctl.c: Remove pointless check
+
+ * 34115: Src/Zle/compcore.c: Fix size argument to zfree
+
+ * 34117: Src/Zle/zle_utils.c: size_t is unsigned, use int instead
+
+ * 34116: Src/Zle/computil.c: Check for NULL before passing
+ to strlen
+
+ * 34118: Src/hist.c: Don't crash when writing out history if
+ HOST is unset
+
+ * 34114: Src/builtin.c: emulate: Handle aborting from mixed
+ -L/-c correctly
+
+2015-01-06 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34103: Src/subst.c: fix ancient (workers/15872) thinko that
+ doesn't seem to have mattered, but must in some obscure cases
+
+2015-01-05 Daniel Shahaf <d.s@daniel.shahaf.name>
+
+ * 34042: Completion/Unix/Command/_git: Respect tags for subcommand
+ completion.
+
+2015-01-05 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Timofey Titovets: 34053: Completion/Linux/Command/_modutils:
+ additional compression option for kernel modules.
+
+2015-01-04 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34093: Src/builtins.c: "whence" should always return nonzero
+ when it finds that nothing matches its arguments
+
+2015-01-04 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34092: Src/utils.c: miscount of buffer length in symlink
+ resolution after ".." caused error with whence -S.
+
+ * 34091: Src/utils.c: typo with "whence -s" expansions.
+
+ * users/19682: Doc/Zsh/builtins.yo: document recommended use of
+ whence.
+
+2015-01-02 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * users/19671: Src/builtin.c: whence -a should still work if
+ there's a full path already.
+
+ * users/19667: Doc/Zsh/builtins.yo, Src/builtin.c, Src/utils.c:
+ whence -S shows intermediate steps in symlink expansion.
+
+ * 34077: Test/A07control.ztst: add some further tests for
+ return status from "for" loops.
+
+2014-12-29 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33963: Completion/Unix/Command/_mount: remove work of art
+ in _mount
+
+2014-12-28 Barton E. Schaefer <schaefer@zsh.org>
+
+ * Daniel Shahaf: 34070: Src/Zle/zle_refresh.c: fix starting
+ position for memset() from 34005.
+
+ * 34068: Completion/Base/Widget/_complete_debug,
+ Completion/Unix/Command/_cvs, Completion/compinstall,
+ Functions/Calendar/calendar, Functions/Zftp/zfcd_match,
+ Functions/Zftp/zfcget, Functions/Zftp/zfcput,
+ Functions/Zftp/zfget_match, Functions/Zftp/zfrglob,
+ Functions/Zftp/zftransfer, Functions/Zftp/zfuget,
+ Functions/Zftp/zfuput: create tempfiles without forking, and
+ safe temp directory creation
+
+2014-12-27 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34067: Completion/Base/Widget/_complete_debug,
+ Completion/compinstall, Functions/Calendar/calendar,
+ Functions/Zftp/zfcd_match, Functions/Zftp/zfcget,
+ Functions/Zftp/zfcput, Functions/Zftp/zffcache,
+ Functions/Zftp/zfget_match, Functions/Zftp/zfrglob,
+ Functions/Zftp/zftransfer, Functions/Zftp/zftype,
+ Functions/Zftp/zfuget, Functions/Zftp/zfuput,
+ Functions/Zle/edit-command-line: safe tempfile creation
+
+ * unposted: Test/A05execution.ztst: regressions for 34065
+
+ * 34065: Src/exec.c, Src/loop.c: following an "if" condition, do
+ not test lastval for ERR_EXIT until a new command is run
+
+ * Takeshi Banse: 34064: Src/exec.c, Test/A06assign.ztst: assignment
+ before command replaces array with export even when KSH_ARRAYS
+
+2014-12-21 Oliver Kiddle <opk@zsh.org>
+
+ * Daniel Shahaf: 33977: Completion/Zsh/Command/_bindkey:
+ don't complete widgets as first argument to bindkey
+
+2014-12-19 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34015: Src/params.c: back off yesterday's mess and
+ disallow environment variables with characters with the
+ top bit set.
+
+ * 34005: Src/Zle/zle_refresh.c: Zero uninitialised memory when
+ realloc'ing region_highlights.
+
+2014-12-18 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 34008: Src/params.c: also metafy anything arriving from the
+ environment.
+
+ * 34006: Src/params.c: unmetafy anything put into the
+ environment.
+
+ * Lokesh Mandvekar: 33999: Completion/Linux/Command/_docker:
+ remove completion as the version supplied with docker is
+ authoritative.
+
+2014-12-17 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 34002: Src/Zle/zle_keymap.c: zshcalloc() in init_keymaps()
+
+ * 33992: Src/jobs.c: do not attempt attachtty() for process group
+ zero (which is possible in a linux pid namespace)
+
+2014-12-18 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 33978: Src/Zle/complist.c: update command line when accept-
+ and-hold is called in interactive mode of menu select
+
+2014-12-17 Peter Stephenson <p.stephenson@samsung.com>
+
+ * users/19551: Doc/builtins.yo, Doc/Zsh/roadmap.yo: better
+ documentation that history file reading and writing is only
+ done in interactive shells.
+
+2014-12-16 Barton E. Schaefer <schaefer@zsh.org>
+
+ * Jun Kuriyama: 33984: Src/builtin.c: bin_dirs() should use
+ zputs() to print metafied directory names
+
+ * Chirantan Ekbote: 33982: Src/jobs.c: minimal support for pid
+ namespaces by recognizing that GETPGRP() may return 0
+
+2014-12-15 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33976: Src/subst.c: fix overlapping strcpy()
+
+2014-12-14 Mikael Magnusson <mikachu@gmail.com>
+
+ * users/19530: Completion/Unix/Type/_file_systems: Handle
+ commented lines in /etc/filesystems
+
+2014-12-13 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: Test/D04parameter.ztst: need -f for starting zsh
+ to avoid problems from user config files.
+
+2014-12-13 Oliver Kiddle <opk@zsh.org>
+
+ * 33958: Completion/Unix/Command/_sudo: update for newer options
+
+ * 33956: Doc/Zsh/zle.yo, Src/Zle/zle_bindings.c,
+ Src/Zle/zle_keymap.c: document key binding changes and remove
+ ^X binding
+
+ * 33846: Src/Zle/iwidgets.list, Src/Zle/zle_bindings.c,
+ Src/Zle/zle_keymap.c: additional default vi-mode key bindings
+
+2014-12-12 Oliver Kiddle <opk@zsh.org>
+
+ * 33950: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list, Src/Zle/zle.h,
+ Src/Zle/zle_keymap.c: ignore KEYTIMEOUT for vi operators
+
+2014-12-11 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33876: etc.: Completion/Base/Core/_main_complete,
+ Doc/Zsh/params.yo, Src/Modules/zpty.c, Src/Modules/zutil.c,
+ Src/Zle/compcore.c, Src/Zle/compctl.c, Src/Zle/compresult.c,
+ Src/Zle/textobjects.c, Src/Zle/zle_hist.c, Src/Zle/zle_keymap.c,
+ Src/Zle/zle_main.c, Src/Zle/zle_misc.c, Src/Zle/zle_tricky.c,
+ Src/Zle/zle_utils.c, Src/builtin.c, Src/exec.c, Src/glob.c,
+ Src/hist.c, Src/init.c, Src/input.c, Src/jobs.c, Src/lex.c,
+ Src/loop.c, Src/params.c, Src/parse.c, Src/prompt.c,
+ Src/signals.c, Src/subst.c, Src/utils.c, Src/zsh.h: Separate
+ shell errors and user interrupt flags into different bits of
+ errflag: ERRFLAG_ERROR and ERRFLAG_INT. Various
+ rationalisations to make keyboard interrupts work smoothly.
+ Work done on interrupt_abort branch.
+
+2014-12-10 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33948: Completion/Unix/Command/_getent,
+ Completion/Unix/Command/_iconv, Completion/Unix/Command/_ldd:
+ Parse "Gentoo" as being GNU libc
+
+2014-12-10 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 33940: Src/lex.c: handle backslash-meta correctly in lexer
+
+2014-12-09 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 33932: Src/utils.c: revise boundary check in unmeta()
+
+2014-12-08 Oliver Kiddle <opk@zsh.org>
+
+ * 33924: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list, Src/Zle/zle.h,
+ Src/Zle/zle_move.c, Src/Zle/zle_vi.c, Test/X02zlevi.ztst:
+ allow vi line/characterwise mode to be forced
+
+2014-12-08 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33927: Completion/Unix/Command/_nm: .elf files and
+ directories.
+
+ * 33843: Completion/Unix/Type/_files: minor optimisation for
+ recursive-files.
+
+2014-12-07 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33912: Completion/Unix/Command/_od: fix filename default case
+
+ * 33901: Completion/Base/Core/_main_complete: fix warning message
+ reference to funcstack (updates 33859)
+
+ * 33894: Src/utils.c: boundary conditions in unmeta(), unmetafy()
+
+2014-12-07 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * Daniel Shahaf: 33883: Doc/Zsh/expn.yo,
+ Completion/Zsh/Type/_globquals: documentation for (*) glob
+ qualifier.
+
+2014-12-07 Jun-ichi Takimoto <takimoto-j@kba.biglobe.ne.jp>
+
+ * 33829: Test/X02zlevi.ztst, Test/comptest: unbind ESC~ asa
+ a more reliable workaround
+
+2014-12-06 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33882: Completion/Unix/Command/_gcc: Complete CXXFLAGS as
+ CFLAGS too
+
+2014-12-05 Oliver Kiddle <opk@zsh.org>
+
+ * 33861: Completion/Unix/Command/_lsof:
+ update lsof completion for new options
+
+ * 33860: Src/Zle/textobjects.c, Src/Zle/zle_misc.c,
+ Src/Zle/zle_move.c, Src/Zle/zle_vi.c, Test/X02zlevi.ztst:
+ minor fixes to vi mode changes
+
+ * 33845: Src/Zle/zle_hist.c: save correct cursor position with
+ push-line from vi command mode
+
+2014-12-05 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33866: Completion/compinit: need multifuncdef for TRAPINT
+ TRAPQUIT definition.
+
+ * 33859 with typo fix: Completion/Base/Core/_main_complete: to
+ propagate signal from trap we need to use function style.
+
+2014-12-05 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33854: Src/glob.c: errors end recursion through scanner(), which
+ makes **/ more easily interruptible
+
+2014-12-04 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33841: Doc/Zsh/params.yo: explain array append a bit better
+
+2014-12-03 Mikael Magnusson <mikachu@gmail.com>
+
+ * Eric Cook: 33689: Completion/Unix/Command/_cp: make cp
+ --reflink's argument optional
+
+2014-12-01 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Jun T: 33830 plus CVS removal: Doc/Zsh/metafaq.yo: typo in
+ sourceforge URL; don't mention CVS.
+
+2014-11-30 Oliver Kiddle <opk@zsh.org>
+
+ * 33823: Src/Zle/zle_misc.c, Test/X02zlevi.ztst: overwrite mode
+ shouldn't replace newlines
+
+ * 33820: configure.ac, Src/hist.c: detect support for realpath()
+ with a NULL argument and fixes to the use of it
+
+ * 33800: Src/Zle/zle_main.c: remove old workaround for ancient
+ systems to consume typeahead before setting up the terminal
+
+ * 33818: Src/Builtins/sched.c, Src/Zle/complist.c,
+ Src/exec.c, Src/sort.c, Src/utils.c: fix types passed to sizeof
+ detected by coverity as being wrong
+
+2014-11-28 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33819: Test/A06assign.ztst: regression tests for 33816
+
+ * 33816 (2nd part): Src/exec.c: GLOB_ASSIGN changes integer and
+ floating type variables to string scalars rather than treat single
+ match file names as arithmetic expressions
+
+2014-11-28 Wayne Davison <wayned@users.sourceforge.net>
+
+ * unposted: avoid compiler warning about a set-but-not-used var.
+
+2014-11-28 Wayne Davison <wayned@users.sourceforge.net>
+
+ * 33139: Doc/Zsh/expn.yo: add example for finding broken symlinks.
+
+2014-11-28 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33815: Src/Zle/zle_word.c: fix word transposition bug where
+ wrong words could be transposed.
+
+2014-11-27 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33805: Doc/Zsh/params.yo: rewrite intro, tweak formatting
+
+ * 33804: Completion/compinit: hide values of large arrays in
+ typeset output by declaring with the -H attribute
+
+2014-11-26 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: Test/C01arith.ztst: test binary input using 0b.
+
+2014-11-26 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33793: Src/math.c, Src/utils.c, Doc/Zsh/arith.yo: Arithmetic
+ constants beginning 0b specify binary.
+
+2014-11-25 Oliver Kiddle <opk@zsh.org>
+
+ * Jun T: 33769: Test/comptest: workaround for KEYTIMEOUT to
+ work from test cases on Darwin and FreeBSD
+
+ * 33770: Src/Zle/zle_main.c: avoid calling identical FIONREAD
+ ioctl twice in succession
+
+ * users/19365 (credit Death Jester and Jan Larres):
+ Completion/Base/Completer/_external_pwds;
+ completer for current directory of other shell processes
+
+2014-11-25 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33791: Src/loop.c: fatal errors in the try-block part of an
+ "always" construct cause the entire construct to have nonzero
+ status, even when TRY_BLOCK_ERROR is used to suppress the error.
+
+2014-11-24 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Daniel Hahler: 33746: Doc/Zsh/builtins.yo: read -q refers to -t.
+
+2014-11-24 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33785: Src/Modules/tcp.c: Fix leaks of desthost in ztcp.
+
+2014-11-23 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33775: Src/exec.c: error opening file in $(<...) is not fatal
+
+2014-11-23 Oliver Kiddle <opk@zsh.org>
+
+ * 33743: Src/Modules/zpty.c, configure.ac: use posix_openpt
+ if it is available
+
+2014-11-23 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33729: Completion/Unix/Command/_git: "git remote add" should
+ complete local repositories.
+
+ * 33740: Stephane: Doc/Zsh/expn.yo: "hideval" parameter type.
+
+ * 33740: Stephane: Etc/FAQ.yo: Another way of avoiding MULTIO
+ effects on pipes.
+
+2014-11-22 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33763 (cf. Baptiste Daroussin 33747): Doc/Zsh/mod_system.yo:
+ fix nested item list in generated zshmodules.1 man page.
+
+2014-11-21 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33750: Src/text.c: handle function autoloads for DEBUG_BEFORE_CMD
+
+ * unposted: Doc/Zsh/zle.yo: add menu reference to Text Objects
+
+2014-11-21 Oliver Kiddle <opk@zsh.org>
+
+ * saga.xu: 33712: Completion/Debian/_apt: add --auto-remove
+
+ * 33738: Src/Zle/zle_vi.c, Test/X02zlevi.ztst: account for a
+ selection in vi-replace-chars
+
+ * 33730: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list,
+ Src/Zle/textobjects.c, Src/Zle/zle.mdd, Src/Zle/zle_keymap.c,
+ Test/X02zlevi.ztst: vim style text objects for selecting words
+
+2014-11-21 Peter Stephenson <p.stephenson@samsung.com>
+
+ * Sebastien Alaiwan: 33728: Completion/Unix/Command/_bzr:
+ complete bzr shelve.
+
+2014-11-20 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted but see 33723: Etc/FAQ.yo: typo in sed command that's
+ been there about twenty years.
+
+2014-11-19 Peter Stephenson <p.stephenson@samsung.com>
+
+ * users/19404: Etc/FAQ.yo: login shells are not after all
+ necessarily interactive.
+
+ * 33679: Doc/Zsh/grammar.yo: Note that alternation in case
+ patterns works just like filename generation, despite
+ appearances to the contrary.
+
+2014-11-17 Oliver Kiddle <opk@zsh.org>
+
+ * 33704: Doc/Zsh/zle.yo, Src/Zle/zle_bindings.c,
+ Src/Zle/zle_keymap.c, Src/Zle/zle_refresh.c, Src/Zle/zle_vi.c,
+ Test/X02zlevi.ztst, Test/comptest: key bindings, documentation,
+ tests and minor fixes for vim style visual selection changes
+
+ * 33636: Src/Zle/iwidgets.list, Src/Zle/zle_misc.c,
+ Src/Zle/zle_move.c, Src/Zle/zle_refresh.c, Src/Zle/zle_vi.c:
+ add support for a linewise visual selection mode
+
+ * 33635: Src/Zle/iwidgets.list, Src/Zle/zle_misc.c,
+ Src/Zle/zle_move.c, Src/Zle/zle_refresh.c, Src/Zle/zle_vi.c:
+ adapt region to function as vim style visual selection mode
+
+ * 33700: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list,
+ Src/Zle/zle_misc.c, Src/Zle/zle_utils.c: new widget
+ for put in vim style visual selection mode
+
+ * 33699: Test/X02zlevi.ztst, Test/comptest: support short
+ delays in zle tests where we need KEYTIMEOUT to elapse
+
+2014-11-16 Oliver Kiddle <opk@zsh.org>
+
+ * 33633: Src/Zle/zle_vi.c: support vim style text objects
+
+ * 33632: Src/Zle/zle_main.c, Src/Zle/zle_vi.c: use viopp and visual
+ local keymaps if they exist
+
+2014-11-15 Oliver Kiddle <opk@zsh.org>
+
+ * 33697: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list, Src/Zle/zle_word.c:
+ new vim style vi-backward-word-end widgets
+
+ * 33696: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list, Src/Zle/zle_hist.c:
+ simple up/down line widgets that don't go through history lines
+
+ * 33695: Src/Zle/zle_vi.c, Test/X02zlevi.ztst, Test/comptest:
+ fix various vi-indent problems and vi-swap-case on a blank line
+
+2014-11-13 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * Artur Penttinen: 19371 plus tweak: run-help helper for ip.
+
+ * Marc Finet: 33687 (first and last patches): ensure length of
+ working directory is correct and return as soon as there's
+ an error chasing symlinks.
+
+2014-11-13 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33686: Test/B06fc.ztst: set PS1 before pattern-matching for it
+
+ * 33656: Src/builtin.c: different algorithm for "whence -am" to
+ produce results more consistent with "whence -m"
+
+2014-11-13 Oliver Kiddle <opk@zsh.org>
+
+ * 33669: Src/Zle/zle_utils.c, Test/X02zlevi.ztst: allow an empty
+ line to be yanked with yy by allocating 1 byte instead of 0
+
+2014-11-11 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33658: Doc/Zsh/options.yo: AUTO_CD depends on SHIN_STDIN.
+
+2014-11-09 Oliver Kiddle <opk@zsh.org>
+
+ * 33599: Jun T.: Test/comptest: workaround zpty issue that
+ causes vi test cases to fail on MacOS and FreeBSD
+
+ * 33640: clutton: Completion/BSD/Command/_kld: look in
+ /boot/modules instead of /modules for third-party modules
+
+ * 33643: Doc/Zsh/options.yo: elaborate documentation of
+ the PRIVILEGED option
+
+ * 33639: Src/Zle/zle_vi.c, Test/X02zlevi.ztst: fix bug with vi
+ operators on a blank line and with backward bracket matching
+
+ * 33659: Completion/Unix/Command/_gpg: use --dump-options to get
+ most of the gpg options to complete
+
+2014-11-08 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33655: Src/zsh.h: remove overlap of node flags.
+
+ * 33653: Src/builtin.c: handle -a option to whence in
+ combination with -m.
+
+2014-11-08 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33648: Completion/Unix/Command/_gpg: complete for gpg2 as well
+
+2014-11-06 Oliver Kiddle <opk@zsh.org>
+
+ * 33624: Src/Zle/zle_utils.c: keep region active when widget fails
+
+2014-11-07 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33607: Src/Modules/attr.c: Fix some minor problems in zattr module
+
+2014-11-06 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33614 (based on RedHat BZ-978613): Src/exec.c: signal safety
+ when updating global state in execshfunc()
+
+2014-11-05 Oliver Kiddle <opk@zsh.org>
+
+ * 33604: Src/Zle/zle_utils.c, Src/Zle/zle_vi.c, Test/X02zlevi.ztst:
+ fix change merging for vi mode where a change has just been undone
+
+2014-11-04 Oliver Kiddle <opk@zsh.org>
+
+ * 33596: Src/Zle/zle_keymap.c: make local keymap keybinding hide
+ global keymap binding that is a prefix of the local binding
+
+2014-11-02 Oliver Kiddle <opk@zsh.org>
+
+ * 33593: Src/Zle/zle_vi.c, Test/X02zlevi.ztst:
+ support numeric argument to vi-join
+
+ * 33575: Src/Zle/zle_params.c, Src/Zle/zle_utils.c: reset vi change
+ start position if text is inserted before it or on history movement
+
+2014-11-02 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33591: Src/exec.c, Test/D04parameter.ztst: don't treat an exec
+ within an subshell as an exec of the parent shell even if about
+ to exit. Fixes incorrect SHLVL in subshell.
+
+2014-10-31 Oliver Kiddle <opk@zsh.org>
+
+ * unposted: Src/jobs.c: quash compiler warning
+
+ * unposted: Test/X02zlevi.ztst: correct cursor position in test
+
+2014-10-31 Peter Stephenson <p.stephenson@samsung.com>
+
+ * unposted: .gitignore: add /.project for GitEye.
+
+ * 33582: Src/Modules/zftp.c: don't include tcp.mdh in zftp.c as
+ it only contains private module definitions.
+
+ * via private email: Jérémie Roquet: Src/options.c: more care
+ with errors using setuid().
+
+2014-10-30 Oliver Kiddle <opk@zsh.org>
+
+ * 33570, 33576: Doc/Zsh/zle.yo, Src/Zle/iwidgets.list, Src/Zle/zle.h,
+ Src/Zle/zle_misc.c, Src/Zle/zle_vi.c, Test/X02zlevi.ztst: make kill-
+ ring/yank-pop work in vi mode after vi-put-before and vi-put-after
+
+2014-10-29 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33566: Jun T.: Src/Modules/zselect.c: quash compiler warning
+
+ * 33563: Completion/Base/Core/_main_complete, Src/Zle/complist.c:
+ fix thinko in status message for INT/QUIT signals; check errflag
+ in output loops so that unexpectedly long completion listings can
+ be interrupted
+
+2014-10-29 Oliver Kiddle <opk@zsh.org>
+
+ * 33528: Src/Zle/iwidgets.list, Src/Zle/zle_vi.c,
+ Test/X02zlevi.ztst: take notice of last column position when
+ using vi-yank and an upward cursor movement
+
+2014-10-27 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33561, 33562: Src/jobs.c: The time builtin forgot to unmetafy
+ TIMEFMT.
+
+2014-10-26 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33564: Test/A05execution.ztst: more care with monitor option.
+
+ * 33542: Test/A05execution.ztst: test previous patch.
+
+ * 33531 (plus fix to test job pointer and removing
+ lastpid_status): Doc/Zsh/builtins.yo, Doc/Zsh/options.yo,
+ Src/exec.c, Src/init.c, Src/jobs.c, Src/linklist.c,
+ Src/signals.c: retain up to CHILD_MAX statuses of exited
+ background processes; remove old lastpid_status mechanism;
+ slightly improve safety of permanently allocated linked lists.
+
+2014-10-24 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33526: Completion/Unix/Type/_path_files: fix path prefix
+ handling when NO_CASE_GLOB is in effect
+
+2014-10-24 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33480 slightly tweaked: Src/Zle/zle_tricky.c: fix completion
+ after $' but before closing quote (if any).
+
+2014-10-24 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33485: Completion/Unix/Command/_su: fix a missing ;; case
+ terminator
+
+2014-10-23 Oliver Kiddle <opk@zsh.org>
+
+ * 33520: Src/Zle/zle_vi.c, Test/X02zlevi.ztst: correct cursor
+ positioning following a vi mode yank operation
+
+ * unposted: .editorconfig: specify 8 char indent for ChangeLog
+
+ * 33519: Src/Zle/zle_move.c, Test/X02zlevi.ztst: last character
+ in the buffer can be cut, changed or yanked using vi-forward-char
+
+ * 33518: Doc/Zsh/zle.yo, Src/Zle/zle.h, Src/Zle/zle_utils.c,
+ Src/Zle/zle_vi.c, Test/X02zlevi.ztst: add support for "_ vi
+ buffer and arguments to vi-set-buffer from a zle widget
+
+ * 33514: Src/Zle/zle_utils.c: even with a named vi buffer, we
+ should update the default buffer
+
+ * 33513: Src/Zle/iwidgets.list: vi mode deletions should replace
+ cut buffer not append to it
+
+ * 33512: Src/Zle/zle.h, Src/Zle/zle_main.c, Src/Zle/zle_utils.c,
+ Src/Zle/zle_vi.c: add support for "0 vi buffer and yank to it
+
+2014-10-22 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33515: Src/Zle/compmatch.c: suppress parser error messages in
+ comp_match()
+
+ * 33493: Src/Builtins/rlimits.c, Src/exec.c: use correct command
+ name in error messages about "ulimit" failure; restore internal
+ copy of limits if setrlimit() fails, so the error won't repeat
+
+2014-10-21 Oliver Kiddle <opk@zsh.org>
+
+ * 33486: Completion/X/Command/_rdesktop: new completion function
+
+ * 33485: Completion/BSD/Command/_portsnap,
+ Completion/Darwin/Command/_defaults,
+ Completion/Darwin/Command/_fink, Completion/Debian/Command/_dchroot,
+ Completion/Debian/Command/_dchroot-dsa,
+ Completion/Debian/Command/_make-kpkg,
+ Completion/Debian/Command/_update-alternatives,
+ Completion/Debian/Command/_vim-addons, Completion/Unix/Command/_du,
+ Completion/Unix/Command/_ecasound, Completion/Unix/Command/_ffmpeg,
+ Completion/Unix/Command/_ln, Completion/Unix/Command/_mail,
+ Completion/Unix/Command/_mosh, Completion/Unix/Command/_mysqldiff,
+ Completion/Unix/Command/_od, Completion/Unix/Command/_pgrep,
+ Completion/Unix/Command/_pydoc, Completion/Unix/Command/_ri,
+ Completion/Unix/Command/_su, Completion/Zsh/Command/_tcpsys,
+ Completion/Zsh/Command/_zattr: fixes for zstyle context handling
+
+ * 33481: Completion/Mandriva/Command/_rebootin,
+ Completion/Unix/Type/_directories, Completion/Unix/Type/_pdf,
+ Completion/Unix/Type/_pids, Completion/openSUSE/Command/_yast,
+ Completion/openSUSE/Command/_SUSEconfig: resolve completion
+ clashes and tidy-up SUSE/Mandriva related functions
+
+2014-10-17 Peter Stephenson <p.stephenson@samsung.com>
+
+ * see 33475: Completion/Unix/Command/_gcc: allow .cpp files as
+ input.
+
+2014-10-14 Oliver Kiddle <opk@zsh.org>
+
+ * 33455: Syohei YOSHIDA: Completion/Unix/Command/_global:
+ update GNU global option completion
+
+ * 33467: Completion/Debian/Command/_apt-move,
+ Completion/Debian/Command/_bts, Completion/Linux/Command/_sysstat,
+ Completion/Mandriva/Command/_urpmi, Completion/Redhat/Command/_rpm,
+ Completion/Solaris/Command/_ptree, Completion/Unix/Command/_arp,
+ Completion/Unix/Command/_at, Completion/Unix/Command/_bittorrent,
+ Completion/Unix/Command/_bogofilter, Completion/Unix/Command/_bpython,
+ Completion/Unix/Command/_bzr, Completion/Unix/Command/_cdrdao,
+ Completion/Unix/Command/_chmod, Completion/Unix/Command/_cpio,
+ Completion/Unix/Command/_df, Completion/Unix/Command/_django,
+ Completion/Unix/Command/_git, Completion/Unix/Command/_less,
+ Completion/Unix/Command/_lha, Completion/Unix/Command/_metaflac,
+ Completion/Unix/Command/_module, Completion/Unix/Command/_monotone,
+ Completion/Unix/Command/_mpc, Completion/Unix/Command/_netcat,
+ Completion/Unix/Command/_notmuch, Completion/Unix/Command/_pkg-config,
+ Completion/Unix/Command/_prove, Completion/Unix/Command/_rar,
+ Completion/Unix/Command/_rsync, Completion/Unix/Command/_rubber,
+ Completion/Unix/Command/_sablotron, Completion/Unix/Command/_screen,
+ Completion/Unix/Command/_stgit, Completion/Unix/Command/_strip,
+ Completion/Unix/Command/_systemd, Completion/Unix/Command/_telnet,
+ Completion/Unix/Command/_tidy, Completion/Unix/Command/_tmux,
+ Completion/Unix/Command/_vcsh, Completion/Unix/Command/_zpool,
+ Completion/Unix/Type/_users, Completion/X/Command/_urxvt,
+ Completion/X/Command/_x_utils: correct return status on functions
+ and numerous other minor fixes
+
+2014-10-13 Peter Stephenson <p.stephenson@samsung.com>
+
+ * 33459: Test/D04parameter.ztst: test for variable substitution
+ in variable splitting.
+
+2014-10-13 Oliver Kiddle <opk@zsh.org>
+
+ * 33438: Completion/Base/Utility/_sequence: use the new way of
+ splitting strings with a dynamic separator from 33423 and quote
+ separators where needed
+
+2014-10-12 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33445: Src/init.c: fix handling of SHIN_STDIN (-s) when combined
+ with INTERACTIVE (-i) on the shell invocation command line
+
+2014-10-12 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * 33423: Doc/Zsh/expn.yo, Src/subst.c: parameter expansion
+ (p) flag allows delimited strings to contain simple $param
+ expansions.
+
+2014-10-11 Barton E. Schaefer <schaefer@zsh.org>
+
+ * unposted: Test/B06fc.ztst: tests for 33429.
+
+2014-10-10 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33429: Src/builtin.c, Src/hist.c: disallow non-integer values
+ for the temporary HISTSIZE and SAVEHIST of "fc -p", and fix
+ crash on zero values for same
+
+2014-10-11 Oliver Kiddle <opk@zsh.org>
+
+ * 33424: Completion/Debian/Type/_deb_architectures,
+ Completion/Debian/Command/_apt-file,
+ Completion/Debian/Command/_dak, Completion/Debian/Command/_madison,
+ Completion/Debian/Command/_dpkg-buildpackage,
+ Completion/Debian/Command/_pbuilder,
+ Completion/Debian/Command/_reprepro,
+ Completion/Debian/Command/_svn-buildpackage: use common function
+ for completing Debian architectures
+
+2014-10-10 Oliver Kiddle <opk@zsh.org>
+
+ * 33420: Completion/Zsh/Command/_zmodload: complete -R/-m options and
+ fix feature completion
+
+ * fREW Schmidt: 33375: Completion/Unix/Command/_runit: sv completion
+
+ * Daniel Shahaf: 33396: Completion/Unix/Command/_xxd: new completion
+
+ * Yuri D'Elia: 33397: Completion/X/Command/_xautolock: new completion
+
+2014-10-09 Frank Terbeck <ft@bewatermyfriend.org>
+
+ * 33405: Functions/VCS_Info/vcs_info: Make sure maxexports
+ is set when VCS_INFO_set is called
+
+2014-10-09 Barton E. Schaefer <schaefer@zsh.org>
+
+ * 33403: Completion/Base/Utility/_call_program: be conservative
+ about redirecting stderr, the caller may have already done so
+
+2014-10-09 Marc Finet <m.dreadlock@gmail.com>
+
+ * 33391: Functions/VCS_Info/Backends/VCS_INFO_get_data_git:
+ vcs_info git: fix applied patch detection on git am
+
+2014-10-08 Peter Stephenson <p.w.stephenson@ntlworld.com>
+
+ * unposted: Config/version.mk: update to 5.0.7-dev-0 to avoid
+ installation clashes with 5.0.7.
+
2014-10-07 Peter Stephenson <p.w.stephenson@ntlworld.com>
* unposted: Config/version.mk: 5.0.7
+2014-10-06 Mikael Magnusson <mikachu@gmail.com>
+
+ * 33365: Src/exec.c: avoid buffer overflow for very long fds in >&
+ fd syntax.
+
2014-10-06 Peter Stephenson <p.stephenson@samsung.com>
* unposted (discussed offline): README: update description of
@@ -12,7 +1815,7 @@
* 33354: Src/jobs.c, Test/A05execution.ztst: when backgrounding
a pipeline, close all pipe descriptors in the parent; add test
for both this and 33345+33346
-
+
2014-10-03 Bart Schaefer <schaefer@zsh.org>
* 33346: Src/parse.c: another bit of the 33345 repair
@@ -1401,7 +3204,7 @@
format unusable.
* unposted but c.f. 32231: Doc/Zsh/compsys.yo: the parameter
- 'line' doesn't include the original command.
+ 'line' doesn't include the original command.
* Jun T: 32231: Completion/Unix/Command/_chmod: was confused by
options before the mode argument.
@@ -1483,7 +3286,7 @@
2013-12-20 Barton E. Schaefer <schaefer@zsh.org>
* 32172; Test/A05execution.ztst: regression test for 32171
-
+
* 32171: Src/exec.c: fix leaked pipe descriptor that could
deadlock a pipeline from a complex shell construct or function
into an external command
@@ -2604,7 +4407,7 @@
completion: functions.
* 31155: Doc/Zsh/contrib.yo, Functions/Misc/zcalc: minor
- extra zcalc features and documentation.
+ extra zcalc features and documentation.
2013-03-15 Peter Stephenson <p.w.stephenson@ntlworld.com>
diff --git a/Completion/BSD/Command/_kld b/Completion/BSD/Command/_kld
index b967f33c4..34f26f1e9 100644
--- a/Completion/BSD/Command/_kld
+++ b/Completion/BSD/Command/_kld
@@ -4,7 +4,7 @@
_kld_module() {
local ret=1
- compadd "$@" - /boot/kernel/*.ko(-.:t) /modules/*.ko(-.:t) && ret=0
+ compadd "$@" - /boot/{kernel,modules}/*.ko(-.:t) && ret=0
_files "$@" -g '*.ko(-.)' && ret=0
return ret
diff --git a/Completion/BSD/Command/_mixerctl b/Completion/BSD/Command/_mixerctl
new file mode 100644
index 000000000..a43aed4cb
--- /dev/null
+++ b/Completion/BSD/Command/_mixerctl
@@ -0,0 +1,11 @@
+#compdef mixerctl
+
+: ${(A)_cache_mixerctlvars:=${${(f)"$(mixerctl -a)"}%%=*}}
+_arguments -s -S -A "-*" \
+ '(-q -t *)-a[Print all device variables and their current values]' \
+ '-f[Specify an alternative audio mixing device]:file:_files -g "*(-%c)"' \
+ '(-q -t)-n[Suppress printing of the variable name]' \
+ '(-a -n -v)-q[Suppress all printing when setting a variable]' \
+ '(-a -n -v)-t[Attempt to select the next possible value of an enum]' \
+ '(-q -t)-v[Show all possible values of variables]' \
+ '(-a)*:mixerctl varible:_multi_parts -i -S = -q . _cache_mixerctlvars'
diff --git a/Completion/BSD/Command/_portsnap b/Completion/BSD/Command/_portsnap
index db71fbc60..0803a842e 100644
--- a/Completion/BSD/Command/_portsnap
+++ b/Completion/BSD/Command/_portsnap
@@ -1,6 +1,6 @@
#compdef portsnap
-local context state line
+local curcontext="$curcontext" state line
typeset -A opt_args
flags=(
diff --git a/Completion/BSD/Type/_jails b/Completion/BSD/Type/_jails
new file mode 100644
index 000000000..36bffeceb
--- /dev/null
+++ b/Completion/BSD/Type/_jails
@@ -0,0 +1,5 @@
+#autoload
+
+jails=( ${${${${(f)"$(_call_program jails jls -n)"}##*jid=}/ name=/:}%% *} )
+
+_describe -t jails jail jails "$@"
diff --git a/Completion/Base/Completer/_expand b/Completion/Base/Completer/_expand
index e52144cb7..3c76e1328 100644
--- a/Completion/Base/Completer/_expand
+++ b/Completion/Base/Completer/_expand
@@ -87,7 +87,7 @@ if [[ "$force" = *s* ]] ||
setopt aliases
eval 'exp=( ${${(e)exp//\\[
-]/ }//(#b)([
+]/ }//(#b)([ \\
])/\\$match[1]} )' 2>/dev/null
setopt NO_aliases
else
diff --git a/Completion/Base/Completer/_external_pwds b/Completion/Base/Completer/_external_pwds
new file mode 100644
index 000000000..4ad50f02b
--- /dev/null
+++ b/Completion/Base/Completer/_external_pwds
@@ -0,0 +1,39 @@
+#autoload
+
+# Completes current directories of other zsh processes
+# this is intended to be used via _generic bound to a
+# different key. Note that pattern matching is enabled.
+
+local -a expl
+local -au dirs
+
+# undo work _main_complete did to remove the tilde
+PREFIX="$IPREFIX$PREFIX"
+IPREFIX=
+SUFFIX="$SUFFIX$ISUFFIX"
+ISUFFIX=
+
+[[ -o magicequalsubst ]] && compset -P '*='
+
+case $OSTYPE in
+ solaris*)
+ dirs=(
+ ${(M)${${(f)"$(pgrep -U $UID -x zsh|xargs pwdx 2>/dev/null)"}:#$$:*}%%/*}
+ )
+ ;;
+ linux*)
+ dirs=( /proc/${^$(pidof zsh):#$$}/cwd(N:A) )
+ dirs=( $^dirs(N^@) )
+ ;;
+ *)
+ if (( $+commands[lsof] )); then
+ dirs=( ${${${(M)${(f)"$(lsof -a -u $EUID -c zsh -p \^$$ -d cwd -F n -w
+ 2>/dev/null)"}:#n*}#?}%% \(*} )
+ fi
+ ;;
+esac
+dirs=( ${(D)dirs} )
+
+compstate[pattern_match]='*'
+_wanted directories expl 'current directory from other shell' \
+ compadd -M "r:|/=* r:|=*" -f -a dirs
diff --git a/Completion/Base/Completer/_history b/Completion/Base/Completer/_history
index 63878ac1c..cd69ca17b 100644
--- a/Completion/Base/Completer/_history
+++ b/Completion/Base/Completer/_history
@@ -51,9 +51,14 @@ ISUFFIX=
# We skip the first element of historywords so the current word doesn't
# interfere with the completion
+local -a hslice
while [[ $compstate[nmatches] -eq 0 && beg -lt max ]]; do
+ if [[ -n $compstate[quote] ]]
+ then hslice=( ${(Q)historywords[beg,beg+slice]} )
+ else hslice=( ${historywords[beg,beg+slice]} )
+ fi
_wanted "$opt" history-words expl 'history word' \
- compadd -Q -a 'historywords[beg,beg+slice]'
+ compadd -Q -a hslice
(( beg+=slice ))
done
diff --git a/Completion/Base/Core/_main_complete b/Completion/Base/Core/_main_complete
index e881ea6a1..977ab49ee 100644
--- a/Completion/Base/Core/_main_complete
+++ b/Completion/Base/Core/_main_complete
@@ -43,6 +43,8 @@ local -a precommands
typeset -U _lastdescr _comp_ignore _comp_colors
+{
+
[[ -z "$curcontext" ]] && curcontext=:::
zstyle -s ":completion:${curcontext}:" insert-tab tmp || tmp=yes
@@ -66,6 +68,16 @@ if [[ "$compstate[insert]" = tab* ]]; then
compstate[insert]="${compstate[insert]//tab /}"
fi
+# Second attempt at GLOB_COMPLETE
+
+if [[ "$compstate[pattern_match]" = "*" &&
+ "$_lastcomp[unambiguous]" = "$PREFIX" &&
+ -n "$_lastcomp[unambiguous_cursor]" ]]; then
+ integer upos="$_lastcomp[unambiguous_cursor]"
+ SUFFIX="$PREFIX[upos,-1]$SUFFIX"
+ PREFIX="$PREFIX[1,upos-1]"
+fi
+
# Special completion contexts after `~' and `='.
if [[ -z "$compstate[quote]" ]]; then
@@ -128,8 +140,11 @@ _completer_num=1
# We assume localtraps to be in effect here ...
integer SECONDS=0
-trap 'zle -M "Killed by signal in ${funcstack[0]} after ${SECONDS}s";
- zle -R; return 130' INT QUIT
+TRAPINT TRAPQUIT() {
+ zle -M "Killed by signal in ${funcstack[2]} after ${SECONDS}s";
+ zle -R
+ return 130
+}
# Call the pre-functions.
@@ -346,17 +361,20 @@ fi
( "$_comp_force_list" = ?* && nm -ge _comp_force_list ) ]] &&
compstate[list]="${compstate[list]//messages} force"
-if [[ "$compstate[old_list]" = keep ]]; then
- if [[ $_saved_colors_set = 1 ]]; then
- ZLS_COLORS="$_saved_colors"
+} always {
+ # Stuff we always do to clean up.
+ if [[ "$compstate[old_list]" = keep ]]; then
+ if [[ $_saved_colors_set = 1 ]]; then
+ ZLS_COLORS="$_saved_colors"
+ else
+ unset ZLS_COLORS
+ fi
+ elif (( $#_comp_colors )); then
+ ZLS_COLORS="${(j.:.)_comp_colors}"
else
unset ZLS_COLORS
fi
-elif (( $#_comp_colors )); then
- ZLS_COLORS="${(j.:.)_comp_colors}"
-else
- unset ZLS_COLORS
-fi
+}
# Now call the post-functions.
diff --git a/Completion/Base/Utility/_arguments b/Completion/Base/Utility/_arguments
index d70c44259..1f35e8d43 100644
--- a/Completion/Base/Utility/_arguments
+++ b/Completion/Base/Utility/_arguments
@@ -26,7 +26,7 @@ if (( long )); then
if (( ! ${(P)+name} )); then
local iopts sopts pattern tmpo dir cur cache
- typeset -U lopts
+ typeset -Ua lopts
cache=()
diff --git a/Completion/Base/Utility/_call_program b/Completion/Base/Utility/_call_program
index b65764827..010e09476 100644
--- a/Completion/Base/Utility/_call_program
+++ b/Completion/Base/Utility/_call_program
@@ -2,8 +2,8 @@
local tmp err_fd=-1
-if (( ${debug_fd:--1} > 2 ))
-then exec {err_fd}>&2 # debug_fd is saved stderr, 2 is log file
+if (( ${debug_fd:--1} > 2 )) || [[ ! -t 2 ]]
+then exec {err_fd}>&2 # debug_fd is saved stderr, 2 is trace or redirect
else exec {err_fd}>/dev/null
fi
diff --git a/Completion/Base/Utility/_describe b/Completion/Base/Utility/_describe
index 1a9f52f5d..ab7200517 100644
--- a/Completion/Base/Utility/_describe
+++ b/Completion/Base/Utility/_describe
@@ -6,23 +6,28 @@ local _opt _expl _tmpm _tmpd _mlen _noprefix
local _type=values _descr _ret=1 _showd _nm _hide _args _grp _sep
local csl="$compstate[list]" csl2
local _oargv _argv _new _strs _mats _opts _i _try=0
+local OPTIND OPTARG
+local -a _jvx12
# Get the option.
-if [[ "$1" = -o ]]; then
- _type=options
- shift
-elif [[ "$1" = -O ]]; then
- _type=options
- _noprefix=1
- shift
-elif [[ "$1" = -t ]]; then
- _type="$2"
- shift 2
-elif [[ "$1" = -t* ]]; then
- _type="${1[3,-1]}"
- shift
-fi
+while getopts "oOt:12JVx" _opt; do
+ case $_opt in
+ (o)
+ _type=options;;
+ (O)
+ _type=options
+ _noprefix=1
+ ;;
+ (t)
+ _type="$OPTARG"
+ ;;
+ (1|2|J|V|x)
+ _jvx12+=(-$_opt)
+ esac
+done
+shift $(( OPTIND - 1 ))
+unset _opt
[[ "$_type$_noprefix" = options && ! -prefix [-+]* ]] && \
zstyle -T ":completion:${curcontext}:options" prefix-needed &&
@@ -53,7 +58,7 @@ fi
_tags "$_type"
while _tags; do
- while _next_label "$_type" _expl "$_descr"; do
+ while _next_label $_jvx12 "$_type" _expl "$_descr"; do
if (( $#_grp )); then
diff --git a/Completion/Base/Utility/_sequence b/Completion/Base/Utility/_sequence
index 391e5f78f..f52955f46 100644
--- a/Completion/Base/Utility/_sequence
+++ b/Completion/Base/Utility/_sequence
@@ -7,11 +7,11 @@
# -s sep : specify separator [defaults to comma]
# -d : duplicate values allowed
-local curcontext="$curcontext" nm="$compstate[nmatches]" pre nosep minus
+local curcontext="$curcontext" nm="$compstate[nmatches]" pre qsep nosep minus
local -a sep num pref suf end uniq dedup
zparseopts -D -a opts s:=sep n:=num p:=pref i:=pref P:=pref I:=suf S:=suf q=suf r:=suf R:=suf C:=cont d=uniq M: J: X: x:
-(( $#cont )) && curcontext="$curcontext%:*}:$cont[2]"
+(( $#cont )) && curcontext="${curcontext%:*}:$cont[2]"
(( $#sep )) || sep[2]=,
if (( $+suf[(r)-S] )); then
@@ -19,20 +19,20 @@ if (( $+suf[(r)-S] )); then
(( $#end )) && compset -S ${end}\* && suf=() && nosep=1
fi
+qsep="${sep[2]}"
+compquote -p qsep
if (( ! $#uniq )); then
(( $+pref[(r)-P] )) && pre="${(q)pref[pref[(i)-P]+1]}"
- typeset -T unique="${PREFIX#$pre}" uniq $sep[2]
- dedup=( ${(q)uniq[1,-2]} )
- unique="${SUFFIX}"
- dedup+=( ${(q)uniq[2,-1]} )
+ dedup=( "${(@)${(@ps.$qsep.)PREFIX#$pre}[1,-2]}" "${(@)${(@ps.$qsep.)SUFFIX}[2,-1]}" )
+ [[ -n $compstate[quoting] ]] || dedup=( ${(Q)dedup} )
fi
-if (( ! $#num )) || (( num[2] > 1 )) && ! compset -P $(( num[2] - 1 )) \*$sep[2]; then
- (( nosep )) || suf=( -S $sep[2] -r "$end[1]${sep[2][1]} \t\n\-" )
- compset -S ${sep[2]}\* && suf=()
- compset -P \*$sep[2] && pref=()
-else
+if (( $#num )) && compset -P $(( num[2] - 1 )) \*${(q)qsep}; then
pref=()
+else
+ (( ! nosep && (!$#num || num[2] > 1) )) && suf=( -S ${qsep} -r "$end[1]${(q)qsep[1]} \t\n\-" )
+ compset -S ${(q)qsep}\* && suf=()
+ compset -P \*${(q)qsep} && pref=()
fi
(( minus = argv[(ib:2:)-] ))
diff --git a/Completion/Base/Utility/_store_cache b/Completion/Base/Utility/_store_cache
index 86e72e9a9..8feaee6f7 100644
--- a/Completion/Base/Utility/_store_cache
+++ b/Completion/Base/Utility/_store_cache
@@ -46,8 +46,15 @@ if zstyle -t ":completion:${curcontext}:" use-cache; then
for var; do
case ${(Pt)var} in
(*readonly*) ;;
- (*(association|array)*) print -r "$var=( ${(kv@Pqq)^^var} )";;
- (*) print -r "$var=${(Pqq)^^var}";;
+ (*(association|array)*)
+ # Dump the array as a here-document to reduce parsing overhead
+ # when reloading the cache with "source" from _retrieve_cache
+ print -r "$var=( "'"${(zQ)$(<<\EO:'"$var"
+ print -r "${(kv@Pqq)^^var}"
+ print -r "EO:$var"
+ print -r ')}" )'
+ ;;
+ (*) print -r "$var=${(Pqq)^^var}";;
esac
done >! "$_cache_dir/$_cache_ident"
else
diff --git a/Completion/Base/Widget/_complete_debug b/Completion/Base/Widget/_complete_debug
index 604486376..85a0f372a 100644
--- a/Completion/Base/Widget/_complete_debug
+++ b/Completion/Base/Widget/_complete_debug
@@ -9,6 +9,8 @@ local pager w="${(qq)words}"
integer debug_fd=-1
{
if [[ -t 2 ]]; then
+ zmodload -F zsh/files b:zf_ln 2>/dev/null &&
+ zf_ln -fn =(<<<'') $tmp &&
exec {debug_fd}>&2 2>| $tmp
fi
diff --git a/Completion/Darwin/Command/_defaults b/Completion/Darwin/Command/_defaults
index 7818e0379..ca5d87e65 100644
--- a/Completion/Darwin/Command/_defaults
+++ b/Completion/Darwin/Command/_defaults
@@ -25,8 +25,9 @@ _defaults(){
_1st_arguments=( read read-type write rename delete domains find help )
local curcontext="$curcontext" state line expl
+ typeset -A opt_args
- _arguments -A '-*' \
+ _arguments -C -A '-*' \
'(-currentHost)-host:host:_hosts' \
'(-host)-currentHost' \
'*::command:->subcmd' && return 0
diff --git a/Completion/Darwin/Command/_fink b/Completion/Darwin/Command/_fink
index 55c9e8da5..04a067ec1 100644
--- a/Completion/Darwin/Command/_fink
+++ b/Completion/Darwin/Command/_fink
@@ -86,7 +86,7 @@ _fink(){
'cleanup:removes obsolete package files'
)
- local context state line expl
+ local curcontext="$curcontext" state line expl
local -A opt_args
_arguments \
@@ -136,8 +136,8 @@ _fink(){
'(-t --tab)'{-t,--tab}'[output the list with tabs as field delimiter]' \
'(-w --width)'{-w=,--width=}'[width of display]:number or "auto"' \
'(1 : -)'{-h,--help}'[display help text]' \
- '1: :->pkgs' && return 0
-
+ '1: :->pkgs' && return
+
if [[ "$state" == pkgs ]]; then
_fink_get_packages
_wanted packages expl 'package hint' compadd -a packages
@@ -161,6 +161,7 @@ _fink(){
#scanpackages)
#checksums)
#cleanup)
+ *) _default ;;
esac
}
diff --git a/Completion/Debian/Command/_apt b/Completion/Debian/Command/_apt
index bf5343a94..db4ceef10 100644
--- a/Completion/Debian/Command/_apt
+++ b/Completion/Debian/Command/_apt
@@ -455,6 +455,7 @@ _apt-get () {
--tar-only:bool \
--arch-only:bool \
--allow-unauthenticated:bool \
+ --auto-remove:bool \
-- \
/$'update\0'/ \| \
/$'upgrade\0'/ \| \
diff --git a/Completion/Debian/Command/_apt-file b/Completion/Debian/Command/_apt-file
index eddbbdcf5..98a93fdd3 100644
--- a/Completion/Debian/Command/_apt-file
+++ b/Completion/Debian/Command/_apt-file
@@ -1,55 +1,59 @@
#compdef apt-file
-_apt-file() {
- local -a arguments
- local state line cmds
- arguments=(
- '(--cache -c)'{--cache,-c}'[cache directory]:directory:_directories'
- '(-v --verbose)'{-v,--verbose}'[verbose]'
- '(--cdrom-mount -d)'{--cdrom-mount,-d}'[cdrom mount point]:directory:_directories'
- '(--ignore-case -i)'{--ignore-case,-i}'[ignore case]'
- '(--regexp -r)'{--regexp,-r}'[regular expression]'
- '(-V --version)'{-V,--version}'[version]'
- '(-a --architecture)'{-a,--architecture}'[architecture]:architecture:(alpha arm hppa hurd-i386 i386 ia64 m68k mips mipsel powerpc s390 sparc)'
- '(-s --sources-list)'{-s,--sources-list}'[source.list file]:file:_files'
- '(-l --package-only)'{-l,--package-only}'[only display package name]'
- '(-F --fixed-string)'{-F,--fixed-string}'[do not expand search pattern]'
- '(-y --dummy)'{-y,--dummy}'[run in dummy mode]'
- '(-h --help)'{-h,--help}'[display help screen]'
- '1: :->cmds'
- '*: :->args'
- )
- _arguments -S $arguments
+local curcontext="$curcontext" state line expl cmds ret=1
+typeset -A opt_args
- case $state in
- cmds)
- cmds=(
- 'update:resynchronize package contents'
- 'search:search in which package file is included'
- 'list:list contents of a package'
- 'show:alias for list'
- 'purge:remove all Contents-<ARCH>.gz files in cache directory'
- )
- _describe -t commands 'apt-list command' cmds && ret=0
+_arguments -C -S \
+ '(--cache -c)'{--cache,-c}'[cache directory]:directory:_directories' \
+ '(-v --verbose)'{-v,--verbose}'[verbose]' \
+ '(--cdrom-mount -d)'{--cdrom-mount,-d}'[cdrom mount point]:directory:_directories' \
+ '(--from-file -f --from-deb -D)'{--from-file,-f}'[read patterns from given file]' \
+ '(--from-deb -D --from-file -f)'{--from-dev,-D}'[use contents of given .deb archives as patterns]' \
+ '(--ignore-case -i)'{--ignore-case,-i}'[ignore case]' \
+ '(--regexp -x)'{--regexp,-x}'[regular expression]' \
+ '(-V --version)'{-V,--version}'[version]' \
+ '(-a --architecture)'{-a,--architecture}'[architecture]:architecture:_deb_architectures' \
+ '(-s --sources-list)'{-s,--sources-list}'[source.list file]:file:_files' \
+ '(-l --package-only)'{-l,--package-only}'[only display package name]' \
+ '(-N --non-interactive)'{-N,--non-interactive}'[skip schemes requiring user input]' \
+ '(-F --fixed-string)'{-F,--fixed-string}'[do not expand search pattern]' \
+ '(-y --dummy)'{-y,--dummy}'[run in dummy mode]' \
+ '(-)'{-h,--help}'[display help screen]' \
+ '1: :->cmds' \
+ '*: :->args' && ret=0
+
+case $state in
+ cmds)
+ cmds=(
+ 'update:resynchronize package contents'
+ {find,search}:'search in which package file is included'
+ {list,show}:'list contents of a package'
+ 'purge:remove all Contents-<ARCH>.gz files in cache directory'
+ )
+ _describe -t commands 'apt-list command' cmds
+ ;;
+ args)
+ case $line[1] in
+ search|find)
+ if (( $#opt_args[(I)(-D|--from-deb)] )); then
+ _wanted files expl 'debian package' _files -g '*.deb(-.)'
+ elif (( $#opt_args[(I)(-f|--from-file)] )); then
+ _files
+ else
+ _message -e patterns "pattern"
+ fi
+ ;;
+ list|show)
+ _deb_packages avail
;;
- args)
- case $line[1] in
- search)
- _message "pattern"
- ;;
- list|show)
- _deb_packages avail
- ;;
- update|purge)
- # do nothing
- ;;
- *)
- _message "command $line[1] not available"
- ;;
- esac
+ update|purge)
+ # do nothing
+ ;;
+ *)
+ _message "command $line[1] not available"
;;
esac
+ ;;
+esac && ret=0
-}
-
-_apt-file "$@"
+return ret
diff --git a/Completion/Debian/Command/_apt-move b/Completion/Debian/Command/_apt-move
index a72378e6f..6911ef6f1 100644
--- a/Completion/Debian/Command/_apt-move
+++ b/Completion/Debian/Command/_apt-move
@@ -1,6 +1,6 @@
#compdef apt-move
-local curcontext="$curcontext" state line cmds ret=1
+local curcontext="$curcontext" state line expl cmds ret=1
typeset -A opt_args
_arguments -C \
@@ -45,7 +45,10 @@ case $state in
_files -g "*.d(sc|eb)(-.)" && ret=0
;;
listbin)
- _wanted lists expl list compadd mirror sync repo
+ _wanted lists expl list compadd mirror sync repo && ret=0
+ ;;
+ *)
+ _default && ret=0
;;
esac
;;
diff --git a/Completion/Debian/Command/_bts b/Completion/Debian/Command/_bts
index 4907d15c1..9f1f77bf4 100644
--- a/Completion/Debian/Command/_bts
+++ b/Completion/Debian/Command/_bts
@@ -40,10 +40,12 @@ case "$words[1]" in
;;
(show|bugs)
if [[ CURRENT -eq 2 ]]; then
- _wanted package expl 'package' _deb_packages avail
- _wanted maintainer expl 'package maintainer' compadd $DEBEMAIL
+ _alternative \
+ 'packages:package:_deb_packages avail' \
+ "emails:package maintainer:compadd $DEBEMAIL"
+ else
+ _wanted sep expl 'separator' compadd -S ' ' , .
fi
- _wanted sep expl 'separator' compadd -S ' ' , .
;;
reopen)
if [[ CURRENT -eq 2 ]]; then
diff --git a/Completion/Debian/Command/_dak b/Completion/Debian/Command/_dak
index 840fc0017..086196c4a 100644
--- a/Completion/Debian/Command/_dak
+++ b/Completion/Debian/Command/_dak
@@ -1,31 +1,26 @@
#compdef dak
-local curcontext="$curcontext" state line expl cmd args ret=1
-typeset -A opt_args
+local expl cmd args ret=1
-_arguments -C \
- '1: :->cmd' \
- '*:: :->args' && ret=0
-
-if (( ! $+_dak_cmds )); then
+if (( CURRENT == 2 )); then
+ if (( ! $+_dak_cmds )); then
typeset -gH _dak_cmds
_dak_cmds=(${${${(f)${"$(_call_program dak dak --help)"#*Availa#ble commands:}}#[^a-z] ##}%%[ ]*})
-fi
+ fi
-if [[ $state != 'args' ]]; then
- _describe -t subcommand 'subcommand' _dak_cmds
- return 0
+ _describe -t subcommands 'subcommand' _dak_cmds
+ return
fi
-cmd="$words[1]"
-curcontext="${curcontext%:*:*}:dak-$cmd:"
+cmd="$words[2]"
+local curcontext="${curcontext%:*:*}:dak-$cmd:"
args=( '(-)'{--help,-h}'[show help message]' )
case $cmd in
(ls)
args+=(
- '(-a --architecture)'{-a,--architecture=}':arch:_values -s , "architecture list" source all alpha amd64 arm hppa hurd-i386 i386 ia64 mips mipsel'
+ '(-a --architecture)'{-a,--architecture=}':arch:_sequence _deb_architectures -a "all source"'
'(-b --binary-type)'{-b,--binary-type=}':type:(deb udeb)'
'(-c --component)'{-c,--component=}':component:_values -s , "component list" main contrib non-free'
'(-g --greaterorequal)'{-g,--greaterorequal}
@@ -70,7 +65,7 @@ case $cmd in
;;
(rm)
args+=(
- '(-a --architecture)'{-a,--architecture=}':arch:_values -s , "architecture list" source all alpha amd64 arm hppa hurd-i386 i386 ia64 mips mipsel'
+ '(-a --architecture)'{-a,--architecture=}':arch:_sequence _deb_architectures -a "all source"'
'(-b --binary)'{-b,--binary}'[remove binaries only]'
'(-c --component)'{-c,--component=}':component:_values -s , "component list" main contrib non-free'
'(-C --carbon-copy)'{-C,--carbon-copy=}':cc address:_email_addresses'
@@ -96,7 +91,7 @@ case $cmd in
(make-suite-file-list)
args+=(
- '(-a --architecture)'{-a,--architecture=}':arch:_values -s , "architecture list" source all alpha amd64 arm hppa hurd-i386 i386 ia64 mips mipsel'
+ '(-a --architecture)'{-a,--architecture=}':arch:_sequence _deb_architectures -a "all source"'
'(-c --component)'{-c,--component=}':component:_values -s , "component list" main contrib non-free'
'(-n --no-delete)'{-n,--no-delete}'[do not delete older versions]'
'(-s --suite)'{-s,--suite=}':suite:_values -s , "suite list" oldstable stable testing unstable experimental'
@@ -239,10 +234,10 @@ case $cmd in
;;
(*)
- _files
+ args+=( '*: :_default' )
;;
esac
_arguments -s "$args[@]" && ret=0
-return $ret
+return ret
diff --git a/Completion/Debian/Command/_dchroot b/Completion/Debian/Command/_dchroot
index 43a797d83..c26e5691a 100644
--- a/Completion/Debian/Command/_dchroot
+++ b/Completion/Debian/Command/_dchroot
@@ -20,8 +20,8 @@ _arguments -S \
'*::arguments: _normal' && return 0
case "$state" in
- (chroot)
- _wanted tag expl 'chroot' \
- compadd ${(os:,:)${${${"$(dchroot -l )"#*: }// /}//[[\]]/,}}
- ;;
+ chroot)
+ _wanted -C $context chroots expl 'chroot' \
+ compadd ${(os:,:)${${${"$(_call_program chroots dchroot -l )"#*: }// /}//[[\]]/,}}
+ ;;
esac
diff --git a/Completion/Debian/Command/_dchroot-dsa b/Completion/Debian/Command/_dchroot-dsa
index bed4bcf19..d4668b553 100644
--- a/Completion/Debian/Command/_dchroot-dsa
+++ b/Completion/Debian/Command/_dchroot-dsa
@@ -19,8 +19,8 @@ _arguments -S \
'*::arguments: _normal' && return 0
case "$state" in
- (chroot)
- _wanted tag expl 'chroot' \
- compadd ${(os:,:)${${${"$(dchroot -l )"#*: }// /}//[[\]]/,}}
- ;;
+ chroot)
+ _wanted -C $context chroots expl 'chroot' \
+ compadd ${(os:,:)${${${"$(_call_program chroots dchroot -l )"#*: }// /}//[[\]]/,}}
+ ;;
esac
diff --git a/Completion/Debian/Command/_dpkg-buildpackage b/Completion/Debian/Command/_dpkg-buildpackage
index d6f5c5f0a..b0eea5783 100644
--- a/Completion/Debian/Command/_dpkg-buildpackage
+++ b/Completion/Debian/Command/_dpkg-buildpackage
@@ -5,7 +5,7 @@ _arguments \
'-B[binary-only build, no source or arch-indep binaries]' \
'-S[source-only build, no binaries]' \
'-s-:source generation:((i\:default a\:force\ inclusion\ of\ original\ source d\:force\ exclusion\ of\ original\ source))' \
- '-a-:architecture:(alpha amd64 arm hppa hurd-i386 i386 ia64 m68k mips mipsel powerpc s390 sparc)' \
+ '-a-:architecture:_deb_architectures' \
'-v-:version:' \
'-C-:changes description:_files' \
'-m-:maintainer address:_email_addresses' \
diff --git a/Completion/Debian/Command/_dpkg-repack b/Completion/Debian/Command/_dpkg-repack
index 5d625a5ce..37f800516 100644
--- a/Completion/Debian/Command/_dpkg-repack
+++ b/Completion/Debian/Command/_dpkg-repack
@@ -2,6 +2,6 @@
_arguments \
'--root=[take package from filesystem rooted on <dir>]:root dir:_files -/' \
- '--arch=[force the package to be built for architecture <arch>]:architecture:(alpha amd64 arm hppa hurd-i386 i386 ia64 m68k mips mipsel powerpc s390 sparc)' \
+ '--arch=[force the package to be built for specified architecture]:architecture:_deb_architectures' \
'--generate[generate build directory but do not build deb]' \
'*:package:_deb_packages xinstalled'
diff --git a/Completion/Debian/Command/_lintian b/Completion/Debian/Command/_lintian
index 554be4550..773e7a182 100644
--- a/Completion/Debian/Command/_lintian
+++ b/Completion/Debian/Command/_lintian
@@ -31,7 +31,7 @@ case "$service" in
'--archivedir:archive directory:_files -/' \
'--dist:distribution:(woody sarge sid)' \
'--section:release:(main contrib non-free)' \
- '--arch:architecture:(alpha arm hppa hurd-i386 i386 ia64 m68k mips mipsel powerpc s390 sparc)' \
+ '--arch:architecture:_deb_architectures' \
'--root:root directory:_files -/' \
'(-a --all)'{-a,--all}'[check all packages in the distribution]' \
'(-b --binary)'{-b,--binary}'[the following packages are binary]' \
diff --git a/Completion/Debian/Command/_madison b/Completion/Debian/Command/_madison
index fc4821e91..445b79a45 100644
--- a/Completion/Debian/Command/_madison
+++ b/Completion/Debian/Command/_madison
@@ -1,7 +1,7 @@
#compdef madison rmadison
_arguments \
- '(-a --architecture)'{-a,--architecture=}':arch:_values -s , "architecture list" source all alpha arm hppa hurd-i386 i386 ia64 mips mipsel' \
+ '(-a --architecture)'{-a,--architecture=}':arch:_sequence _deb_architectures -a "all source" -' \
'(-b --binary)'{-b,--binary-type=}':type:(deb udeb)' \
'(-c --component)'{-c,--component=}':component:_values -s , "component list" main contrib non-free' \
'(-g --greaterorequal)'{-g,--greaterorequal} \
diff --git a/Completion/Debian/Command/_make-kpkg b/Completion/Debian/Command/_make-kpkg
index c079d9aa0..55adf882f 100644
--- a/Completion/Debian/Command/_make-kpkg
+++ b/Completion/Debian/Command/_make-kpkg
@@ -1,9 +1,9 @@
#compdef make-kpkg
-local context state line
+local curcontext="$curcontext" state line
typeset -A opt_args
-_arguments \
+_arguments -C \
'--help[display help message]' \
'--revision[change Debian revision number]:number:' \
'--append-to-version[specify additional kernel sub-version]:suffix:' \
@@ -45,7 +45,7 @@ _arguments \
configure\:"configure the kernel" \
debian\:"creates the debian/ directory" \
libc-kheaders\:"create the kernel headers package needed by libc" \
- ))' && return 0
+ ))' && return
case "$state" in
(addedmodules)
diff --git a/Completion/Debian/Command/_pbuilder b/Completion/Debian/Command/_pbuilder
index 7811d567b..9322d036a 100644
--- a/Completion/Debian/Command/_pbuilder
+++ b/Completion/Debian/Command/_pbuilder
@@ -14,8 +14,8 @@ else
'--buildresult:location:_files -/' \
'--mirror:URL:_urls' \
'--othermirror:URL:_urls' \
- '--distribution:suite:(breezy dapper edgy etch feisty gutsy hardy hoary intrepid jaunty karmic lenny lucid potato sarge sid squeeze warty woody' \
- '--architecture:architecture:(alpha amd64 armel hppa hurd-i386 i386 ia64 m68k mips mipsel powerpc s390 sparc)' \
+ '--distribution:suite:(breezy dapper edgy etch feisty gutsy hardy hoary intrepid jaunty jessie karmic lenny lucid potato sarge sid squeeze warty woody' \
+ '--architecture:architecture:i_deb_architectures' \
'--components:component:(main contrib non-free)' \
'--override-config' \
'--hookdir:location:_files -/' \
diff --git a/Completion/Debian/Command/_reprepro b/Completion/Debian/Command/_reprepro
index 44ed1548c..d1e124eef 100644
--- a/Completion/Debian/Command/_reprepro
+++ b/Completion/Debian/Command/_reprepro
@@ -1,10 +1,10 @@
#compdef reprepro
-local context state line distfile
+local curcontext="$curcontext" state line expl distfile ret=1
typeset -A opt_args
local -a codenames
-_arguments \
+_arguments -C \
'(-h --help)'{-h,--help}'[display help]' \
'*'{-v,-V,--verbose}'[be more verbose]' \
'--silent[be less verbose]' \
@@ -17,7 +17,7 @@ _arguments \
'--listdir:list dir:_files -/' \
'--methoddir:method dir:_files -/' \
'(-C --component)'{-C,--component}':component:(component1 component2)' \
- '(-A --architecture)'{-A,--architecture}':architecture:(amd64 sparc)' \
+ '(-A --architecture)'{-A,--architecture}':architecture:_sequence -s "|" _deb_architectures -' \
'(-T --type)'{-T,--type}':file type:(dsc deb udeb)' \
'(-S --section)'{-S,--section}':section:(section1 section2)' \
'(-P --priority)'{-P,--priority}':priority:(high low)' \
@@ -40,12 +40,11 @@ _arguments \
rereference dumpreferences dumpunreferenced deleteunreferenced
reoverride dumptracks retrack removealltracks removetrack tidytracks
copy clearvanished gensnapshot rerunnotifiers)' \
- '*::subcmd:->subcmd' && return 0
+ '*::subcmd:->subcmd' && ret=0
case "$state" in
- (subcmd)
-
- case "$words[1]" in
+ subcmd)
+ case "$words[1]" in
(export|update|iteratedupdate|checkupdate|predelete|pull|checkpull|check)
if [[ -n "$opt_args[--confdir]" ]]; then
distfile=${opt_args[--confdir]}/distributions
@@ -60,11 +59,13 @@ case "$state" in
fi
codenames=($(awk '/^[Cc][Oo][Dd][Ee][Nn][Aa][Mm][Ee]: / {$1="";print}' "$distfile"))
- _wanted -V 'codenames' expl 'codename' compadd -a codenames
- ;;
+ _wanted -V 'codenames' expl 'codename' compadd -a codenames && ret=0
+ ;;
(*)
- _files
- ;;
- esac
+ _files && ret=0
+ ;;
+ esac
;;
esac
+
+return ret
diff --git a/Completion/Debian/Command/_svn-buildpackage b/Completion/Debian/Command/_svn-buildpackage
index 0b4d50125..e0f925896 100644
--- a/Completion/Debian/Command/_svn-buildpackage
+++ b/Completion/Debian/Command/_svn-buildpackage
@@ -28,8 +28,8 @@ _arguments \
'-B[binary-only build, no source or arch-indep binaries]' \
'-S[source-only build, no binaries]' \
'-s-:source generation:((i\:default a\:force\ inclusion\ of\ original\ source d\:force\ exclusion\ of\ original\ source))' \
- '-a-:architecture:(alpha amd64 arm hppa hurd-i386 i386 ia64 m68k mips mipsel powerpc s390 sparc)' \
- '-v-:version:' \
+ '-a-:architecture:_deb_architectures' \
+ '-v-:version' \
'-C-:changes description:_files' \
'-m-:maintainer address:_email_addresses' \
'-e-:maintainer address:_email_addresses' \
diff --git a/Completion/Debian/Command/_update-alternatives b/Completion/Debian/Command/_update-alternatives
index ccf5084bf..31128dd82 100644
--- a/Completion/Debian/Command/_update-alternatives
+++ b/Completion/Debian/Command/_update-alternatives
@@ -1,6 +1,6 @@
#compdef update-alternatives
-local curcontext="$curcontext" context state line alterdir
+local curcontext="$curcontext" state line alterdir ret
if [[ -d /var/lib/dpkg/alternatives ]]; then
alterdir=/var/lib/dpkg/alternatives
diff --git a/Completion/Debian/Command/_vim-addons b/Completion/Debian/Command/_vim-addons
index dbd0ee31d..0ad39955d 100644
--- a/Completion/Debian/Command/_vim-addons
+++ b/Completion/Debian/Command/_vim-addons
@@ -1,47 +1,48 @@
#compdef vim-addons
-local state line cmds ret=1
+local context state line expl ret=1
typeset -A opt_args
-_arguments -C \
- {-q,--query}'[be quiet and make the output more parseable]' \
- {-r,--registry-dir}'[set the registry directory]' \
- {-s,--source-dir}'[set addon source directory]' \
- {-t,--target-dir}'[set addon target directory]' \
- {-v,--verbose}'[increase verbosity]' \
- {-y,--system-dir}'[set system-wide target directory]' \
- {-h,--help}'[help]' \
- {-w,--system-wide}'[set target directory to the system-wide one (overrides -t)]' \
- '1: :->cmds' \
- '*: :->args' && ret=0
-
+_arguments \
+ '(-q --query)'{-q,--query}'[be quiet and make the output more parseable]' \
+ '(-r --registry-dir)'{-r,--registry-dir}'[set the registry directory]' \
+ '(-s --source-dir)'{-s,--source-dir}'[set addon source directory]' \
+ '(-t --target-dir -w --system-wide)'{-t,--target-dir}'[set addon target directory]' \
+ '(-v --verbose -z --silent)'{-v,--verbose}'[increase verbosity]' \
+ '(y --system-dir)'{-y,--system-dir}'[set system-wide target directory]' \
+ '(-)'{-h,--help}'[show help information]' \
+ '(-w --system-wide -t --target-dir)'{-w,--system-wide}'[use system-wide target directory]' \
+ '(-z --silent -v --verbose)'{-z,--silent}'[supress most output]' \
+ '1:commands:((
+ install\:install\ specified\ addons
+ remove\:remove\ specified\ addons
+ list\:list\ available\ addons\ in\ registry
+ status\:list\ status\ of\ addons
+ disable\:disable\ specified\ addons
+ enable\:undo\ effects\ of\ previous\ disable
+ files\:list\ files\ composing\ the\ specified\ addon
+ show\:display\ detailed\ information\ on\ specified\ addon
+ ))' \
+ '*: :->args' && ret=0
+
case $state in
- cmds)
- cmds=(
- 'install:install the specified addon'
- 'remove:remove the specified addon'
- 'list:list available addons in registry'
- 'status:list the status of addons'
- 'disable:disable the specified addons'
- 'amend:under the effects of the previous disable'
- 'files:list the files composing the specified addon'
- 'show:display detailed information about the specified addon'
- )
- _describe -t commands 'vim-addons command' cmds && ret=0
- ;;
args)
case $line[1] in
install)
- _wanted addon expl 'addon' compadd $(command vim-addons -q | awk '$2 == "removed" { print $1 }') && ret=0
+ _wanted -C $context addons expl 'addon' compadd - \
+ ${${(M)${(f)"$(_call_program addons vim-addons -q)"}:#*removed}%$'\t'*} && ret=0
;;
- amend)
- _wanted addon expl 'addon' compadd $(command vim-addons -q | awk '$2 == "disabled" { print $1 }') && ret=0
+ enable)
+ _wanted -C $context addons expl 'addon' compadd - \
+ ${${(M)${(f)"$(_call_program addons vim-addons -q)"}:#*disabled}%$'\t'*} && ret=0
;;
remove)
- _wanted addon expl 'addon' compadd $(command vim-addons -q | awk '$2 ~ /disabled|installed/ { print $1 }') && ret=0
+ _wanted -C $context addons expl 'addon' compadd - \
+ ${${(M)${(f)"$(_call_program addons vim-addons -q)"}:#*(disabled|installed)}%$'\t'*} && ret=0
;;
- files|status|disable|show)
- _wanted addon expl 'addon' compadd $(command vim-addons list) && ret=0
+ *)
+ _wanted -C $context addons expl 'addon' compadd - \
+ $(_call_program addons vim-addons list) && ret=0
;;
esac
;;
diff --git a/Completion/Debian/Type/_deb_architectures b/Completion/Debian/Type/_deb_architectures
new file mode 100644
index 000000000..22c43dd3e
--- /dev/null
+++ b/Completion/Debian/Type/_deb_architectures
@@ -0,0 +1,9 @@
+#autoload
+
+local extra
+zparseopts -E -D -a extra a:
+
+_description architectures expl 'architecture'
+compadd "$@" "$expl[@]" alpha amd64 arm64 armel armhf hppa hurd-i386 i386 ia64 \
+ kfreebsd-amd64 kfreebsd-i386 m68k mips mipsel powerpc powerpcspe ppc64 \
+ ppc64el s390x sh4 sparc sparc64 x32 ${=extra[2]}
diff --git a/Completion/Linux/Command/_docker b/Completion/Linux/Command/_docker
deleted file mode 100644
index faf17b2be..000000000
--- a/Completion/Linux/Command/_docker
+++ /dev/null
@@ -1,410 +0,0 @@
-#compdef docker
-#
-# zsh completion for docker (http://docker.com)
-#
-# version: 0.3.0
-# github: https://github.com/felixr/docker-zsh-completion
-#
-# contributers:
-# - Felix Riedel
-# - Vincent Bernat
-#
-# license:
-#
-# Copyright (c) 2013, Felix Riedel
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# * Neither the name of the <organization> nor the
-# names of its contributors may be used to endorse or promote products
-# derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-__parse_docker_list() {
- awk '
-NR == 1 {
- idx=1;i=0;f[i]=0
- header=$0
- while ( match(header, / ([A-Z]+|[A-Z]+ [A-Z]+)/) ) {
- idx += RSTART+1
- f[++i]=idx
- header = substr($0,idx)
- }
- f[++i]=999
-}
-
-NR > 1 '"$1"' {
- for(j=0;j<i;j++) {
- x[j] = substr($0, f[j], f[j+1]-f[j]-1)
- gsub(/[ ]+$/, "", x[j])
- }
- printf("%s:%7s, %s\n", x[0], x[3], x[1])
- if (x[6] != "") {
- split(x[6], names, /,/)
- for (name in names) printf("%s:%7s, %s\n", names[name], x[3], x[1])
- }
-}
-'| sed -e 's/ \([hdwm]\)\(inutes\|ays\|ours\|eeks\)/\1/'
-}
-
-__docker_stoppedcontainers() {
- local expl
- declare -a stoppedcontainers
- stoppedcontainers=(${(f)"$(_call_program commands docker ps -a | __parse_docker_list '&& / Exit/')"})
- _describe -t containers-stopped "Stopped Containers" stoppedcontainers "$@"
-}
-
-__docker_runningcontainers() {
- local expl
- declare -a containers
-
- containers=(${(f)"$(_call_program commands docker ps | __parse_docker_list)"})
- _describe -t containers-active "Running Containers" containers "$@"
-}
-
-__docker_containers () {
- __docker_stoppedcontainers "$@"
- __docker_runningcontainers "$@"
-}
-
-__docker_images () {
- local expl
- declare -a images
- images=(${(f)"$(_call_program commands docker images | awk '(NR > 1 && $1 != "<none>"){printf("%s", $1);if ($2 != "<none>") printf("\\:%s", $2); printf("\n")}')"})
- images=($images ${(f)"$(_call_program commands docker images | awk '(NR > 1){printf("%s:%-15s in %s\n", $3,$2,$1)}')"})
- _describe -t docker-images "Images" images
-}
-
-__docker_tags() {
- local expl
- declare -a tags
- tags=(${(f)"$(_call_program commands docker images | awk '(NR>1){print $2}'| sort | uniq)"})
- _describe -t docker-tags "tags" tags
-}
-
-__docker_repositories_with_tags() {
- if compset -P '*:'; then
- __docker_tags
- else
- __docker_repositories -qS ":"
- fi
-}
-
-__docker_search() {
- # declare -a dockersearch
- local cache_policy
- zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
- if [[ -z "$cache_policy" ]]; then
- zstyle ":completion:${curcontext}:" cache-policy __docker_caching_policy
- fi
-
- local searchterm cachename
- searchterm="${words[$CURRENT]%/}"
- cachename=_docker-search-$searchterm
-
- local expl
- local -a result
- if ( [[ ${(P)+cachename} -eq 0 ]] || _cache_invalid ${cachename#_} ) \
- && ! _retrieve_cache ${cachename#_}; then
- _message "Searching for ${searchterm}..."
- result=(${(f)"$(_call_program commands docker search ${searchterm} | awk '(NR>2){print $1}')"})
- _store_cache ${cachename#_} result
- fi
- _wanted dockersearch expl 'Available images' compadd -a result
-}
-
-__docker_caching_policy()
-{
- # oldp=( "$1"(Nmh+24) ) # 24 hour
- oldp=( "$1"(Nmh+1) ) # 24 hour
- (( $#oldp ))
-}
-
-
-__docker_repositories () {
- local expl
- declare -a repos
- repos=(${(f)"$(_call_program commands docker images | sed -e '1d' -e 's/[ ].*//' | sort | uniq)"})
- _describe -t docker-repos "Repositories" repos "$@"
-}
-
-__docker_commands () {
- # local -a _docker_subcommands
- local cache_policy
-
- zstyle -s ":completion:${curcontext}:" cache-policy cache_policy
- if [[ -z "$cache_policy" ]]; then
- zstyle ":completion:${curcontext}:" cache-policy __docker_caching_policy
- fi
-
- if ( [[ ${+_docker_subcommands} -eq 0 ]] || _cache_invalid docker_subcommands) \
- && ! _retrieve_cache docker_subcommands;
- then
- _docker_subcommands=(${${(f)"$(_call_program commands
- docker 2>&1 | sed -e '1,6d' -e '/^[ ]*$/d' -e 's/[ ]*\([^ ]\+\)\s*\([^ ].*\)/\1:\2/' )"}})
- _docker_subcommands=($_docker_subcommands 'help:Show help for a command')
- _store_cache docker_subcommands _docker_subcommands
- fi
- _describe -t docker-commands "docker command" _docker_subcommands
-}
-
-__docker_subcommand () {
- local -a _command_args
- case "$words[1]" in
- (attach)
- _arguments \
- '--no-stdin[Do not attach stdin]' \
- '--sig-proxy[Proxify all received signal]' \
- ':containers:__docker_runningcontainers'
- ;;
- (build)
- _arguments \
- '--no-cache[Do not use cache when building the image]' \
- '-q[Suppress verbose build output]' \
- '--rm[Remove intermediate containers after a successful build]' \
- '-t=-:repository:__docker_repositories_with_tags' \
- ':path or URL:_directories'
- ;;
- (commit)
- _arguments \
- '--author=-[Author]:author: ' \
- '-m=-[Commit message]:message: ' \
- '--run=-[Configuration automatically applied when the image is run]:configuration: ' \
- ':container:__docker_containers' \
- ':repository:__docker_repositories_with_tags'
- ;;
- (cp)
- _arguments \
- ':container:->container' \
- ':hostpath:_files'
- case $state in
- (container)
- if compset -P '*:'; then
- _files
- else
- __docker_containers -qS ":"
- fi
- ;;
- esac
- ;;
- (diff|export)
- _arguments '*:containers:__docker_containers'
- ;;
- (history)
- _arguments \
- '--no-trunc[Do not truncate output]' \
- '-q[Only show numeric IDs]' \
- '*:images:__docker_images'
- ;;
- (images)
- _arguments \
- '-a[Show all images]' \
- '--no-trunc[Do not truncate output]' \
- '-q[Only show numeric IDs]' \
- '--tree[Output graph in tree format]' \
- '--viz[Output graph in graphviz format]' \
- ':repository:__docker_repositories'
- ;;
- (inspect)
- _arguments \
- '--format=-[Format the output using the given go template]:template: ' \
- '*:containers:__docker_containers'
- ;;
- (import)
- _arguments \
- ':URL:(- http:// file://)' \
- ':repository:__docker_repositories_with_tags'
- ;;
- (info)
- ;;
- (import)
- _arguments \
- ':URL:(- http:// file://)' \
- ':repository:__docker_repositories_with_tags'
- ;;
- (insert)
- _arguments '1:containers:__docker_containers' \
- '2:URL:(http:// file://)' \
- '3:file:_files'
- ;;
- (kill)
- _arguments '*:containers:__docker_runningcontainers'
- ;;
- (load)
- ;;
- (login)
- _arguments \
- '-e=-[Email]:email: ' \
- '-p=-[Password]:password: ' \
- '-u=-[Username]:username: ' \
- ':server: '
- ;;
- (logs)
- _arguments \
- '-f[Follow log output]' \
- '*:containers:__docker_containers'
- ;;
- (port)
- _arguments \
- '1:containers:__docker_runningcontainers' \
- '2:port:_ports'
- ;;
- (start)
- _arguments \
- '-a[Attach container'"'"'s stdout/stderr and forward all signals]' \
- '-i[Attach container'"'"'s stding]' \
- '*:containers:__docker_stoppedcontainers'
- ;;
- (rm)
- _arguments \
- '--link[Remove the specified link and not the underlying container]' \
- '-v[Remove the volumes associated to the container]' \
- '*:containers:__docker_stoppedcontainers'
- ;;
- (rmi)
- _arguments \
- '*:images:__docker_images'
- ;;
- (restart|stop)
- _arguments '-t=-[Number of seconds to try to stop for before killing the container]:seconds to before killing:(1 5 10 30 60)' \
- '*:containers:__docker_runningcontainers'
- ;;
- (top)
- _arguments \
- '1:containers:__docker_runningcontainers' \
- '(-)*:: :->ps-arguments'
- case $state in
- (ps-arguments)
- _ps
- ;;
- esac
-
- ;;
- (ps)
- _arguments \
- '-a[Show all containers]' \
- '--before=-[Show only container created before...]:containers:__docker_containers' \
- '-l[Show only the latest created container]' \
- '-n=-[Show n last created containers, include non-running one]:n:(1 5 10 25 50)' \
- '--no-trunc[Do not truncate output]' \
- '-q[Only show numeric IDs]' \
- '-s[Display sizes]' \
- '--since=-[Show only containers created since...]:containers:__docker_containers'
- ;;
- (tag)
- _arguments \
- '-f[force]'\
- ':image:__docker_images'\
- ':repository:__docker_repositories_with_tags'
- ;;
- (run)
- _arguments \
- '-P[Publish all exposed ports to the host]' \
- '-a[Attach to stdin, stdout or stderr]' \
- '-c=-[CPU shares (relative weight)]:CPU shares:(0 10 100 200 500 800 1000)' \
- '--cidfile=-[Write the container ID to the file]:CID file:_files' \
- '-d[Detached mode: leave the container running in the background]' \
- '*--dns=-[Set custom dns servers]:dns server: ' \
- '*-e=-[Set environment variables]:environment variable: ' \
- '--entrypoint=-[Overwrite the default entrypoint of the image]:entry point: ' \
- '*--expose=-[Expose a port from the container without publishing it]: ' \
- '-h=-[Container host name]:hostname:_hosts' \
- '-i[Keep stdin open even if not attached]' \
- '--link=-[Add link to another container]:link:->link' \
- '--lxc-conf=-[Add custom lxc options]:lxc options: ' \
- '-m=-[Memory limit (in bytes)]:limit: ' \
- '--name=-[Container name]:name: ' \
- '*-p=-[Expose a container'"'"'s port to the host]:port:_ports' \
- '--privileged[Give extended privileges to this container]' \
- '--rm[Remove intermediate containers when it exits]' \
- '--sig-proxy[Proxify all received signal]' \
- '-t[Allocate a pseudo-tty]' \
- '-u=-[Username or UID]:user:_users' \
- '*-v=-[Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)]:volume: '\
- '--volumes-from=-[Mount volumes from the specified container]:volume: ' \
- '-w=-[Working directory inside the container]:directory:_directories' \
- '(-):images:__docker_images' \
- '(-):command: _command_names -e' \
- '*::arguments: _normal'
-
- case $state in
- (link)
- if compset -P '*:'; then
- _wanted alias expl 'Alias' compadd -E ""
- else
- __docker_runningcontainers -qS ":"
- fi
- ;;
- esac
-
- ;;
- (pull|search)
- _arguments ':name:__docker_search'
- ;;
- (push)
- _arguments ':repository:__docker_repositories_with_tags'
- ;;
- (save)
- _arguments \
- ':images:__docker_images'
- ;;
- (wait)
- _arguments ':containers:__docker_runningcontainers'
- ;;
- (help)
- _arguments ':subcommand:__docker_commands'
- ;;
- (*)
- _message 'Unknown sub command'
- esac
-
-}
-
-_docker () {
- # Support for subservices, which allows for `compdef _docker docker-shell=_docker_containers`.
- # Based on /usr/share/zsh/functions/Completion/Unix/_git without support for `ret`.
- if [[ $service != docker ]]; then
- _call_function - _$service
- return
- fi
-
- local curcontext="$curcontext" state line
- typeset -A opt_args
-
- _arguments -C \
- '-H=-[tcp://host:port to bind/connect to]:socket: ' \
- '(-): :->command' \
- '(-)*:: :->option-or-argument'
-
- if (( CURRENT == 1 )); then
-
- fi
- case $state in
- (command)
- __docker_commands
- ;;
- (option-or-argument)
- curcontext=${curcontext%:*:*}:docker-$words[1]:
- __docker_subcommand
- ;;
- esac
-}
-
-_docker "$@"
diff --git a/Completion/Linux/Command/_modutils b/Completion/Linux/Command/_modutils
index 66e65d32e..0732aa106 100644
--- a/Completion/Linux/Command/_modutils
+++ b/Completion/Linux/Command/_modutils
@@ -107,7 +107,7 @@ _modutils() {
if _cache_invalid modules-$kver || ! _retrieve_cache modules-$kver;
then
# 2011-01-02 gi1242: Do we need .o files? Or is .ko enough?
- modules=( $modules_dir/$kver/(*~(source|build))/**/*.(o|ko|ko.gz)(.:t:r:r) )
+ modules=( $modules_dir/$kver/(*~(source|build))/**/*.(o|ko|ko.gz|.ko.xz)(.:t:r:r) )
_store_cache modules-$kver modules
fi
diff --git a/Completion/Linux/Command/_qdbus b/Completion/Linux/Command/_qdbus
new file mode 100644
index 000000000..95a4d5243
--- /dev/null
+++ b/Completion/Linux/Command/_qdbus
@@ -0,0 +1,114 @@
+#compdef qdbus
+#
+# Copyright (C) 2015 Thomas Mitterfellner <thomas.mitterfellner@gmail.com>
+#
+# This file is released under the GPLv2.
+#
+# version 0.1
+
+# get the type of a method: 1 means function, 2 means property
+getType () {
+ case "$1" in
+ "method"*) echo 1 ;;
+ "property"*) echo 2 ;;
+ *) echo 0 ;;
+ esac
+}
+
+# get the index of a method in an array of methods
+getIndex () {
+ local e
+ local index
+ local type_
+ index=0
+ for e in "${@:2}"; do
+ index=$(( index + 1 ))
+ type_=$(getType "$e")
+ if [[ $type_ == 1 ]] ; then
+ if [[ "$e" == *"$1("* ]] ; then
+ echo $index
+ return 0
+ fi
+ elif [[ $type_ == 2 ]] ; then
+ if [[ "$e" == *"$1" ]] ; then
+ echo $index
+ return 0
+ fi
+ fi
+ done
+ echo 0
+}
+
+_qdbus() {
+ local curcontext="$curcontext" state line
+ local services
+ local path_
+ local methods
+ local names
+ local types
+ local properties
+ local index
+ typeset -A opt_args
+
+ _arguments "--system[connect to system bus]"\
+ "--literal[print literal replies]"\
+ "1:service name:->service"\
+ "2:path:->path"\
+ "3:method:->method"\
+ "*:arguments:->arguments"
+
+ case $state in
+ service)
+ services=( $(qdbus ${words[@]:1:-1} | grep -E '^([^:])') )
+ compadd "$@" $services
+ ;;
+
+ path)
+ path_=( $(qdbus ${words[@]:1:-1} 2>/dev/null) )
+
+ compadd "$@" $path_
+ ;;
+
+ method)
+ IFS=$'\n'
+ methods=( $(qdbus ${words[@]:1:-1} | \
+ grep -e "^method" | \
+ sed -r 's/method (.+) (.+)\((.*)\)/\2:\1(\3)/g' 2>/dev/null) )
+ properties=( $(qdbus ${words[@]:1:-1} | \
+ grep -e "^property" | \
+ sed -r 's/property (.+) (.+) (.+)/\3:\1 \2/g' 2>/dev/null) )
+
+ _describe properties properties -J properties
+ _describe methods methods -J methods
+ ;;
+
+ arguments)
+ IFS=$'\n'
+
+ path_pos=$(( ${(M)#words:#--*} + 2))
+ method_pos=$(( $path_pos + 2))
+ names=( $(qdbus ${words[@]:1:$path_pos} | grep -e '^[mp]' 2>/dev/null) )
+ index=$(getIndex "${words[$method_pos]}" $names[@])
+ method=$names[$index]
+
+ arg_pos=$(( ${#words} - $method_pos ))
+ if [[ $(getType "$method") -eq 1 ]] ; then
+ method_args="$(echo $method | sed -r 's/(.+) (.+) (.+)\((.*)\)/\4/g')"
+ IFS=$',' method_args_=(${=method_args})
+ num_args=${#method_args_}
+ if [[ $arg_pos -le $num_args ]] ; then
+ _message "${method_args_[$arg_pos]}"
+ fi
+ else
+ property_=$(echo "$method" |\
+ sed -r 's/property (.+) (.+) (.+)/\1 \2/g')
+ if [[ $arg_pos -eq 1 ]] ; then
+
+ _message ${property_}
+ fi
+ fi
+ ;;
+ esac
+}
+
+_qdbus "$@"
diff --git a/Completion/Linux/Command/_strace b/Completion/Linux/Command/_strace
index 45ebfcf1a..d6dabfd24 100644
--- a/Completion/Linux/Command/_strace
+++ b/Completion/Linux/Command/_strace
@@ -5,6 +5,7 @@
# - allow negated calls (e.g. -e!write)
_sys_calls () {
local expl
+ local -a sys_calls
sys_calls=(_llseek _newselect _sysctl accept access acct
adjtimex afs_syscall alarm bdflush bind break brk cacheflush
diff --git a/Completion/Linux/Command/_sysstat b/Completion/Linux/Command/_sysstat
index 60de9d899..2a7128c23 100644
--- a/Completion/Linux/Command/_sysstat
+++ b/Completion/Linux/Command/_sysstat
@@ -4,80 +4,73 @@
# sysstat-nfsiostat - there seems to be two nfsiostat(1)s. one from oracle and one by redhat.
_mpstat() {
- local ret=1
_arguments : \
'-A[equivalent to -u -I ALL -P ALL]' \
- '-I[report interrupt statistics]:interrupts:(SUM CPU SCPU ALL)' \
- '-P[specify processor number]:processor: _values -s "," processor ON ALL' \
+ '-I[report interrupt statistics]:interrupt:(SUM CPU SCPU ALL)' \
+ '-P[specify processor number]:processor: _values -s "," processor ON ALL {1..$(_call_program processors getconf _NPROCESSORS_ONLN)}' \
'-u[report CPU utilization]' \
'-V[print version number]' \
- '1:interval:_guard "[0-9]#" "interval"' \
- '2:count:_guard "[0-9]#" "count"' && ret=0
- return ret
+ '1:interval' \
+ '2:count'
}
_iostat() {
- local ret=1
_arguments : \
'-c[display CPU utilization report]' \
'-d[display device utilization report]' \
'-T[only display global statistics for group_name]' \
- '-g[display statistics for a group of devices]:group name: _message "group name"' \
+ '-g[display statistics for a group of devices]:group name' \
'-h[human readable device utilization report]' \
'-j[display persistent device name]' \
'(-m)-k[display statistics in kB/s]' \
'(-k)-m[display statistics in MB/s]' \
'-N[display registered device mapper names]' \
- '1:interval:_guard "[0-9]#" "interval"' \
- '2:count:_guard "[0-9]#" "count"' && ret=0
- return ret
+ '::device:_files -W /dev -g "*(-%)"' \
+ ': :_guard "[0-9]#" "interval"' \
+ ':count'
}
_cifsiostat() {
- local ret=1
_arguments : \
'-h[human readable]' \
'(-m)-k[display statistics in kB/s]' \
'(-k)-m[display statistics in MB/s]' \
'-t[print timestamp for each report]' \
'-V[print version number]' \
- '1:interval:_guard "[0-9]#" "interval"' \
- '2:count:_guard "[0-9]#" "count"' && ret=0
- return ret
+ '1:interval' \
+ '2:count'
}
_isag() {
- local ret=1
_arguments : \
- '-p[Pathname to daily data files]:data files: _files -/' \
- '-c[Specify configuration file]:configuration file: _files' \
- '-ght[Specify height of the chart]:height: _message "height"' \
- '-gwd[Specify width of the chart]:width: _message "width"' && ret=0
- return ret
+ '-p[specify path to daily data files]:path:_files -/' \
+ '-c[specify configuration file]:configuration file:_files' \
+ '-ght[specify height of the chart]:height' \
+ '-gwd[specify width of the chart]:width'
}
_sadf() {
- local ret=1 line state context expl
- typeset -A opt_args
+ local ret=1
# any options after `--' are for sar(1)
if ! (( CURRENT > $words[(i)--] )); then
_arguments : \
'-C[display comments in file]' \
'(-j -p -x)-d[output file in SQL format]' \
- '-e[set ending time of report]:ending time: _message "ending time in localtime(HH\:MM\:SS 24-hour format)"' \
+ '-e[set ending time of report]:ending time (HH\:MM\:SS)' \
'-H[display only the header of the report]' \
'(-j -p -x)-h[print on a single line when used with -d]' \
'(-d -p -x)-j[output file in JSON]' \
'-P[restrict processor dependant statistics]:processor number(zero indexed) or ALL:(ALL)' \
'(-j -x -d)-p[print in format parsable by tools like awk]' \
- '-s[set starting time of report]:starting time: _message "starting time in localtime(HH\:MM\:SS 24-hour format)"' \
+ '-s[set starting time of report]:starting time (HH\:MM\:SS)"' \
'(-t -U)-T[display timestamp in local time]' \
'(-T -U)-t[display timestamp in file\''s original localtime]' \
- '(-t -T)-U[display in seconds from epoch(UTC)]' \
+ '(-t -T)-U[display in seconds since epoch (UTC)]' \
'-V[print version number]' \
'(-j -d -p)-x[output file in XML]' \
- '1:interval:_guard "[0-9]#" "interval"' \
- '2:count:_guard "[0-9]#" "count"' && ret=0
+ '1:interval' \
+ '2:count' \
+ '3:data file:_files' && ret=0
else
_arguments : '*::sar: _sar' && ret=0
fi
@@ -85,20 +78,19 @@ _sadf() {
}
_sar() {
- local ret=1
_arguments : \
'-A[equivalent to -bBdFHqrRSuvwWy -I SUM -I XALL -m ALL -n ALL -u ALL -P ALL]' \
'-B[report paging statistics]' \
'-b[report I/O and transfer rate statistics]' \
'-C[display comments from sadc]' \
'-d[report activity for each block device]' \
- '-e[set ending time of report]:ending time: _message "ending time (HH\:MM\:SS 24-hour format)"' \
+ '-e[set ending time of report]:ending time (HH\:MM\:SS)' \
'-F[display statistics for mounted filesystems]' \
'-f[extract records from file]:record:_files' \
'-H[report hugepages utilization]' \
'-h[display help]' \
'*-I[report statistics for interrupts]:interrupts: _values -s "," interrupts 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 SUM ALL XALL' \
- '-i[select records as close as possible to interval]:interval: _message "interval"' \
+ '-i[select records as close as possible to interval]:interval' \
'-j[display persistent device names]:type:(ID LABEL PATH UUID)' \
'-m[report power management statistics]:keywords: _values -s "," keywords CPU FAN FREQ IN TEMP USB ALL' \
'-n[report network statistics]:keywords: _values -s "," keywords DEV EDEV NFS NFSD SOCK IP EIP ICMP EICMP TCP ETCP UDP SOCK6 IP6 EIP6 ICMP6 EICMP6 UDP6 ALL' \
@@ -108,27 +100,25 @@ _sar() {
'-R[report memory statistics]' \
'-r[report memory utilization statistics]' \
'-S[report swap space utilization]' \
- '-s[set starting time of report]:start time: _message "start time (HH\:MM\:SS 24-hour format)"' \
+ '-s[set starting time of report]:start time (HH\:MM\:SS)' \
'-u[report CPU utilization]: :(ALL)' \
'-V[print version number]' \
'-v[report status of kernel tables]' \
'-W[report swapping statistics]' \
'-w[report task creation and system switching activity]' \
'-y[report TTY device activity]' \
- '1:interval:_guard "[0-9]#" "interval"' \
- '2:count:_guard "[0-9]#" "count"' && ret=0
- return ret
+ '1:interval' \
+ '2:count'
}
_pidstat() {
- local ret=1
_arguments : \
- '-C[filter tasks by string]:task: _message "string or regex"' \
+ '-C[filter tasks by string]:task filter' \
'-d[report I/O statistics]' \
'-h[display on horizontally]' \
'-I[divide CPU usage by number of processors]' \
'-l[display process name along with arguments]' \
- '-p[select pid]:pid: _pids' \
+ '-p[select pid]:pid: _sequence _pids' \
'-r[report page faults and memory]' \
'-s[report stack utilization]' \
'-T[specifies what to monitor]:type:(TASK CHILD ALL)' \
@@ -137,14 +127,13 @@ _pidstat() {
'-u[report cpu utilization]' \
'-V[print version number]' \
'-v[display values from kernel table]' \
- '-w[report task switching activity]' && ret=0
- return ret
+ '-w[report task switching activity]' \
+ ':interval' ':count'
}
_sysstat() {
- local ret=1
- _call_function ret _$service
- return ret
-}
+ local ret
+ _call_function ret _$service && return ret
+}
_sysstat "$@"
diff --git a/Completion/Mandriva/Command/_rebootin b/Completion/Mandriva/Command/_rebootin
index 1b69609f3..3f30b2591 100644
--- a/Completion/Mandriva/Command/_rebootin
+++ b/Completion/Mandriva/Command/_rebootin
@@ -1,27 +1,29 @@
#compdef rebootin
+local context state line expl
+typeset -A opt_args
local loader=$(sudo detectloader -q)
-_arguments -C -s \
+_arguments -s \
'-n[no immediate reboot just set the flags for next reboot]' \
'-f[create a /fastboot file to reboot in fastboot mode]' \
'*::arguments:->loader_entry'
-local expl
case $state in
- loader_entry)
- case $loader in
- GRUB)
- if [ -r /boot/grub/menu.lst ];then
- compadd ${${(M)${(f)"$(</boot/grub/menu.lst)"}##title *}#title }
- fi
- ;;
- LILO)
- if [ -r /etc/lilo.conf ];then
- compadd $(awk -F= '{ if ($0 ~ /label=/) print $2 }' /etc/lilo.conf)
- fi
- ;;
- *)
- ;;
- esac
+ loader_entry)
+ case $loader in
+ GRUB)
+ if [ -r /boot/grub/menu.lst ]; then
+ _wanted -C $context entries expl entry \
+ compadd ${${(M)${(f)"$(</boot/grub/menu.lst)"}##title *}#title }
+ fi
+ ;;
+ LILO)
+ if [ -r /etc/lilo.conf ]; then
+ _wanted -C $context entries expl entry \
+ compadd $(awk -F= '{ if ($0 ~ /label=/) print $2 }' /etc/lilo.conf)
+ fi
+ ;;
+ esac
+ ;;
esac
diff --git a/Completion/Mandriva/Command/_urpmi b/Completion/Mandriva/Command/_urpmi
index 2468b2318..7951e6a9f 100644
--- a/Completion/Mandriva/Command/_urpmi
+++ b/Completion/Mandriva/Command/_urpmi
@@ -1,24 +1,8 @@
#compdef urpme urpmi urpmi.addmedia urpmi.removemedia urpmi.update urpmq urpmf parsehdlist
_urpmi_media() {
- local ret=1 single=0
- local -a all_sources opts
-
- if [[ $1 = -s ]]; then
- single=1
- shift
- fi
-
# TODO should we probe for active media only?
- all_sources=( ${(f)"$(urpmq --list-media 2> /dev/null)"} )
-
- if (( single )); then
- compadd "$expl[@]" -a all_sources && ret=0
- else
- _values -s , 'urpmi media' "$all_sources[@]" && ret=0
- fi
-
- return $ret
+ compadd "$@" - ${(f)"$(urpmq --list-media 2> /dev/null)"}
}
_urpmi_rpms() {
@@ -40,7 +24,7 @@ _urpmi_rpms() {
_requested files expl '(S)RPM file' \
_files -g '*.(#i)rpm(-.)' && ret=0
-
+
(( ret )) || break
done
@@ -65,12 +49,12 @@ _urpmi_media_url() {
fi
fi
- return $ret
+ return ret
}
_urpme_package() {
local -a _rpms
- _rpms=( $(_call_program packages rpm -qa 2>/dev/null) )
+ _rpms=( $(_call_program packages rpm -qa) )
compadd "$@" -a _rpms
}
@@ -80,12 +64,11 @@ _urpmi_parallel_alias() {
}
_urpmi() {
- local state context line ret=1 help="--help -h"
-
- local -a opts_help opts_net opts_verbose opts_inst_rem opts_search opts_media
+ local ret=1 help="--help -h"
+ local -a opts_help opts_net opts_verbose opts_inst_rem opts_search opts_media
opts_help=(
- "($help : -)"{--help,-h}"[print usage information]"
+ "(: -)"{--help,-h}"[print usage information]"
)
opts_net=(
@@ -116,10 +99,10 @@ _urpmi() {
)
opts_media=(
- "($help)--excludemedia[do not use the given media]:urpmi media: _urpmi_media"
- "($help --update --use-distrib)--media[use only the media listed by comma]:urpmi media: _urpmi_media"
- "($help)--searchmedia[use only the given media to search requested (or updated) packages]:urpmi media: _urpmi_media -s"
- "($help)--sortmedia[sort media according to substrings separated by comma]:urpmi media: _urpmi_media"
+ "($help)--excludemedia[do not use the given media]:urpmi media:_sequence _urpmi_media"
+ "($help --update --use-distrib)--media[use only the media listed by comma]:urpmi media:_sequence _urpmi_media"
+ "($help)--searchmedia[use only the given media to search requested (or updated) packages]:urpmi media:_urpmi_media"
+ "($help)--sortmedia[sort media according to substrings separated by comma]:urpmi media:_sequence _urpmi_media"
"($help)--synthesis[use the given synthesis instead of urpmi db]:synthesis file:_url"
"($help --media --use-distrib)--update[use only update media]"
"($help --media --update)--use-distrib[configure urpmi on the fly from a distrib tree]:installation media:_urpmi_media_url"
@@ -132,7 +115,7 @@ _urpmi() {
$opts_inst_rem \
"--auto[do not ask any question]" \
"-v[verbose]" \
- ": :_urpme_package"
+ ": :_urpme_package" && ret=0
;;
urpmi.addmedia )
_arguments -A '-*' \
@@ -165,7 +148,7 @@ _urpmi() {
"($help :)-a[select all media]" \
"($help)-c[clean headers cache directory]" \
"($help)-y[fuzzy mathing on media names]" \
- "(-a)"{,\*}": : _urpmi_media" \
+ "(-a)"{,\*}":media:_sequence _urpmi_media" \
&& ret=0
;;
urpmi.update )
@@ -179,7 +162,7 @@ _urpmi() {
"($help --update :)-a[select all non-removable media]" \
"($help)-c[clean /var/cache/urpmi/headers on exit]" \
"($help)*-f[force generation of hdlist files]" \
- "($help -a)"{,\*}": : _urpmi_media" \
+ "($help -a)"{,\*}":media:_sequence _urpmi_media" \
&& ret=0
;;
urpmi )
@@ -308,7 +291,7 @@ _urpmi() {
;;
esac
- return $ret
+ return ret
}
_urpmi "$@"
diff --git a/Completion/Redhat/Command/_rpm b/Completion/Redhat/Command/_rpm
index 83922b60c..b2157bd48 100644
--- a/Completion/Redhat/Command/_rpm
+++ b/Completion/Redhat/Command/_rpm
@@ -32,6 +32,8 @@
# complete a RPM package file name
# package_or_file
# the previous two together
+# file_or_package
+# an absolute path to any file (not a package file) or a package
# tags
# complete a tag name
# capability
@@ -66,7 +68,7 @@ _rpm () {
{-g,--group}'[query packages in one of specified groups]'
--fileid --hdrid --pkgid --tid --querybynumber
'--triggeredby'
- '--whatprovides'
+ '--whatprovides:*:provided file:->file_or_package'
'--whatrequires'
)
sopts=${selectopts%\[*}\ --specfile
@@ -122,7 +124,7 @@ _rpm () {
query)
# --dump requires one of -{l,c,d}
# --triggers requires --script
- _arguments -s \
+ _arguments -s -C \
\!{-q,--query} "${commonopts[@]}" "${selectopts[@]}" "${pathopts[@]}" \
"($sopts)--specfile[query specified spec file as if it were a package]" \
'(-i --info)'{-i,--info}'[display package information]' \
@@ -140,10 +142,10 @@ _rpm () {
{--triggers,--triggerscripts}'[show trigger scripts]' && ret=0
;;
setattrs)
- _arguments -s --set{perm,ugids} "${selectopts[@]}" && ret = 0
+ _arguments -s -C --set{perm,ugids} "${selectopts[@]}" && ret=0
;;
verify)
- _arguments -s \!-{y,V} \
+ _arguments -s -C \!-{y,V} \
"${commonopts[@]}" "${selectopts[@]}" "${pathopts[@]}" \
--no{deps,files,scripts,digest,signature,linkto,md5,size,user,group,mtime,mode,rdev} && ret=0
;;
@@ -151,7 +153,7 @@ _rpm () {
tmp=( '(--force)--oldpackage' )
;&
install)
- _arguments -s \!-{i,U} "$tmp[@]" \
+ _arguments -s -C \!-{i,U} "$tmp[@]" \
"${commonopts[@]}" "${pathopts[@]}" \
'--excludepath:file to exclude:_files -/' \
'--relocate:relocate:->relocate' \
@@ -165,7 +167,7 @@ _rpm () {
'*:pkg file:->package_file' && ret=0
;;
uninstall)
- _arguments -s \!-e \
+ _arguments -s -C \!-e \
"${commonopts[@]}" "${pathopts[@]}" \
--{allmatches,justdb,repackage,test} \
--no{deps,scripts,preun,postun,trigger{s,un,postun}} \
@@ -177,7 +179,7 @@ _rpm () {
build_t)
(( $#tmp )) || tmp=( '*:tar file:_files -g "*.(#i)tar(.*|)(-.)"' )
- _arguments -s \
+ _arguments -s -C \
"${commonopts[@]}" "${pathopts[@]}" \
--{short-circuit,clean,nobuild,rmsource,sign,test} \
'--target:specify a build target:->target'\
@@ -187,13 +189,13 @@ _rpm () {
'--timecheck:time check (seconds):' "$tmp[1]" && ret=0
;;
sigcheck)
- _arguments -s \!-K \
+ _arguments -s -C \!-K \
"${commonopts[@]}" \
--no{gpg,pgp,md5,signature,digest} \
'*:package file:->package_file' && ret=0
;;
rebuild)
- _arguments -s \
+ _arguments -s -C \
"${commonopts[@]}" "${pathopts[@]}" \
'*:source package file:->package_file' && ret=0
;;
@@ -246,6 +248,13 @@ _rpm () {
package_or_file)
state=package_file
;;
+ file_or_package)
+ if [[ $PREFIX = /* ]]; then
+ _wanted files expl 'file' _files
+ else
+ state=package
+ fi
+ ;;
package)
if ( [[ ${+_rpms} -eq 0 ]] || _cache_invalid RPMs ) &&
! _retrieve_cache RPMs;
@@ -286,7 +295,7 @@ _rpm () {
;;
capabilities)
_wanted capabilities expl capability compadd \
- ${(f)"$(_call_program capabilities rpm -qa --queryformat '%\{requirename}\\n' 2>/dev/null)"}
+ ${(f)"$(_call_program capabilities rpm -qa --queryformat '%\{requirename}\\n' 2>/dev/null)"} && ret=0
;;
relocate)
if compset -P '*='; then
diff --git a/Completion/Redhat/Command/_yum b/Completion/Redhat/Command/_yum
index ae63364e6..a6983283c 100644
--- a/Completion/Redhat/Command/_yum
+++ b/Completion/Redhat/Command/_yum
@@ -85,15 +85,14 @@ _yum()
fi
}
-# Fills the installed pkg cache
+# Fills the all pkg cache
_yum_all_pkgs()
{
if ( [[ ${+_all_pkgs} -eq 0 ]] || _cache_invalid ALL ) &&
! _retrieve_cache ALL;
then
- local prog="yum -C list all | sed 's/\s.*//' | grep '\.'"
- _all_pkgs=( $(kages $prog 2>/dev/null) )
- _store_cache ALL _all_pkg
+ _all_pkgs=( $(yum -C list all | sed 's/\s.*//' | grep '\.' 2>/dev/null) )
+ _store_cache ALL _all_pkgs
fi
}
@@ -227,8 +226,9 @@ _yum_list_or_info()
else
local subcmd
subcmd="${${listlist[(r)$words[2]:*]%%:*}}"
- # Deal with any aliases
+ # offer packages selected by the subcommand
case $subcmd in
+ all) _yum_all;;
installed) _yum_erase;;
available) _yum_install;;
updates) _yum_update;;
diff --git a/Completion/Solaris/Command/_beadm b/Completion/Solaris/Command/_beadm
index 6e498bee3..8422653d8 100644
--- a/Completion/Solaris/Command/_beadm
+++ b/Completion/Solaris/Command/_beadm
@@ -1,76 +1,69 @@
#compdef beadm
-_beadm() {
- local context state line subcmds
- typeset -A opt_args
+local cmd expl args
- subcmds=( activate create destroy list mount rename unmount )
+if (( CURRENT == 2 )); then
+ _wanted subcommands expl 'subcommand' compadd \
+ activate create destroy list mount rename unmount
+ return
+fi
- if [[ $service == "beadm" ]]; then
- _arguments -C -A "-*" \
- '*::command:->subcmd' && return 0
+cmd="$words[2]"
+curcontext="${curcontext%:*}-$cmd:"
+shift words
+(( CURRENT-- ))
- if (( CURRENT == 1 )); then
- _wanted commands expl 'beadm subcommand' compadd -a subcmds
- return
- fi
- service="$words[1]"
- curcontext="${curcontext%:*}=$service:"
- fi
-
- case $service in
- (activate)
- _arguments -A "-*" \
- ':BE name:_be_name'
- ;;
-
- (create)
- # TODO: Add support for -o, and for creating snapshots
- _arguments -A "-*" \
- '-a[Activate new BE]' \
- '-d[Description]:' \
- '-e[Base BE]:BE name or snapshot:_be_name -t all' \
- '-p[Create new BE in specified ZFS pool]:ZFS pool:_zfs_pool' \
- ':new BE name:'
- ;;
-
- (destroy)
- _arguments -A "-*" \
- '-f[Unmount BE if necessary]' \
- "-F[Don't prompt for verification]" \
- ':BE or BE snapshot:_be_name'
- ;;
-
- (list)
- _arguments -A "-*" \
- '-a[List subordinate filesystems and snapshots]' \
- '-d[List subordinate filesystems]' \
- '-s[List snapshots]' \
- '-H[Parseable format]' \
- ':BE name:_be_name'
- ;;
-
- (mount)
- _arguments -A "-*" \
- ':BE name:_be_name' \
- ':mountpoint:_path_files -/'
- ;;
-
- (rename)
- _arguments -A "-*" \
- ':existing BE name:_be_name' \
- ':new BE name:'
- ;;
-
- (unmount)
- _arguments -A "-*" \
- '-f[Force unmount]' \
- ':BE name:_be_name'
- ;;
-
- (*)
- _message "unknown beadm subcommand: $service"
- esac
-}
-
-_beadm "$@"
+case $cmd in
+ activate)
+ _wanted boot-environs expl 'boot environment' _be_name
+ ;;
+ create)
+ [[ $OSTYPE = solaris* ]] && args=(
+ '-a[activate new BE]'
+ '-d[description]:description'
+ '*-o[property]:zfs property'
+ '-p[create new BE in specified zfs pool]:zfs pool:_zfs_pool'
+ )
+ _arguments -A "-*" $args \
+ '-e[base BE]:BE name or snapshot:_be_name -t all' \
+ ':new BE name:'
+ ;;
+ destroy)
+ [[ $OSTYPE = solaris* ]] && args=(
+ '-f[unmount BE if necessary]'
+ )
+ _arguments -A "-*" \
+ "-F[don't prompt for verification]" \
+ ':BE or BE snapshot:_be_name'
+ ;;
+ list)
+ if [[ $OSTYPE = solaris* ]]; then
+ args=( '-d[list subordinate filesystems]' )
+ elif [[ $OSTYPE = freebsd* ]]; then
+ args=( '-D[display space usage of boot environment]' )
+ fi
+ _arguments -A "-*" \
+ '-a[list subordinate filesystems and snapshots]' \
+ '-s[list snapshots]' \
+ '-H[parseable format]' \
+ ':boot environment:_be_name'
+ ;;
+ mount)
+ _arguments -A "-*" \
+ ':BE name:_be_name' \
+ ':mountpoint:_path_files -/'
+ ;;
+ rename)
+ _arguments -A "-*" \
+ ':existing boot environment name:_be_name' \
+ ':new boot environment:'
+ ;;
+ u(n|)mount)
+ _arguments -A "-*" \
+ '-f[force unmount]' \
+ ':boot environment:_be_name'
+ ;;
+ *)
+ _message "unknown beadm subcommand: $service"
+ ;;
+esac
diff --git a/Completion/Solaris/Command/_gcore b/Completion/Solaris/Command/_gcore
deleted file mode 100644
index d4ac9a03a..000000000
--- a/Completion/Solaris/Command/_gcore
+++ /dev/null
@@ -1,31 +0,0 @@
-#compdef gcore
-
-_gcore() {
- local -a content
-
- content=(
- "anon[anonymous private mappings]"
- "ctf[CTF type information]"
- "data[writable private file mappings]"
- "dism[DISM mappings]"
- "heap[process heap]"
- "ism[ISM mappings]"
- "rodata[read-only private file mappings]"
- "shanon[anonymous shared mappings]"
- "shfile[file-backed shared mappings]"
- "shm[System V shared memory]"
- "stack[process stack]"
- "symtab[symbol table sections for loaded files]"
- "text[readable and executable private file mappings]"
- )
-
- _arguments -s \
- '-p[use per-process core file repository]' \
- '-g[use global core file repository]' \
- '-F[force grabbing the target process]' \
- '-c[set core file content]:_values -s + "content" $content' \
- '-o[set core file base name]:' \
- '*:pids:_pids'
-}
-
-_gcore "$@"
diff --git a/Completion/Solaris/Command/_ps b/Completion/Solaris/Command/_ps
deleted file mode 100644
index 5ae61832a..000000000
--- a/Completion/Solaris/Command/_ps
+++ /dev/null
@@ -1,77 +0,0 @@
-#compdef ps
-
-_ps()
-{
- local -a o_opt
-
-o_opt=(
- "user[user ID]"
- "ruser[real user ID]"
- "group[group ID]"
- "rgroup[real group ID]"
- "pid[process ID]"
- "ppid[parent process ID]"
- "pgid[process group ID]"
- "pcpu[ratio of CPU time used recently to CPU time available]"
- "vsz[total size of the process in virtual memory, in kilobytes]"
- "nice[decimal value of the system scheduling priority of the process]"
- "etime[elapsed time since the process was started]"
- "time[cumulative CPU time of the process]"
- "tty[name of the controlling terminal of the process]"
- "comm[name of the command being executed]"
- "args[command with all its arguments as a string]"
- "f[flags associated with the process]"
- "s[state of the process]"
- "c[processor utilization for scheduling]"
- "uid[effective user ID number]"
- "ruid[real user ID number]"
- "gid[effective group ID number]"
- "rgid[real group ID numberu]"
- "projid[project ID number]"
- "project[project name]"
- "zoneid[zone ID number]"
- "zone[zone name]"
- "sid[process ID of the session leader]"
- "taskid[task ID of the process]"
- "class[scheduling class]"
- "pri[priority, higher number - higher priority]"
- "opri[obsolete priority, lower number - higher priority]"
- "lwp[lwd ID number]"
- "nlwp[number of lwps in the process]"
- "psr[number of the processor to which the process or lwp is bound]"
- "pset[ID of the processor set to which the process or lwp is bound]"
- "addr[memory address of the process]"
- "osz[total size of the process in virtual memory, in pages]"
- "wchan[address of an event for which the process is sleeping]"
- "stime[starting time or date of the process]"
- "rss[resident set size of the process, in kilobytes]"
- "pmem[ratio of resident set size to physical memory on the machine, in %]"
- "fname[first 8 bytes of base name of process's executable file]"
- "ctid[contract ID number]"
- "lgrp[home lgroup]"
-)
-_arguments \
- '-a[information about all processes most frequently requested]' \
- '-c[information in a format that reflects scheduler properties]' \
- '-d[information about all processes except session leaders]' \
- '-e[information about every process]' \
- '-f[full listing]' \
- '-g[only process data whose group leaders ID number(s) appears in grplist]:group leader ID list' \
- '-G[information for processes whose real group ID numbers are in gidlist]:real group ID list' \
- '-H[prints the home lgroup of the process]' \
- '-j[prints session ID and process group ID]' \
- '-l[long listing]' \
- '-L[information about each light weight process]' \
- '-o[specify output format]:property:_values -s , "property" $o_opt' \
- '-p[only process data whose process ID numbers are given in proclist]:process ID list' \
- '-P[Prints the number of the processor to which the process or lwp is bound]' \
- '-s[information on all session leaders whose IDs appear in sidlist]:session leader ID list' \
- '-t[lists only process data associated with term]:term' \
- '-u[only process data whose effective user ID number or login name is given in uidlist]:UID:_users' \
- '-U[information for processes whose real user ID numbers or login names are in uidlist]:UID:_users' \
- '-y[both RSS and SZ is reported in kilobytes, instead pages (used with -l)]' \
- '-z[lists only processes in the specified zones]:zone list' \
- '-Z[prints the name of the zone with which the process is associated]'
-}
-
-_ps "$@"
diff --git a/Completion/Solaris/Command/_ptree b/Completion/Solaris/Command/_ptree
index 035614b59..754979c37 100644
--- a/Completion/Solaris/Command/_ptree
+++ b/Completion/Solaris/Command/_ptree
@@ -1,23 +1,7 @@
#compdef ptree
-_ptree() {
- local curcontext="$curcontext" context state line ret=1
- typeset -A opt_args
-
- _arguments -s \
- '-a[all processes]' \
- '-c[show contract memberships]' \
- '-z[show processes in zone]:zone:($(zoneadm list))' \
- '*:pid or user:->pidoruser' && ret=0
-
- if [[ $ret -ne 0 ]]; then
- _alternative \
- 'users:logged-in user:compadd ${$(who -q)\:#(users=*|\#)}' \
- 'pids:pid:_pids'
- ret=$?
- fi
-
- return $ret
-}
-
-_ptree "$@"
+_arguments -s \
+ '-a[all processes]' \
+ '-c[show contract memberships]' \
+ '-z[show processes in zone]:zone:_zones' \
+ '*: : _alternative "users:logged-in user:_users_on" "pids:pid:_pids"'
diff --git a/Completion/Solaris/Type/_be_name b/Completion/Solaris/Type/_be_name
index b25a8ff22..4b80c65f2 100644
--- a/Completion/Solaris/Type/_be_name
+++ b/Completion/Solaris/Type/_be_name
@@ -1,18 +1,13 @@
#autoload
-local -a type be_names
-local name uuid activate mtpt space policy created snap
+local -a type be_names expl
zparseopts -D -E -a type t+:
-beadm list -H | while IFS=\; read name uuid active mtpt space policy created; do
- be_names=( $be_names $name )
-done
+be_names=( ${${(f)"$(_call_program boot-environs beadm list -H)"}%%;*} )
-if [[ -n $type[(r)all] ]]; then
- beadm list -sH | while IFS=\; read name snap space policy created; do
- be_names=( $be_names $snap )
- done
-fi
+[[ -n $type[(r)all] ]] &&
+ be_names+=( ${${${(f)"$(_call_program boot-environs beadm list -sH)"}#*;}%%;*} )
-compadd "$@" - $be_names
+_description boot-environs expl 'boot environment'
+compadd "$@" "$expl[@]" -a be_names
diff --git a/Completion/Solaris/Type/_zones b/Completion/Solaris/Type/_zones
index 0c2d273a2..92064d2b8 100644
--- a/Completion/Solaris/Type/_zones
+++ b/Completion/Solaris/Type/_zones
@@ -1,13 +1,11 @@
#autoload
-local -a type typearg
-local zonelist
+local -a type typearg expl
zparseopts -D -E -a type t+:
[[ -n $type[(r)c] ]] && typearg=-c
[[ -n $type[(r)i] ]] && typearg=-i
-zonelist=( ${="$(zoneadm list $typearg)"} )
-
-compadd "$@" - $zonelist
+_description zones expl zone
+compadd "$@" "$expl[@]" - ${="$(_call_program zones /usr/sbin/zoneadm list $typearg)"}
diff --git a/Completion/Unix/Command/_adb b/Completion/Unix/Command/_adb
index 2e36046c7..e687762d3 100644
--- a/Completion/Unix/Command/_adb
+++ b/Completion/Unix/Command/_adb
@@ -63,6 +63,7 @@ _adb() {
"root"
"usb"
"tcpip"
+ "sideload"
"ppp"
)
diff --git a/Completion/Unix/Command/_arp b/Completion/Unix/Command/_arp
index 64a8b8069..f340e979e 100644
--- a/Completion/Unix/Command/_arp
+++ b/Completion/Unix/Command/_arp
@@ -1,6 +1,6 @@
#compdef arp
-local state line expl curcontext="$curcontext"
+local state line expl curcontext="$curcontext" ret=1
local -a cmds
cmds=(-a --display -d --delete -s --set -f --file)
@@ -15,7 +15,9 @@ _arguments -C \
'(-H --hw-type -d --delete)'{-H,--hw-type}'[class of entries to check for]:class:(ether arcnet pronet ax25 netrom)' \
'(-n --numeric -d --delete -s --set -f --file)'{-n,--numeric}'[shows numerical addresses]' \
'(-v --verbose)'{-v,--verbose}'[be verbose]' \
- '(-a)1:host:->hostintable'
+ '(-a)1:host:->hostintable' && ret=0
[[ "$state" = hostintable ]] &&
- _wanted hosts expl 'host' compadd ${${${(f)"$(${words[1]} -an)"}##[ ?(]#}%%[ )]*}
+ _wanted hosts expl 'host' compadd ${${${(f)"$(${words[1]} -an)"}##[ ?(]#}%%[ )]*} && ret=0
+
+return ret
diff --git a/Completion/Unix/Command/_at b/Completion/Unix/Command/_at
index 8734e6b55..b22589020 100644
--- a/Completion/Unix/Command/_at
+++ b/Completion/Unix/Command/_at
@@ -1,6 +1,6 @@
#compdef atrm atq at batch
-local context state line expl
+local context state line expl ret=1
typeset -A opt_args
#todo (when extremely bored) make -l and -d do the atq and atrm completions
@@ -8,12 +8,12 @@ case $service in
atrm)
_arguments \
'-V[print version number]' \
- '*:job number:->jobs'
+ '*:job number:->jobs' && ret=0
;;
atq)
_arguments \
'-V[print version number]' \
- '-q[uses specified queue]:a-z+A-Z'
+ '-q[uses specified queue]:a-z+A-Z' && ret=0
;;
at|batch)
_arguments \
@@ -29,11 +29,13 @@ at|batch)
- atrm \
'-d[alias for atrm]' \
- show-job \
- '-c[cat specified jobs to stdout]:*:job number:->jobs'
+ '-c[cat specified jobs to stdout]:*:job number:->jobs' && ret=0
esac
case $state in
jobs)
- _wanted job expl 'job number' compadd ${(M)${(f)"$(_call_program job atq)"}##<->}
+ _wanted -C $context jobs expl 'job number' compadd ${(M)${(f)"$(_call_program job atq)"}##<->} && ret=0
;;
esac
+
+return ret
diff --git a/Completion/Unix/Command/_bittorrent b/Completion/Unix/Command/_bittorrent
index f7da2047a..1f305a1c0 100644
--- a/Completion/Unix/Command/_bittorrent
+++ b/Completion/Unix/Command/_bittorrent
@@ -21,7 +21,7 @@ case $service in
;&
btlaunchmanycurses)
_arguments -s -S \
- '(--responsefile)--responsefile+[specify file for server response]:file:_files -g "*"'\
+ '(--responsefile)--responsefile+[specify file for server response]:file:_files'\
"--url+[specify URL of torrent file]:URL:_urls"\
'(-i --ip)'{-i+,--ip+}'[specify ip address to report as]:ip address'\
"--bind+[specify ip to bind to instead of default]:ip:_bind_addresses"\
@@ -50,18 +50,18 @@ case $service in
"--max_initiate+[specify peers needed before stopping initiating new connections]:peers:"\
"--report_hash_failures+[report hash failures to user]:enable:(0 1)"\
"--rarest_first_priority_cutoff+[specify peers which need to have a piece before other partials take priority over rarest first]:peers:"\
- ':torrent file:_files -g "*.torrent(-.)"' \
- && return 0
+ ':torrent file:_files -g "*.torrent(-.)"'
+ return
;;
# Next up are the torrent file manipulation programs.
btshowmetainfo)
- _files -g "*.torrent(-.)" && return 0
- ;;
+ _files -g "*.torrent(-.)" && return
+ ;;
btrename)
- _files -g '*.torrent(-.)' && return 0
+ _files -g '*.torrent(-.)' && return
;;
btmakemetafile)
@@ -69,12 +69,12 @@ case $service in
'--piece_size_pow2+[specify power of 2 to set the piece size to]:power:' \
"--comment+[specify human-readable comment to put in .torrent]:comment:"\
"--target+[specify target file for the torrent]:file:_files"\
- ':file:_files -g "*"' \
- && return 0;
+ ':file:_files -g "*"'
+ return
;;
btreannounce)
- _files -g '*.torrent(-.)' && return 0
+ _files -g '*.torrent(-.)' && return
;;
# Lastly the tracker.
@@ -94,7 +94,7 @@ case $service in
"--min_time_between_log_flushes+[specify minimum time between log flushes]:time (s):" \
"--allowed_dir+[specify directory having downloadable torrents]:directory:_files -/" \
"--parse_allowed_interval+[specify interval between reloading allowed_dir]:time (min):" \
- "--show_names+[display names from allowed dir]:enable:(0 1)"\
- && return 0
- ;;
+ "--show_names+[display names from allowed dir]:enable:(0 1)"
+ return
+ ;;
esac
diff --git a/Completion/Unix/Command/_bogofilter b/Completion/Unix/Command/_bogofilter
index 44953cc71..ff36e83af 100644
--- a/Completion/Unix/Command/_bogofilter
+++ b/Completion/Unix/Command/_bogofilter
@@ -1,7 +1,5 @@
#compdef bogoutil bogotune bogofilter
-local expl ret bogotokens
-
_bogoutil_caching_policy () {
local -a oldp
@@ -14,6 +12,7 @@ _bogoutil_caching_policy () {
_bogoutil() {
+ local bogotokens expl ret=1
typeset -a _bogoutil_actions
_bogoutil_actions=(-h --help -V --version -d --dump -l --load -u
--upgrade -m -w -p -H --db-verify -r -R --db-prune --db-recover
@@ -46,30 +45,27 @@ _bogoutil() {
"($_bogoutil_actions)"'--db-remove-environment:database:_files -/' \
'--db_lk_max_locks[set max lock count]' \
'--db_lk_max_objects[set max object count]' \
- "($_bogoutil_actions)"'-h[help]' \
- "($_bogoutil_actions)"'--help' \
- "($_bogoutil_actions)"'-V[version]' \
- "($_bogoutil_actions)"'--version' \
+ "($_bogoutil_actions)"{-h,--help}'[help]' \
+ "($_bogoutil_actions)"{-V,--version}'[version]' \
'*:tokens:->tokens' && ret=0
zstyle -s ":completion:${curcontext}:" cache-policy update_policy
if [[ -z "$update_policy" ]]; then
zstyle ":completion:${curcontext}:" cache-policy _bogoutil_caching_policy
fi
-
+
case $state in
(tokens)
if ( [[ -z "$bogotokens" ]] || _cache_invalid bogotokens ) &&
! _retrieve_cache bogotokens; then
- bogotokens=(${${(f)"$(_call_program bogoutil bogoutil -d ~/.bogofilter/wordlist.db -c 50)"}%% *})
+ bogotokens=(${${(f)"$(_call_program bogotokens bogoutil -d ~/.bogofilter/wordlist.db -c 50)"}%% *})
_store_cache bogotokens bogotokens
- else
- :
fi
- _wanted tokens expl "token" \
- compadd -a bogotokens
+ _wanted tokens expl "token" compadd -a bogotokens && ret=0
;;
esac
+
+ return ret
}
case $service in
diff --git a/Completion/Unix/Command/_bpython b/Completion/Unix/Command/_bpython
index c51cc8c3c..233e032e6 100644
--- a/Completion/Unix/Command/_bpython
+++ b/Completion/Unix/Command/_bpython
@@ -13,10 +13,10 @@ all_opts=(
)
urwid_opts=(
- '(-r --reactor)'{-r,--reactor}'[use Twisted reactor instead of the event loop]:reactor:'
+ '(-r --reactor)'{-r,--reactor}'[use twisted reactor instead of the event loop]:reactor'
'--help-reactors[display list of available Twisted reactors]'
- '(-p --plugin)'{-p,--plugin}'[exectue a twistd plugin]:plugin:'
- '(-s --server)'{-s,--server}'[run an eval server on the given port]:port:'
+ '(-p --plugin)'{-p,--plugin}'[execute a twisted plugin]:plugin'
+ '(-s --server)'{-s,--server}'[run an eval server on the given port]:port:_ports'
)
gtk_opts=(
@@ -26,19 +26,19 @@ gtk_opts=(
case "$service" in
bpython|bpython2|bpython3)
_arguments \
- "$all_opts[@]" && return 0
+ "$all_opts[@]"
;;
bpython-urwid|bpython2-urwid|bpython3-urwid)
_arguments \
"$all_opts[@]" \
- "$urwid_opts[@]" && return 0
+ "$urwid_opts[@]"
;;
bpython-gtk|bpython2-gtk|bpython3-gtk)
_arguments \
"$all_opts[@]" \
- "$gtk_opts[@]" && return 0
+ "$gtk_opts[@]"
;;
esac
diff --git a/Completion/Unix/Command/_bzr b/Completion/Unix/Command/_bzr
index c28c2148e..28ebd145c 100644
--- a/Completion/Unix/Command/_bzr
+++ b/Completion/Unix/Command/_bzr
@@ -11,12 +11,12 @@ _arguments -C \
if (( ! $+_bzr_cmds )); then
typeset -gH _bzr_cmds
- _bzr_cmds=(${(f)"$(_call_program bzr bzr shell-complete)"})
+ _bzr_cmds=(${(f)"$(_call_program subcommands bzr shell-complete)"})
fi
if [[ $state != 'args' ]]; then
- _describe -t subcommand 'subcommand' _bzr_cmds
- return 0
+ _describe -t subcommands 'subcommand' _bzr_cmds
+ return
fi
cmd="$words[1]"
@@ -25,39 +25,35 @@ curcontext="${curcontext%:*:*}:bzr-$cmd:"
(( $+functions[_bzr_unknownFiles] )) ||
_bzr_unknownFiles() {
local fileList
- fileList=(${(ps:\0:)"$(bzr ls --null --unknown -R)"})
+ fileList=(${(ps:\0:)"$(_call_program files bzr ls --null --unknown -R)"})
compadd -af fileList
- return 0
}
(( $+functions[_bzr_unknownRoot] )) ||
_bzr_unknownRoot() {
- local fileList
- fileList=(${(ps:\0:)"$(bzr ls --null --from-root --unknown)"})
+ local -a fileList
+ fileList=(${(ps:\0:)"$(_call_program files bzr ls --null --from-root --unknown)"})
compadd -af fileList
- return 0
}
(( $+functions[_bzr_versionedFiles] )) ||
_bzr_versionedFiles() {
local fileList
- fileList=(${(ps:\0:)"$(bzr ls --null --versioned -R)"})
+ fileList=(${(ps:\0:)"$(_call_program files bzr ls --null --versioned -R)"})
compadd -af fileList
- return 0
}
(( $+functions[_bzr_modifiedFiles] )) ||
_bzr_modifiedFiles() {
local fileList
- fileList=(${(ps:\0:)"$(bzr status . --versioned --short | cut -b 5- | tr '\n' '\0')"})
+ fileList=(${(ps:\0:)"$(_call_program files bzr status . --versioned --short | cut -b 5- | tr '\n' '\0')"})
compadd -af fileList
- return 0
}
(( $+functions[_bzr_completeParents] )) ||
_bzr_completeParents() {
- local parentFile=$(bzr root 2>/dev/null)/.bzr/branch/parent
- [[ -r $parentFile ]] && compadd -X "Completing parents" $(cat $parentFile)
+ local parentFile=$(_call_program parents bzr root)/.bzr/branch/parent
+ [[ -r $parentFile ]] && _wanted parents expl parent compadd -- $(<$parentFile)
}
args=( '(-)'{--help,-h}'[show help message]' )
@@ -99,7 +95,7 @@ case $cmd in
'--lightweight[perform a lightweight checkout]'
'(-r --revision)'{--revision=,-r}'[the revision to get]:rev:'
)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(rename|move|mv)
@@ -194,7 +190,7 @@ case $cmd in
'(-v --verbose)'{--verbose,-v}'[display more information]'
'*:local repository:_files -/'
)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(missing)
@@ -210,7 +206,7 @@ case $cmd in
'(-v --verbose)'{--verbose,-v}'[display more information]'
'*:local repository:_files -/'
)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(commit|checkin|ci)
@@ -226,8 +222,19 @@ case $cmd in
)
;;
+(shelve)
+ args+=(
+ '--destroy[Destroy removed changes instead of shelving them]'
+ '(-m --message)'{--message=,-m}'[shelve message]:message text:'
+ '--all[shelve all changes]'
+ '(-q --quiet)'{--quiet,-q}'[be quiet]'
+ '(-v --verbose)'{--verbose,-v}'[display more information]'
+ '*:modified files:_bzr_modifiedFiles'
+ )
+ ;;
+
(bind|break-lock|reconcile)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(register-branch)
@@ -240,7 +247,7 @@ case $cmd in
'--link-bug=[the bug this branch fixes]:bug-ID:'
'--product=[launchpad product short name to associate with the branch]:product:'
)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(remerge)
@@ -249,7 +256,7 @@ case $cmd in
'--reprocess[reprocess to reduce spurious conflicts]'
'--show-base[show base revision text in conflicts]'
)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(conflicts|added|deleted|modified|unknowns|directories|ignored|unbind|nick|revno|version)
@@ -322,7 +329,7 @@ case $cmd in
'--show-base[show base revision text in conflicts]'
'*:local repository:_files -/'
)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(ls)
@@ -346,7 +353,7 @@ case $cmd in
'(-v --verbose -q --quiet)'{--verbose,-v}'[display more information]'
'*:local repository:_files -/'
)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(help)
@@ -355,8 +362,8 @@ case $cmd in
'*:subcmds:->cmds'
)
_arguments -s "$args[@]" && ret=0
- _describe -t subcommand 'subcommand' _bzr_cmds
- return 0
+ _describe -t subcommands 'subcommand' _bzr_cmds && ret=0
+ return ret
;;
# Plugins
@@ -380,7 +387,7 @@ case $cmd in
'--remember[remember the specified location as a default]'
'*:local repository:_files -/'
)
- _bzr_completeParents
+ _bzr_completeParents && ret=0
;;
(clean-tree)
@@ -409,10 +416,11 @@ case $cmd in
;;
(*)
- _message "unknown bzr command completion: $cmd"
- return 1
+ _default
+ return
;;
esac
_arguments -s "$args[@]" && ret=0
-return $ret
+
+return ret
diff --git a/Completion/Unix/Command/_cabal b/Completion/Unix/Command/_cabal
new file mode 100644
index 000000000..bd81cf261
--- /dev/null
+++ b/Completion/Unix/Command/_cabal
@@ -0,0 +1,9 @@
+#compdef cabal
+
+local -a subcmds
+
+subcmds=(${${${${${(f)"$(cabal --help)"}[(r)Commands:*,(r)For more information*]}[2,-2]}# }%% *})
+
+_arguments \
+ '1:subcmd:compadd -a subcmds' \
+ ':other: _alternative "options:option:compadd -- $(cabal $words[2] --list-options)" "files:file:_files"'
diff --git a/Completion/Unix/Command/_cdrdao b/Completion/Unix/Command/_cdrdao
index 06b47c9b1..ad1bf4034 100644
--- a/Completion/Unix/Command/_cdrdao
+++ b/Completion/Unix/Command/_cdrdao
@@ -4,108 +4,85 @@
# Command completion and main loop {{{1
-_cdrdao_commands () {
- local -a commands
-
- commands=(
- 'show-toc:print out a summary of a TOC'
- 'read-toc:create a TOC file based on a CD'
- 'read-cd:create a TOC file and image file based on a CD'
- 'read-cddb:add CD-TEXT data from a CDDB server to a TOC'
- 'show-data:print out samples that would be written to CD'
- 'read-test:check if data described in a TOC can be read from a CD'
- 'disk-info:show information about a CD'
- 'msinfo:generate mkisofs command for creating multi-session CD'
- 'unlock:try to unlock a recorder after a failed run'
- 'blank:blank a CD-RW'
- 'simulate:simulate a write'
- 'write:write a CD based on a TOC'
- 'copy:copy a CD'
- )
-
- _describe -t commands 'cdrdao command' commands && ret=0
-}
-
_cdrdao () {
- local curcontext=$curcontext ret=1
-
- local context state line
- typeset -A opt_args
- _arguments \
- ':command:->command' \
- '*::options:->options' && ret=0
- case $state in
- (command)
- _cdrdao_commands
- ;;
- (options)
- curcontext="${curcontext%:*:*}:cdrdao-$words[1]:"
- _call_function ret _cdrdao-$words[1]
- ;;
- esac
+ local ret=1
+ local -a commands
+ if (( CURRENT == 2 )); then
+ commands=( ${${${(M)${(f)"$(_call_program subcommands cdrdao 2>&1)"}:# *}// #- /:}#??} )
+ _describe -t subcommands 'cdrdao command' commands && ret=0
+ else
+ local cmd="${words[2]}"
+ local curcontext="${curcontext%:*:*}:cdrdao-$cmd:"
+ shift words
+ (( CURRENT-- ))
+ if ! _call_function ret _cdrdao-$cmd; then
+ _default && ret=0
+ fi
+ fi
+ return ret
}
# Common arguments {{{1
-declare -ga tmpfile_args
-tmpfile_args=(
+declare -ga _cdrdao_tmpfile_args
+_cdrdao_tmpfile_args=(
'--tmpdir[directory to store temporary data in]:directory:_directories'
- '--keep[do not remove temporary data when done]')
-
-declare -ga device_args
-device_args=(
- '--device[set SCSI address of the CD recorder]:device:__cdrdao-device'
- '--driver[use given driver for the CD recorder]:driver:__cdrdao-drivers')
+ '--keep[do not remove temporary data when done]'
+)
# TODO: Gah! Fix a cddb server spec matcher
-declare -ga cddb_args
-cddb_args=(
+declare -ga _cdrdao_cddb_args
+_cdrdao_cddb_args=(
'--cddb-servers[specify list of CDDB servers to use]:CDDB servers:'
'--cddb-timeout[specify timeout in seconds for connections to CDDB servers]: :_guard "[[\:digit\:]]" timeout'
- '--cddb-directory[directory where fetched CDDB records will be stored]:directory:_directories')
+ '--cddb-directory[directory where fetched CDDB records will be stored]:directory:_directories'
+)
-declare -g paranoiamode_arg=
-paranoiamode_arg='--paranoia-mode[set correction mode for digital audio extraction]:mode:(("0\:no checking" "1\:perform overlapped reading to avoid jitter" "2\:like 1 but with checks of read audio data" "3\:like 2 but with scratch detection/repair (default)"))'
+declare -g _cdrdao_paranoiamode_arg
+_cdrdao_paranoiamode_arg='--paranoia-mode[set correction mode for digital audio extraction]:mode:(("0\:no checking" "1\:perform overlapped reading to avoid jitter" "2\:like 1 but with checks of read audio data" "3\:like 2 but with scratch detection/repair (default)"))'
-declare -g fasttoc_arg=
-fasttoc_arg='--fast-toc[skip pre-gap-length and index-mark extraction]'
+declare -g _cdrdao_fasttoc_arg
+_cdrdao_fasttoc_arg='--fast-toc[skip pre-gap-length and index-mark extraction]'
-declare -g swap_arg=
-swap_arg='--swap[swap the byte order of samples]'
+declare -g _cdrdao_swap_arg
+_cdrdao_swap_arg='--swap[swap the byte order of samples]'
-declare -g reload_arg=
-reload_arg='--reload[reload the disk if necessary]'
+declare -g _cdrdao_reload_arg
+_cdrdao_reload_arg='--reload[reload the disk if necessary]'
-declare -g eject_arg=
-eject_arg='--eject[eject CD after completed operation]'
+declare -g _cdrdao_eject_arg
+_cdrdao_eject_arg='--eject[eject CD after completed operation]'
-declare -g speed_arg=
-speed_arg='-speed[set writing speed]: :_guard "[[\:digit\:]]##" speed'
+declare -g _cdrdao_speed_arg
+_cdrdao_speed_arg='-speed[set writing speed]: :_guard "[[\:digit\:]]##" speed'
-declare -ga common_args
-common_args=(
+declare -ga _cdrdao_common_args
+_cdrdao_common_args=(
'(*)'{-h,--help}'[display command/option summary]'
'-v[set verbosity level]: :_guard "[[\:digit\:]]##" verbosity')
-declare -ga common_toc_args
-common_toc_args=(
- $common_args
+declare -ga _cdrdao_common_toc_args
+_cdrdao_common_toc_args=(
+ $_cdrdao_common_args
':TOC file:_files -g "*.toc(-.)"')
-declare -ga common_device_args
-common_device_args=(
- $common_args
- $device_args)
-
-declare -ga common_toc_device_args
-common_toc_device_args=(
- $common_toc_args
- $common_device_args
- $force_arg)
-
-declare -ga common_read_args
-common_read_args=(
+declare -ga _cdrdao_common_device_args
+_cdrdao_common_device_args=(
+ $_cdrdao_common_args
+ '--device[set SCSI address of the CD recorder]:device:__cdrdao-device'
+ '--driver[use given driver for the CD recorder]:driver:__cdrdao-drivers'
+)
+
+declare -ga _cdrdao_common_toc_device_args
+_cdrdao_common_toc_device_args=(
+ $_cdrdao_common_toc_args
+ $_cdrdao_common_device_args
+ '--force[force execution of operation]'
+)
+
+declare -ga _cdrdao_common_read_args
+_cdrdao_common_read_args=(
'--rspeed[set reading speed]: :_guard "[[\:digit\:]]##" speed'
'--session[specify what session to process on multi-session CDs]: :_guard "[[\:digit\:]]##" "session number"'
'--read-subchan[set sub-channel reading-mode]:mode:(("rw\:de-interleaved and error corrected" "rw_raw\:not de-interleaved, not error-corrected, and L-EC data included"))'
@@ -128,18 +105,18 @@ _cdrdao-toc-size () {
__cdrdao-show-toc-or-toc-info-or-toc-size () {
_arguments \
- $common_toc_args \
- $tmpfile_args && ret=0
+ $_cdrdao_common_toc_args \
+ $_cdrdao_tmpfile_args
}
_cdrdao-read-toc () {
- __cdrdao-read-toc-or-read-cd \
- $fasttoc_arg
+ __cdrdao-read-toc-or-read-cd $_cdrdao_cddb_args
}
_cdrdao-read-cd () {
__cdrdao-read-toc-or-read-cd \
- $paranoiamode_arg
+ $_cdrdao_paranoiamode_arg \
+ $_cdrdao_cddb_args
}
__cdrdao-read-toc-or-read-cd () {
@@ -148,30 +125,31 @@ __cdrdao-read-toc-or-read-cd () {
__cdrdao-read-toc-or-read-cd-or-copy-dependent-args
_arguments \
- $common_toc_device_args \
- $common_read_args \
- $dependent_args
+ $_cdrdao_common_toc_device_args \
+ $_cdrdao_common_read_args \
+ $dependent_args \
+ $_cdrdao_fasttoc_arg \
'--datafile[set name of data file placed in TOC file]:file:_files' \
'--read-raw[read data in raw format from CD]' \
'--no-mode2-mixed[if MODE2_FORM1 or MODE2_FORM2, do not extract as MODE2_FORM_MIX]' \
- $* && ret=0
+ "$@" && ret=0
}
_cdrdao-read-cddb () {
_arguments \
- $common_toc_args \
- $cddb_args && ret=0
+ $_cdrdao_common_toc_args \
+ $_cdrdao_cddb_args
}
_cdrdao-show-data () {
_arguments \
- $common_toc_args \
- $swap_arg && ret=0
+ $_cdrdao_common_toc_args \
+ $_cdrdao_swap_arg
}
_cdrdao-read-test () {
_arguments \
- $common_toc_args && ret=0
+ $_cdrdao_common_toc_args
}
_cdrdao-disk-info () {
@@ -180,13 +158,18 @@ _cdrdao-disk-info () {
__cdrdao-disk-info-or-drive-info () {
_arguments \
- $common_device_args && ret=0
+ $_cdrdao_common_device_args
+}
+
+_cdrdao-discid() {
+ _arguments $_cdrdao_common_device_args $_cdrdao_cddb_args \
+ '--query-string[print out CDDB query only]'
}
_cdrdao-msinfo () {
_arguments \
- $common_device_args \
- $reload_arg && ret=0
+ $_cdrdao_common_device_args \
+ $_cdrdao_reload_arg
}
_cdrdao-drive-info () {
@@ -195,22 +178,22 @@ _cdrdao-drive-info () {
_cdrdao-unlock () {
_arguments \
- $common_device_args \
- $reload_arg \
- $eject_arg && ret=0
+ $_cdrdao_common_device_args \
+ $_cdrdao_reload_arg \
+ $_cdrdao_eject_arg
}
_cdrdao-blank () {
_arguments \
- $common_device_args \
- $speed_arg \
+ $_cdrdao_common_device_args \
+ $_cdrdao_speed_arg \
'--blank-mode[set the blanking mode]:blanking mode:(("full\:completely erase data" "minimal\:only dereference data"))' \
- $eject_arg && ret=0
+ $_cdrdao_eject_arg
}
_cdrdao-scanbus () {
_arguments \
- $common_args && ret=0
+ $_cdrdao_common_args
}
_cdrdao-simulate () {
@@ -218,26 +201,26 @@ _cdrdao-simulate () {
}
__cdrdao-simulate-or-write () {
- local capacity_arg=
-
+ local _cdrdao_capacity_arg=
+
if (( $words[(I)--full-burn] )); then
- capacity_arg='--capacity[set disk capacity for --full-burn]: :_guard "[[\:digit\:]]" minutes'
+ _cdrdao_capacity_arg='--capacity[set disk capacity for --full-burn]: :_guard "[[\:digit\:]]" minutes'
fi
_arguments \
- $common_toc_device_args \
- $speed_arg \
+ $_cdrdao_common_toc_device_args \
+ $_cdrdao_speed_arg \
'--multi[do not close the session after successful write]' \
'--overburn[allow overburing of medium]' \
'--full-burn[force burning to the outer disk edge]' \
- $capacity_arg \
- $eject_arg \
- $swap_arg \
+ $_cdrdao_capacity_arg \
+ $_cdrdao_eject_arg \
+ $_cdrdao_swap_arg \
'--buffers[set fifo buffer size]: :_guard "[[\:digit\:]]" size' \
- $reload_arg \
- $tmpfile_args \
+ $_cdrdao_reload_arg \
+ $_cdrdao_tmpfile_args \
'-n[do not pause before writing]' \
- $* && ret=0
+ $*
}
_cdrdao-write () {
@@ -254,24 +237,24 @@ __cdrdao-read-toc-or-read-cd-or-copy-dependent-args () {
fi
if (( words[(I)--with-cddb] )); then
- dependent_args+=$cddb_args
+ dependent_args+=$_cdrdao_cddb_args
fi
}
_cdrdao-copy () {
- local -ga dependent_args
+ local -a dependent_args
__cdrdao-read-toc-or-read-cd-or-copy-dependent-args
_cdrdao-write \
- $dependent_args
- $common_read_args
+ $dependent_args \
+ $_cdrdao_common_read_args \
'--source-device[set SCSI address of the CD reader]:device:__cdrdao-device' \
'--source-driver[use given driver for the CD reader]:driver:__cdrdao-drivers' \
'--on-the-fly[perform on-the-fly copy of CD (no image created)]' \
- $fasttoc_arg \
+ $_cdrdao_fasttoc_arg \
'--keepimage[do not remove generated image when done]' \
- $paranoiamode_arg && ret=0
+ $_cdrdao_paranoiamode_arg
}
# Type completion {{{1
@@ -280,24 +263,21 @@ __cdrdao-device () {
# Use cdrdao scanbus and also check what OS we're running under and provide
# additional stuff, like devices (/dev/sg0)
local -a devices
+ devices=(${${(f)"$(_call_program devices cdrdao scanbus -v 0 2>&1)"}%% :*})
- devices=(${(f)"$(_call_program devices cdrdao scanbus -v 0 2>/dev/null)"})
- if (( ${#pipestatus:#0} > 0 )); then
- return 1
- fi
-
- _wanted devices expl 'device' compadd - $devices
+ _wanted devices expl 'device' compadd -a devices
}
__cdrdao-drivers () {
- local -a drivers
-
- drivers=(${(f)"$(_call_program drivers cut -d'|' -f4 /usr/share/cdrdao/drivers -s 2>/dev/null | sort -u)"})
- if (( ${#pipestatus:#0} > 0 )); then
- return 1
+ local suf
+ local -Ua drivers
+ drivers=(${(f)"$(_call_program drivers cut -d'\|' -f4 /usr/share/cdrdao/drivers -s)"})
+ if compset -P \*:; then
+ _message -e options option
+ else
+ compset -S :\* || suf=-qS:
+ _wanted drivers expl 'driver' compadd $suf -a drivers
fi
-
- _wanted drivers expl 'driver' compadd -qS: - $drivers
}
# }}}1
diff --git a/Completion/Unix/Command/_chmod b/Completion/Unix/Command/_chmod
index 5d3cb2c78..85e6df1ae 100644
--- a/Completion/Unix/Command/_chmod
+++ b/Completion/Unix/Command/_chmod
@@ -1,34 +1,52 @@
-#compdef chmod
+#compdef chmod gchmod
local curcontext="$curcontext" state line expl ret=1
local -a args privs
-args=( '*:file:->files' )
-(( $+words[(r)--reference*] )) || args+=( '1:mode:->mode' )
+args=( '*:file:->files' '1:mode:->mode' )
if _pick_variant gnu=Free\ Soft unix --version; then
args+=(
'(-v --verbose -c --changes)'{-c,--changes}'[report changes made]'
'(-v --verbose -c --changes)'{-v,--verbose}'[output a diagnostic for every file processed]'
'(-f --silent --quiet)'{-f,--silent,--quiet}'[suppress most error messages]'
- '--reference=[copy permissions of specified file]:file:_files'
+ '(--no-preserve-root)--preserve-root[fail to operate recursively on /]'
+ "(--preserve-root)--no-preserve-root[don't treat / specially (default)]"
+ '(1)--reference=[copy permissions of specified file]:file:_files'
'(-R --recursive)'{-R,--recursive}'[change files and directories recursively]'
'(- : *)--help[display help information]'
'(- : *)--version[display version information]'
)
- privs=(
- 'X[execute only if executable to another]'
- "u[owner's current permissions]"
- "g[group's current permissions]"
- "o[other's current permissions]"
- )
else
- # based on $OSTYPE = solaris2.8
args+=(
'-f[suppress most error messages]'
'-R[change files and directories recursively]'
)
- privs=( 'l[mandatory locking]' )
+ case $OSTYPE in
+ freebsd*|dragonfly*|darwin*)
+ args+=( '-v[output a diagnostic for every file processed]')
+ ;|
+ freebsd*|netbsd*|darwin*|dragonfly*)
+ args+=( "-h[operate on symlinks them self]" )
+ ;|
+ freebsd*|openbsd*|netbsd*|darwin*|dragonfly*)
+ args+=(
+ '(-H -L -P)-L[follow all symlinks]'
+ '(-H -L -P)-H[follow symlinks on the command line]'
+ '(-H -L -P)-P[do not follow symlinks (default)]'
+ )
+ ;|
+ darwin*)
+ args+=(
+ '(1)-C[returns false if any of the named files have ACLs]'
+ '(1)-N[remove ACLs from specified files]'
+ '(1)-E[read ACL info from stdin as a sequential list of ACEs]'
+ '(1)-i[removes inherited bit from all entries in named files ACLs]'
+ '(1)-I[removes all inherited entries from named files ACLs]'
+ )
+ ;;
+ solaris*) privs=( 'l[mandatory locking]' ) ;;
+ esac
fi
_arguments -C -s "$args[@]" && ret=0
@@ -43,13 +61,17 @@ case "$state" in
_values -S '' privilege \
'r[read]' 'w[write]' 'x[execute]' \
's[set uid/gid]' 't[sticky]' \
+ 'X[execute only if directory or executable to another]' \
+ "u[owner's current permissions]" \
+ "g[group's current permissions]" \
+ "o[other's current permissions]" \
"$privs[@]" && ret=0
else
suf=( -S '' )
compset -P '*'
_alternative -O suf \
'who:who:((u\:user g\:group a\:all o\:others))' \
- 'operators:operator:(+ - =)'
+ 'operators:operator:(+ - =)' && ret=0
fi
;;
files)
diff --git a/Completion/Unix/Command/_chown b/Completion/Unix/Command/_chown
index b4539315d..641b5a773 100644
--- a/Completion/Unix/Command/_chown
+++ b/Completion/Unix/Command/_chown
@@ -1,29 +1,42 @@
-#compdef chown chgrp
+#compdef chown chgrp zf_chown=chown zf_chgrp=chgrp
local curcontext="$curcontext" state line expl ret=1
-local suf usr grp req deref args
+local suf usr grp req deref pattern arg args
if _pick_variant gnu=Free\ Soft unix --version; then
args=(
'(-c --changes -v --verbose)'{-c,--changes}'[report each change made]'
'(-c --changes -v --verbose)'{-v,--verbose}'[output info for every file processed]'
'(-h --no-dereference)--dereference[dereference symlinks]'
- '(-h --no-dereference --dereference)'{-h,--no-dereference}'[operate on symlinks them self]'
+ '(-h --no-dereference --dereference)'{-h,--no-dereference}'[operate on symlinks themselves]'
'(-f --silent --quiet)'{-f,--silent,--quiet}"[don't report errors]"
+ '--preserve-root[fail to operate recursively on /]'
'--reference=[copy ownership of specified file]:file:_files'
'(-R --recursive)'{-R,--recursive}'[change files and directories recursively]'
+ '(-H -L -P)-L[follow all symlinks]'
+ '(-H -L -P)-H[follow symlinks on the command line]'
+ '(-H -L -P)-P[do not follow symlinks (default)]'
'(- : *)--help[display help information]'
'(- : *)--version[display version information]'
)
[[ $service = chown ]] &&
args+=( '--from=[restrict changes to files by current ownership]: :->owner' )
else
- # based on $OSTYPE = solaris2.8
args=(
"-f[don't report errors]"
"-h[operate on symlinks them self]"
'-R[change files and directories recursively]'
+ '(-H -L -P)-L[follow all symlinks]'
+ '(-H -L -P)-H[follow symlinks on the command line]'
+ '(-H -L -P)-P[do not follow symlinks (default)]'
)
+ for pattern arg in \
+ 'freebsd*' "-x[don't traverse file systems]" \
+ '(darwin|dragonfly|(free|net)bsd)*' '-v[output info for every file processed]' \
+ 'solaris2.<11->' '-s[owner and/or group are Windows SID strings]'
+ do
+ [[ $OSTYPE = $~pattern ]] && args+=( $arg )
+ done
fi
(( $+words[(r)--reference*] )) || args+=( '(--reference)1: :->owner' )
@@ -32,8 +45,8 @@ _arguments -C -s "$args[@]" '*:files:->files' && ret=0
case $state in
owner)
if [[ $service = chgrp ]] || compset -P '*[:.]'; then
- if (( EGID && $+commands[groups] )); then # except for root
- _wanted groups expl 'group' compadd $(groups) && return 0
+ if (( EGID && $+commands[groups] && ! $+funcstack[(r)_sudo] )); then # except for root
+ _wanted groups expl 'group' compadd $(groups) && return 0
fi
_groups && ret=0
else
diff --git a/Completion/Unix/Command/_cmp b/Completion/Unix/Command/_cmp
new file mode 100644
index 000000000..bcede8b0b
--- /dev/null
+++ b/Completion/Unix/Command/_cmp
@@ -0,0 +1,33 @@
+#compdef cmp gcmp
+
+local args variant
+_pick_variant -r variant gnu=GNU $OSTYPE --version
+
+case $variant in
+ gnu)
+ args=(
+ '(-b --print-bytes)'{-b,--print-bytes}'[print differing bytes]'
+ '(-i --ignore-initial)'{-i+,--ignore-initial}'[skip specified number of bytes]:bytes'
+ '(-l --verbose -s --silent --quiet)'{-l,--verbose}'[output all differences]'
+ '(-n --bytes)'{-n+,--bytes=}'[specify maximum bytes to compare]:bytes'
+ '(-s --quiet --silent -l --verbose)'{-s,--quiet,--silent}'[return status alone signifies differences]'
+ '(- *)'{-v,--version}'[display version information]'
+ '(- *)--help[display help information]'
+ )
+ ;;
+ freebsd*|openbsd*)
+ args=(
+ "-h[don't follow symbolic links]"
+ '-x[hexadecimal output and zero based offset index]'
+ '-z[compare file sizes first]'
+ )
+ ;&
+ *)
+ args+=(
+ '(-s)-l[output all differences]'
+ '(-l)-s[silent: return status alone signifies differences]'
+ )
+ ;;
+esac
+
+_arguments -s $args '1:file 1:_files' '2:file 2:_files' '::byte offset' '::byte offset'
diff --git a/Completion/Unix/Command/_comm b/Completion/Unix/Command/_comm
index e90c317f6..d1d835f6a 100644
--- a/Completion/Unix/Command/_comm
+++ b/Completion/Unix/Command/_comm
@@ -1,20 +1,27 @@
-#compdef comm
+#compdef comm gcomm
local -a args
args=(
- '-1[suppress lines unique to FILE1]'
- '-2[suppress lines unique to FILE2]'
+ '-1[suppress lines unique to first file]'
+ '-2[suppress lines unique to second file]'
'-3[suppress lines that appear in both files]'
- '1:file1 to compare:_files'
- '2:file2 to compare:_files'
+ '1:file to compare:_files'
+ '2:file to compare:_files'
)
if _pick_variant gnu=GNU unix --version; then
args+=(
+ '(--nocheck-order)--check-order[check input is correctly sorted]'
+ "(--check-order)--nocheck-order[don't check input is correctly sorted]"
+ '--output-delimiter=:delimiter'
'(- : *)--version[display version information]'
'(- : *)--help[display help information]'
)
+elif [[ $OSTYPE = (freebsd|dragonfly|darwin)* ]]; then
+ args+=( '-i[case insensitive comparison of lines]' )
+elif [[ $OSTYPE = (openbsd|netbsd)* ]]; then
+ args+=( '-f[case insensitive comparison of lines]' )
fi
_arguments -s $args
diff --git a/Completion/Unix/Command/_cp b/Completion/Unix/Command/_cp
index 5013f852c..4c4dea2e9 100644
--- a/Completion/Unix/Command/_cp
+++ b/Completion/Unix/Command/_cp
@@ -1,62 +1,65 @@
-#compdef cp
+#compdef cp gcp
if _pick_variant gnu=GNU unix --version; then
_arguments -s -S \
- '(-a --archive)'{-a,--archive}'[same as -dR --preserve=all]' \
+ '(-a --archive)'{-a,--archive}'[archive mode, same as -dR --preserve=all]' \
+ "--attributes-only[don't copy file data, just attributes]" \
'(-b --backup)-b[backup]' \
- '(-b --backup)--backup=[backup]:method:(none off numbered t existing nil simple never)' \
+ '(-b --backup)--backup=-[backup each destination file]::method:(none off numbered t existing nil simple never)' \
'--copy-contents[copy contents of special files when recursive]' \
'-d[same as --no-dereference --preserve=links]' \
'(-f --force)'{-f,--force}'[remove and retry for destinations that cannot be opened]' \
- '(-i --interactive)'{-i,--interactive}'[prompt before overwrite]' \
+ '(-i --interactive -n --no-clobber)'{-i,--interactive}'[prompt before overwrite]' \
'-H[follow command-line symbolic links]' \
'(-l --link)'{-l,--link}'[link files instead of copying]' \
'(-L --dereference)'{-L,--dereference}'[always follow symbolic links]' \
- '(-n --no-clobber)'{-n,--no-clobber}'[do not overwrite an existing file]' \
+ (-n --no-clobber -i --interactive){-n,--no-clobber}"[don't overwrite an existing file]" \
'(-P --no-dereference)'{-P,--no-dereference}'[never follow symbolic links]' \
'-p[same as --preserve=mode,ownership,timestamps]' \
- '--preserve=[preserve specified attributes]:attributes to preserve:_values -s , mode timestamps ownership links context xattr all' \
- '--no-preserve=[don'\''t preserve specified attributes]:attributes not to preserve:_values -s , mode timestamps ownership links context xattr all' \
+ '--preserve=-[preserve specified attributes]:: :_values -s , attribute mode timestamps ownership links context xattr all' \
+ "--no-preserve=[don't preserve specified attributes]: :_values -s , attribute mode timestamps ownership links context xattr all" \
'--parents[append source path to target directory]' \
'(-R -r --recursive)'{-R,-r,--recursive}'[copy directories recursively]' \
- '--reflink=[control clone/CoW copies]:when to perform a lightweight copy:(always auto)' \
+ '--reflink=-[control clone/CoW copies]::when to perform a lightweight copy:(always auto)' \
'--remove-destination[remove each existing destination file before attempting to open it]' \
'--sparse=[control creation of sparse files]:when to create sparse files:(auto always never)' \
'--strip-trailing-slashes[remove any trailing slashes from each source argument]' \
'(-s --symbolic-link)'{-s,--symbolic-link}'[make symbolic links instead of copies of non-directories]' \
- '(-S --suffix)'{-S,--suffix=}'[override the usual backup suffix]:backup suffix:' \
- '(-t --target-directory)'{-t,--target-directory=}'[copy all source arguments into target directory]:target directory:_files -/' \
+ '(-S --suffix)'{-S+,--suffix=}'[override the usual backup suffix]:backup suffix' \
+ '(-t --target-directory)'{-t+,--target-directory=}'[copy all source arguments into target directory]:target directory:_files -/' \
'(-T --no-target-directory)'{-T,--no-target-directory}'[treat DEST as a normal file]' \
'(-u --update)'{-u,--update}'[copy only when source is newer than destination or destination is missing]' \
'(-v --verbose)'{-v,--verbose}'[explain what is being done]' \
'(-x --one-file-system)'{-x,--one-file-system}'[stay on this file system]' \
- '--help' \
- '--version' \
+ '(--context)-Z[set destination SELinux security context]' \
+ '(-Z)--context=-[set destination SELinux security context]::context' \
+ '(- *)--help' '(- *)--version' \
'*:file or directory:_files'
-
-elif [[ "$OSTYPE" == darwin* ]]; then
- _arguments -s -S \
- '-R[copy directories recursively]' \
- '(-L -P)-H[with -R, follow symlinks on the command line]' \
- '(-H -P)-L[with -R, follow all symlinks]' \
- '(-H -L)-P[with -R, do not follow symlinks (default)]' \
- '(-i -n)-f[force overwriting existing file]' \
- '(-f -n)-i[confirm before overwriting existing file]' \
- '(-f -i)-n[do not overwrite existing file]' \
- '-a[same as -pRP]' \
- '-p[preserve timestamps, mode, owner, flags, ACLs, and Extended Attributes]' \
- '-v[show file names as they are copied]' \
- '-X[do not copy Extended Attributes or resource forks]' \
- '(-)*:file or directory:_files'
-
-else # assume POSIX
- _arguments -s -S \
+else
+ local pattern arg args
+ args=(
+ '(-L -P)-H[follow symlinks on the command line in recursive mode]'
+ '(-H -P)-L[follow all symlinks in recursive mode]'
+ '(-H -L)-P[do not follow symlinks in recursive mode (default)]'
+ '(-i -n)-f[force overwriting existing file]'
+ '(-f -n)-i[confirm before overwriting existing file]'
+ '-p[preserve timestamps, mode, owner, flags, ACLs, and extended attributes]'
'-R[copy directories recursively]' \
- '(-L -P)-H[with -R, follow symlinks on the command line]' \
- '(-H -P)-L[with -R, follow all symlinks]' \
- '(-H -L)-P[do not follow symlinks]' \
- '(-i)-f[force overwriting existing file]' \
- '(-f)-i[confirm before overwriting existing file]' \
- '-p[preserve timestamps, mode, and owner]' \
'(-)*:file or directory:_files'
+ )
+ for pattern arg in \
+ '(aix|hpux|irix|solaris)*' '-r[copy directories recursively]' \
+ 'solaris2.<9->*' '-@[preserve extended attributes]' \
+ 'solaris2.<11->*' '-/[preserve extended attributes and extended system attributes]' \
+ '(darwin|dragonfly|freebsd)*' "(-f -i)-n[don't overwrite existing file]" \
+ 'netbsd*' "-N[don't copy file flags]" \
+ '(darwin|dragonfly|freebsd|netbsd)*' '-a[archive mode, same as -RpP]' \
+ '(dragonfly|freebsd)*' '-l[link files instead of copying]' \
+ '(darwin|dragonfly|freebsd|netbsd)*' '-v[show file names as they are copied]' \
+ 'darwin*' "-X[don't copy extended attributes or resource forks]" \
+ '(dragonfly|freebsd)*' "-x[don't traverse file systems]"
+ do
+ [[ $OSTYPE = $~pattern ]] && args+=( $arg )
+ done
+ _arguments -s -S $args
fi
diff --git a/Completion/Unix/Command/_cpio b/Completion/Unix/Command/_cpio
index 280a8930f..6b07a214a 100644
--- a/Completion/Unix/Command/_cpio
+++ b/Completion/Unix/Command/_cpio
@@ -1,17 +1,17 @@
#compdef cpio
local args ig curcontext="$curcontext" state line
-local expl ret
+local expl ret=1
local fmts='(bar bin odc newc crc tar ustar hpbin hpodc)'
_pick_variant -r ig gnu=GNU unix --version
if (( CURRENT == 2 )); then
- # Complete arguments
+ # Complete arguments
args=('-o[create archive]' '-i[extract from archive]'
'-p[run as filter on directory tree]')
[[ $ig = gnu ]] && args=($args '--create[create archive]'
- '--extract[extract from archive]'
+ '--extract[extract from archive]'
'--pass-through[run as filter on directory tree]'
'--help[show help text]' '--version[show version information]')
else
@@ -23,13 +23,13 @@ else
"--format=:format type:$fmts"
'--message=:message at end of volume:'
'--null' '--reset-access-time'
- '--verbose' '--dot' '--append'
+ '--verbose' '--dot' '--append'
'--block-size=:block size in 512 byte units:'
'--dereference'
'--io-size=:block size in bytes'
'--quiet' '--force-local' '--help' '--version')
fi
- args=($args
+ args+=(
'-A[append files to archive]'
'-B[block size 5120 bytes with special file]'
'-C[set block size per record]:block size in bytes:(8192)'
@@ -44,10 +44,10 @@ else
if [[ $ig = gnu ]]; then
args=('--file=:archive file:->afile'
"--format=:format type:$fmts"
- '--make-directories' '--nonmatching'
+ '--make-directories' '--nonmatching'
'--preserve-modification-time' '--numeric'
'--rename' '--list' '--swap-bytes' '--swap-halfwords'
- '--dot' '--unconditional' '--verbose'
+ '--dot' '--unconditional' '--verbose'
'--block-size=:block size in 512 byte units:'
'--swap-halfwords'
'--io-size=:block size in bytes:'
@@ -58,7 +58,7 @@ else
'--no-absolute-filenames' '--sparse' '--only-verify-crc'
'--quiet' '--help' '--version')
fi
- args=($args
+ args+=(
'-b[reverse bytes in word]'
'-B[block size 5120 bytes with special file]'
'-d[create directories as needed]'
@@ -87,7 +87,7 @@ else
'--owner=:user (and group) for files:->user'
'--no-preserve-owner' '--sparse' '--help' '--version')
fi
- args=($args
+ args+=(
'-d[create directories as needed]'
'-l[link files instead of copying]'
'-L[follow symbolic links]'
@@ -98,12 +98,11 @@ else
else
return 1
fi
- args=($args
+ args+=(
'-a[reset access time of input files]'
)
-fi
+fi
-ret=1
_arguments -C -s "$args[@]" && ret=0
if [[ $state = afile ]]; then
@@ -121,12 +120,12 @@ if [[ $state = afile ]]; then
fi
elif [[ $state = user ]]; then
if compset -P '*[:.]'; then
- _groups
+ _groups && ret=0
else
local suf=.
[[ $OSTYPE = (solaris|hpux)* ]] && suf=:
compset -S '.*' && unset suf
- _users -S "$suf" -q
+ _users -S "$suf" -q && ret=0
fi
fi
diff --git a/Completion/Unix/Command/_cut b/Completion/Unix/Command/_cut
index 1024c20a7..caf8f32b7 100644
--- a/Completion/Unix/Command/_cut
+++ b/Completion/Unix/Command/_cut
@@ -2,44 +2,41 @@
typeset -A _cut_args
-if _pick_variant gnu="Free Soft" unix --version; then
- case $LANG in
- (de_DE.UTF-8)
- _cut_args=(
- bytes "nur diese Bytes ausgeben"
- characters "nur diese Zeichen ausgeben"
- delimiter "Delimiter anstelle von Tabulator als Trenner benutzen"
- fields "nur diese Felder und alle Zeilen OHNE Trennzeichen ausgeben"
- n "(ignoriert)"
- complement $'das Komplement der Menge der gew\u00e4hlten Bytes, Zeichen oder Felder bilden'
- only-delimited "keine Zeilen ausgeben, die keinen Trenner enthalten"
- output-delimiter "Zeichenkette als Ausgabetrennzeichen benutzen"
- help "diese Hilfe anzeigen und beenden"
- version "Versionsinformation anzeigen und beenden"
- )
- ;;
- (*)
- _cut_args=(
- bytes "select only these bytes"
- characters "select only these characters"
- delimiter "use DELIM instead of TAB for field delimiter"
- fields "select only these fields and lines without the delimiter character"
- n "(ignored)"
- complement "complement the set of selected bytes, characters or fields"
- only-delimited "do not print lines not containing delimiters"
- output-delimiter "use STRING as the output delimiter"
- help "display this help and exit"
- version "output version information and exit"
- )
- ;;
- esac
+case $LANG in
+ (de_DE.UTF-8)
+ _cut_args=(
+ bytes "nur diese Bytes ausgeben"
+ characters "nur diese Zeichen ausgeben"
+ delimiter "Delimiter anstelle von Tabulator als Trenner benutzen"
+ fields "nur diese Felder und alle Zeilen OHNE Trennzeichen ausgeben"
+ complement $'das Komplement der Menge der gew\u00e4hlten Bytes, Zeichen oder Felder bilden'
+ only-delimited "keine Zeilen ausgeben, die keinen Trenner enthalten"
+ output-delimiter "Zeichenkette als Ausgabetrennzeichen benutzen"
+ help "diese Hilfe anzeigen und beenden"
+ version "Versionsinformation anzeigen und beenden"
+ )
+ ;;
+ (*)
+ _cut_args=(
+ bytes "select only specified bytes"
+ characters "select only specified characters"
+ delimiter "use alternate field delimiter"
+ fields "select only specified fields"
+ complement "negate the set of selected bytes, characters or fields"
+ only-delimited "suppress lines with no delimiters"
+ output-delimiter "use specified string as the output delimiter"
+ help "display help information"
+ version "output version information"
+ )
+ ;;
+esac
+if _pick_variant gnu="Free Soft" unix --version; then
_arguments \
'(--bytes -b)'{--bytes=,-b+}'['$_cut_args[bytes]']:list' \
'(--characters -c)'{--characters=,-c+}'['$_cut_args[characters]']:list' \
'(--delimiter -d)'{--delimiter=,-d+}'['$_cut_args[delimiter]']:delimiter' \
'(--fields -f)'{--fields=,-f+}'['$_cut_args[fields]']:list' \
- '-n['$_cut_args[n]']' \
'--complement['$_cut_args[complement]']' \
'(--only-delimited -s)'{--only-delimited,-s}'['$_cut_args[only-delimited]']' \
'--output-delimiter=['$_cut_args[output-delimiter]']:delimiter' \
@@ -47,12 +44,15 @@ if _pick_variant gnu="Free Soft" unix --version; then
'(- *)--version['$_cut_args[version]']' \
'*:file:_files'
else
- _arguments \
- '-b[list specifies byte positions]:list:' \
- '-c[list specifies character positions]:list:' \
- '-d[use alternate delimiter]:delimiter' \
- '-f[list specifies fields]:list:' \
- '-n[do not split multi-byte characters]' \
- '-s[suppress lines with no delimiters]' \
+ case $OSTYPE in
+ freebsd*|dragonfly*) args+=( '(-d)-w[use whitespace as the delimiter]' ) ;;
+ esac
+ _arguments $args \
+ "-b[${_cut_args[bytes]}]:list" \
+ "-c[${_cut_args[characters]}]:list" \
+ "(-w)-d[${_cut_args[delimiter]}]:delimiter" \
+ "-f[${_cut_args[fields]}]:list" \
+ "-n[do not split multi-byte characters]" \
+ "-s[${_cut_args[only-delimited]}]" \
'*:file:_files'
fi
diff --git a/Completion/Unix/Command/_cvs b/Completion/Unix/Command/_cvs
index 3c06e0481..31997ec09 100644
--- a/Completion/Unix/Command/_cvs
+++ b/Completion/Unix/Command/_cvs
@@ -704,15 +704,18 @@ _cvs_sub_modules() {
_cvs_run() {
local cvsroot="$1" dir="$2"
shift 2
- local d=/tmp/zsh-cvs-work-$$
- mkdir $d >&/dev/null
- cd $d
- mkdir CVS >&/dev/null
+ local d=${TMPPREFIX:-/tmp/zsh}-cvs-work-$$
+ rm -rf $d
+ mkdir $d &&
+ (
+ chmod 0700 $d &&
+ builtin cd -q $d &&
+ mkdir CVS >&/dev/null || return 1
print -r - "$cvsroot" > CVS/Root
print "$dir" > CVS/Repository
print D > CVS/Entries
CVS_IGNORE_REMOTE_ROOT= cvs "$@"
- cd $OLDPWD
+ )
rm -rf $d
}
diff --git a/Completion/Unix/Command/_date b/Completion/Unix/Command/_date
index 7b1d3a7ab..e596ac038 100644
--- a/Completion/Unix/Command/_date
+++ b/Completion/Unix/Command/_date
@@ -1,4 +1,4 @@
-#compdef date
+#compdef date gdate
local -a args
@@ -8,7 +8,7 @@ if _pick_variant gnu="Free Software Foundation" unix --version; then
'-f[output dates specified in file]:file:_files'
'-I-[iso-8601]:precision:(date hours minutes seconds)'
'-r[reference]:file:_files'
- '-R[rfc-2822]'
+ '-R[RFC2822 format]'
'-s[set]:time string'
'--rfc-3339=-[output date and time in RFC 3339 format]:output type:(date seconds ns)'
--
@@ -20,26 +20,23 @@ else
solaris*)
args=( '-a:adjustment' )
;;
- freebsd*|darwin*)
+ freebsd*|darwin*|dragonfly*|netbsd*|openbsd*)
args=(
'-n[only set time on current machine]'
'-d:daylight saving time value'
'-j[do not try to set date]'
- '-f:parsing format'
'-r:seconds since epoch'
'-t:minutes west of GMT'
- '-v:adjustment value'
)
+ ;|
+ freebsd*) args+=( '-R[RFC2822 format]' ) ;|
+ freebsd*|dragonfly*|darwin*)
+ args+=( '-f:parsing format' '-v:adjustment value' )
;;
openbsd*)
- args=(
- '-n[only set time on current machine]'
- '-d:daylight saving time value'
- '-a[gradually skew]'
- '-r:seconds since epoch'
- '-t:minutes west of GMT'
- )
- ;;
+ args+=( '-z[specify timezone for output]:time zone:_time_zone')
+ ;|
+ openbsd*|netbsd*) args=( '-a[gradually skew]' ) ;;
esac
fi
diff --git a/Completion/Unix/Command/_df b/Completion/Unix/Command/_df
index 892f91fa0..a98180a2c 100644
--- a/Completion/Unix/Command/_df
+++ b/Completion/Unix/Command/_df
@@ -1,6 +1,6 @@
#compdef df
-local context state state_descr line args spec
+local curcontext="$curcontext" state state_descr line args spec ret=1
local -A opt_args
if _pick_variant gnu=GNU unix --version; then
@@ -34,6 +34,7 @@ elif [[ "$OSTYPE" == (darwin|freebsd|dragonfly)* ]]; then
'(-b -g -H -h -k -m)-m[use 1024*1024-byte blocks]'
'-P[POSIX compliant output]'
'-a[show all mount points]'
+ '-c[display a grand total]'
'-i[include inode usage statistics (default)]'
'-l[only display locally-mounted file systems]'
'-n[use previously obtained statistics]'
@@ -44,7 +45,7 @@ elif [[ "$OSTYPE" == (darwin|freebsd|dragonfly)* ]]; then
(darwin*)
args+=(
"-T+$spec"
-# '-t[same as -T (obsolete)]:file system type:->fslist'
+ "!-t+$spec" # obsolete
)
;;
(freebsd*|dragonfly*)
@@ -61,19 +62,15 @@ else
)
fi
-_arguments -s -S : $args && return 0
+_arguments -C -s -S : $args && ret=0
case "$state" in
(fslist)
- local -a fsys used pre disp expl
- _file_systems -U -O fsys
- pre=$IPREFIX
- # offer 'no' only if at the beginning of the list
- if ! compset -P '*,' && ! compset -P 'no'; then
- disp=( 'no -- exclude file system types in the list' )
- _wanted list-prefix expl 'prefix to list' compadd -d disp 'no'
- fi
- used=( ${(s:,:)${${IPREFIX#$pre}#no}} )
- _wanted fsys-types expl "$state_descr" compadd -qS , -F used -a fsys
+ [[ ! -prefix *, ]] && ! compset -P 'no' &&
+ _describe -t list-prefixes 'prefix to list' \
+ '( no:exclude\ file\ system\ types\ in\ the\ list )' && ret=0
+ _sequence -s , _file_systems && ret=0
;;
esac
+
+return ret
diff --git a/Completion/Unix/Command/_django b/Completion/Unix/Command/_django
index ac20409eb..029687696 100644
--- a/Completion/Unix/Command/_django
+++ b/Completion/Unix/Command/_django
@@ -1,26 +1,23 @@
#compdef django-admin.py django-admin manage.py
-local ret=1 state
+local curcontext="$curcontext" state line expl ret=1
-if [ "$service" = "manage.py" ] && [ ! -x ./manage.py ]; then
- return 0
+if [[ "$service" = "manage.py" && ! -x ./manage.py ]]; then
+ _default
+ return
fi
declare -ga common_args
common_args=(
'--help[display help information]'
'--version[display version information]'
- '--pythonpath=[directory to add to the Python path]:directory:_directories'
- '--settings=[Python path to settings module]:settings'
+ '--pythonpath=[directory to add to the Python path]:directory:_directories -W / -P /'
+ '--settings=[python path to settings module]:settings'
'--traceback[print traceback on exception]'
)
-_directories () {
- _wanted directories expl directory _path_files -/ "$@" -
-}
-
typeset -A opt_args
-_arguments \
+_arguments -C \
$common_args \
':subcommand:->subcommand' \
'*::options:->options' && ret=0
@@ -66,7 +63,7 @@ case $state in
subcommands+=($cmd)
fi
done
-
+
_describe -t subcommands 'django admin subcommand' subcommands && ret=0
;;
@@ -101,8 +98,8 @@ case $state in
settings="${DJANGO_SETTINGS_MODULE}"
else
return 0
- fi
-
+ fi
+
_wanted appname expl appname compadd - $(command \
sed -n "/INSTALLED_APPS\s*=\s*(/,/)/p" ${settings} | \
sed -n "s/^\s*'\(.*\.\)*\(.*\)'.*$/\2 /pg")
@@ -205,7 +202,7 @@ case $state in
;;
esac
- _arguments $args && ret=0
+ _arguments -C $args && ret=0
;;
esac
diff --git a/Completion/Unix/Command/_du b/Completion/Unix/Command/_du
index 9ae6e9cb3..d8871cd8d 100644
--- a/Completion/Unix/Command/_du
+++ b/Completion/Unix/Command/_du
@@ -1,7 +1,7 @@
-#compdef du
+#compdef du gdu
if _pick_variant gnu=Free\ Soft unix --version /dummy/no-such-file; then
- local ret=1
+ local context state line expl ret=1
_arguments -s \
'(-a --all -s --summarize)'{-a,--all}'[write counts for all files]' \
@@ -18,68 +18,61 @@ if _pick_variant gnu=Free\ Soft unix --version /dummy/no-such-file; then
'(-l --count-links)'{-l,--count-links}'[count sizes many times if hard linked]' \
'(-L --dereference -H -D --dereference-args -P --no-dereference)'{-L,--dereference}'[dereference all symlinks]' \
'(-S --separate-dirs)'{-S,--separate-dirs}'[do not include size of subdirectories]' \
- '(-s --summarize --max-depth -a --all)'{-s,--summarize}'[only display total for each argument]' \
+ '(-s --summarize --max-depth -a --all)'{-s,--summarize}'[only report total for each argument]' \
'(-x --one-file-system)'{-x,--one-file-system}'[skip directories on different filesystems]' \
'(-0 --null)'{-0,--null}'[end each output line with NUL instead of newline]' \
\*{-X+,--exclude-from=}'[exclude files matching any pattern in file]:file:_files' \
'*--exclude=[exclude files matching pattern]:pattern' \
'(-s --summarize)--max-depth=[maximum levels to recurse]:levels' \
- '--files0-from=[use NUL-terminated list of files from file]:file' \
+ '--files0-from=[use NUL-terminated list of files from file]:file:_files' \
'--time-style=[show times using given style, +FORMAT for strftime formatted args]:style:->timestyle' \
- '--time=-[show time of last modification of any file in the directory]:property:->time' \
+ '--time=-[show time of last modification of any file in the directory]:property:(atime access use ctime status)' \
+ '(-t --threshold)'{-t+,--threshold=}'[report only entries for which size exceeds threshold]:threshold' \
'(* -)--help[display help information]' \
'(* -)--version[display version information]' \
'*:file:_files' && ret=0
case $state in
- (time)
- local -a property
- property=(atime access use ctime status)
- _wanted property expl property compadd -a property && ret=0
- ;;
(timestyle)
local -a style desc
style=(full-iso long-iso iso +)
desc=('full-iso' 'long-iso' 'iso' '+FORMAT like `date'\''')
- _wanted -V style expl style compadd -d desc -a style && ret=0
- ;;
+ _wanted -C $context -V style expl style compadd -d desc -a style && ret=0
+ ;;
esac
return ret
-elif [[ "$OSTYPE" == darwin* ]]; then
- _arguments -s -A "-*" \
- '(-H -L -P)-H[follow symlinks on the command line]' \
- '(-H -L -P)-L[follow all symlinks]' \
- '(-H -L -P)-P[do not follow symlinks (default)]' \
- '*-I+[ignore files/directories matching specified mask]:mask' \
- '(-a -s -d)-a[display entry also for files (not just directories) in file hierarchy]' \
- '(-a -s -d)-d+[display entry for directories up to specified depth]:depth' \
- '(-a -s -d)-s[display entry only for files/directories specified on the command line]' \
- '(-h -k -m -g)-h[human readable output]' \
- '(-h -k -m -g)-k[use block size of 1K-byte]' \
- '(-h -k -m -g)-m[use block size of 1M-byte]' \
- '(-h -k -m -g)-g[use block size of 1G-byte]' \
- '-c[display grand total]' \
- '-r[notify about unreadable files/directories]' \
- '-x[exclude directories on different file systems]' \
- '*:file:_files'
-
else
- # based on $OSTYPE = solaris2.8
+ local pattern arg args
+ args=(
+ '(-a -s -d)-a[report sizes for all files, not just directories]'
+ '(-H -L -P)-L[follow all symlinks]'
+ '(-a -s -d)-s[only report total for each argument]'
+ '(-h -m -g -B)-k[use block size of 1K-byte]'
+ '-r[notify about unreadable files/directories]'
+ )
local xdev='[skip directories on different filesystems]'
- if [[ ${commands[$words[1]]:-$words[1]} = *xpg4* ]]; then
- args=( -x$xdev )
- else
- args=( -d$xdev
- '-L[dereference symlinks]'
- "(-a)-o[do not add child directories' usage to parent's total]"
- )
- fi
- _arguments -s "$args[@]" \
- '(-s -o)-a[write counts for all files]' \
- '-k[use block size of 1k]' \
- '-r[notify about unreadable files/directories]' \
- '(-a)-s[only display total for each argument]' \
- '*:file:_files'
+ for pattern arg in \
+ 'freebsd*' '-A[apparent size instead of usage]' \
+ '(darwin*|*bsd*|dragonfly*|solaris2.<10->)' '(-H -L -P)-H[follow symlinks on the command line]' \
+ '(darwin|*bsd|dragonfly)*' '(-H -L -P)-P[do not follow symlinks (default)]' \
+ '(darwin|dragonfly|freebsd)*' '*-I+[ignore files/directories matching specified mask]:mask' \
+ '(darwin|*bsd|dragonfly)*' '(-a -s -d)-d+[display entry for directories up to specified depth]:depth' \
+ '(darwin*|*bsd*|dragonfly*|solaris2.<10->)' '(-k -m -g -B)-h[human readable output]' \
+ 'netbsd*' '-i[output inode usage instead of blocks]' \
+ '(darwin*|freebsd*|netbsd*|solaris2.<11->)' '(-h -k -g -B)-m[use block size of 1M-byte]' \
+ '(darwin|freebsd<8->.|netbsd)*' '(-h -k -m -B)-g[use block size of 1G-byte]' \
+ 'freebsd*' '(-h -k -m -g)-B[block size]:block size (bytes)' \
+ '(darwin|*bsd|dragonfly)*' '-c[display grand total]' \
+ 'freebsd*' '-l[count sizes many times if hard linked]' \
+ '(freebsd|netbsd)*' '-n[ignore files and directories with nodump flag set]' \
+ 'solaris*' "(-a)-o[don't add child directories' usage to parent's total]" \
+ 'freebsd<8->.*' '-t+[report only entries for which size exceeds threshold]:threshold' \
+ 'solaris*' "-d$xdev" \
+ '(darwin|*bsd|dragonfly|solaris)*' "-x$xdev"
+ do
+ [[ $OSTYPE = $~pattern ]] && args+=( $arg )
+ done
+ _arguments -s -A "-*" $args
fi
diff --git a/Completion/Unix/Command/_ecasound b/Completion/Unix/Command/_ecasound
index e31b072f9..7ad08d0e1 100644
--- a/Completion/Unix/Command/_ecasound
+++ b/Completion/Unix/Command/_ecasound
@@ -1,9 +1,9 @@
#compdef ecasound
-local curcontext="$curcontext" state line expl
+local curcontext="$curcontext" state line expl ret=1
typeset -A opt_args
-_arguments \
+_arguments -C \
'-c[start in interactive mode]' \
'(-q)-d\:-[debug level]:debug level' \
'-D[print all debug information to stderr]' \
@@ -53,7 +53,7 @@ _arguments \
'*-eli\:-[LADSPA Plugin]: :->el' \
'*-gc\:-[time crop gate]: :->gc' \
'*-ge\:-[threshold gate]: :->ge' \
- && return 0
+ ':input source:->io' && ret=0
case $state in
filters)
@@ -82,12 +82,12 @@ case $state in
'r[reverb effect]: :->etr'
;;
emod)
- _values -S : 'envelopme modulation' \
+ _values -S : 'envelope modulation' \
'b[pulse gate]: :->eemb' \
'p[pulse gate (hz)]: :->eemp' \
't[tremolo effect]: :->eemt'
;;
-esac
+esac && ret=0
case $state in
b)
@@ -173,12 +173,12 @@ case $state in
typeset -A msgs
local str
msgs=(
- eac 'amplification value (percent):channel'
- eaw 'amplification value (percent):channel:max-clipped-samples'
- ec 'compression rate (decibels):threshold (0.0-1.0)'
- eca 'peak-level:release-time (seconds):fast compression rate (0.0-1.0):compression rate'
- enm 'threshold-level:pre-hold-time (msec):attack-time (msec):post-hold-time (msec):release-time (msec)'
- ezx 'left DC fix value:right CD fix value'
+ eac 'amplification value (percent):channel'
+ eaw 'amplification value (percent):channel:max-clipped-samples'
+ ec 'compression rate (decibels):threshold (0.0-1.0)'
+ eca 'peak-level:release-time (seconds):fast compression rate (0.0-1.0):compression rate'
+ enm 'threshold-level:pre-hold-time (msec):attack-time (msec):post-hold-time (msec):release-time (msec)'
+ ezx 'left DC fix value:right CD fix value'
eemb 'pulse frequency (beats per minute):on time (msec)'
eemp 'pulse frequency (hz):on time (percent)'
eemt 'tremolo speed (beats per second):depth (percent)'
@@ -206,5 +206,7 @@ case $state in
str="${str#*:}"
done
_message "${str%%:*}"
- ;;
-esac
+ ;;
+esac && ret=0
+
+return ret
diff --git a/Completion/Unix/Command/_elfdump b/Completion/Unix/Command/_elfdump
new file mode 100644
index 000000000..ee92402d2
--- /dev/null
+++ b/Completion/Unix/Command/_elfdump
@@ -0,0 +1,47 @@
+#compdef elfdump
+
+local -a args
+
+_elf_file() {
+ [[ -x $REPLY || $REPLY = (core*|*.([ao]|so|elf)) ]]
+}
+
+args=(
+ '-c[dump section header information]'
+ '-d[dump .dynamic section]'
+ '-e[dump file header]'
+ '-G[dump .got (global offset table) section]'
+ '-h[dump .hash section]'
+ '-i[dump .interp (interpreter) section]'
+ '-n[dump .note sections]'
+ '(-w)-p[dump program headers]'
+ '-r[dump relocation sections]'
+ '-s[dump symbol table sections]'
+ '(-p)-w[write contents of matched sections to file]:file:_files'
+)
+
+case $OSTYPE in
+ solaris*)
+ args+=(
+ '-g[dump .group section]'
+ '-H[dump .SUNW_cap (capabilities) section]'
+ '-m[dump .SUNW_move section]'
+ '-S[dump symbol table sections sorted according to symbol sort sections]'
+ '-u[dump stack unwind/exceptions sections]'
+ '-v[dump .SUNW_version (versioning) sections]'
+ '-y[dump .SUNW_syminfo (symbol bindings) section]'
+ '-I[match sections by index]:index or range'
+ "-N[match sections by name]:section"
+ '-T[match sections by type]:type'
+ '-C[demangle C++ symbol names]'
+ '-k[calculate ELF checksum]'
+ '-l[show long section names without truncation]'
+ '-O[specify osabi to apply]:osabi'
+ '-P[use alternative section header]'
+ "*:elf file:_files -g '*(-.e:_elf_file:)'"
+ )
+ ;;
+ freebsd*) args+=( '-a[dump all information]' ) ;;
+esac
+
+_arguments -s $args
diff --git a/Completion/Unix/Command/_ffmpeg b/Completion/Unix/Command/_ffmpeg
index 6a4ba234d..d68a094d4 100644
--- a/Completion/Unix/Command/_ffmpeg
+++ b/Completion/Unix/Command/_ffmpeg
@@ -1,6 +1,6 @@
#compdef ffmpeg
-local context state line expl
+local curcontext="$curcontext" state line expl
typeset -A opt_args
(( $+functions[_ffmpeg_presets] )) || _ffmpeg_presets() {
@@ -33,14 +33,10 @@ typeset -A opt_args
_wanted ffmpeg-formats expl 'force format' compadd -a formats
}
-(( $+functions[_ffmpeg_list_pix_fmts] )) || _ffmpeg_list_pix_fmts() {
- echo - ${${${(M)${(f)"$(_call_program formats $words[1] -pix_fmts 2>/dev/null)"}:#[I.][O.][H.][P.][B.] [^=[:space:]]*}#* }%% *}
-}
-
(( $+functions[_ffmpeg_pix_fmts] )) || _ffmpeg_pix_fmts() {
local pix_fmts
- pix_fmts=($(_ffmpeg_list_pix_fmts))
- _wanted ffmpeg-pix-fmts expl 'set pixel format' compadd -a pix_fmts
+ _wanted ffmpeg-pix-fmts expl 'pixel format' compadd "$@" - \
+ ${${${(M)${(f)"$(_call_program formats $words[1] -pix_fmts 2>/dev/null)"}:#[I.][O.][H.][P.][B.] [^=[:space:]]*}#* }%% *}
}
(( $+functions[_ffmpeg_bsfs] )) || _ffmpeg_bsfs() {
@@ -71,10 +67,10 @@ typeset -A _ffmpeg_flags
local match mbegin mend
integer ret=1
- if [[ $PREFIX = (#b)(*)[-+]([^-+]#) ]]; then
+ if [[ $PREFIX = (#b)(*)[-+]([^-+]#) ]]; then
if [[ -n ${flag_options[(R)$match[2]]} ]]; then
_ffmpeg_new_flag_options && ret=0
- fi
+ fi
if [[ -n ${flag_options[(R)$match[2]?*]} ]]; then
_ffmpeg_more_flag_options ${#match[1]} && ret=0
fi
@@ -82,7 +78,7 @@ typeset -A _ffmpeg_flags
_ffmpeg_flag_options && ret=0
fi
- return $ret
+ return ret
}
(( $+functions[_ffmpeg_register_lastopt_values] )) || _ffmpeg_register_lastopt_values() {
@@ -150,7 +146,7 @@ local -a _ffmpeg_argspecs
elif [[ $lastopt == -pix_fmt ]]; then
lastopt_takesargs=0
lastopt="*$lastopt"
- lastopt+=": :_ffmpeg_pix_fmts"
+ lastopt+=":set pixel format:_ffmpeg_pix_fmts"
elif [[ $example == bitstream_filter ]]; then
lastopt_takesargs=0
lastopt+=": :_ffmpeg_bsfs"
@@ -175,17 +171,17 @@ local -a _ffmpeg_argspecs
[[ -n $lastopt ]] && _ffmpeg_register_lastopt_values
}
-_arguments -S \
+_arguments -C -S \
"${_ffmpeg_argspecs[@]}" \
'*:output file:_files' \
- && return 0
+ && return
[[ "$state" == "vfilters" ]] &&
_values -s , -S = 'video filters' \
'aspect:set aspect ratio (rational number X\:Y or decimal number):' \
'crop:crop input video (x\:y\:width\:height):' \
- 'format: :->format' \
- 'noformat: :->noformat' \
+ 'format: :_sequence -s : _ffmpeg_pix_fmts' \
+ 'noformat: :_sequence -s : _ffmpeg_pix_fmts' \
'null' \
'pad:add pads to the input image (width\:height\:x\:y\:color_string):' \
'pixelaspect:set pixel aspect ratio (rational number X\:Y or decimal number):' \
@@ -196,15 +192,9 @@ _arguments -S \
'buffer' \
'nullsrc' \
'nullsink' \
- && return 0
-
-[[ "$state" == "format" ]] &&
- _values -s : -S = 'convert input video to one of the specified pixel formats' $(_ffmpeg_list_pix_fmts) && return 0
-
-[[ "$state" == "noformat" ]] &&
- _values -s : -S = 'disable specified pixel formats by force' $(_ffmpeg_list_pix_fmts) && return 0
+ && return
[[ -n $state && -n $_ffmpeg_flags[$state] ]] &&
- _ffmpeg_flags $state && return 0
+ _ffmpeg_flags $state && return
return 1
diff --git a/Completion/Unix/Command/_find b/Completion/Unix/Command/_find
index 33767c080..8f80e36cf 100644
--- a/Completion/Unix/Command/_find
+++ b/Completion/Unix/Command/_find
@@ -1,82 +1,145 @@
-#compdef find
+#compdef find gfind
-_arguments \
- '(- *)-help' '(-)--help' \
- '(- *)-version' '(-)--version' \
+local variant args
+
+_pick_variant -r variant gnu=GNU $OSTYPE -version
+
+case $variant in
+ solaris*)
+ args+=(
+ '*-'{n,}'cpio:device:_files'
+ '*-local'
+ )
+ ;|
+ solaris*|darwin*)
+ args+=( '*-xattr' )
+ ;|
+ solaris2.<10->|freebsd*|darwin*)
+ args+=( '*-acl' )
+ ;|
+ solaris2.<11->|freebsd*|dragonfly*|darwin*|openbsd*|gnu)
+ args+=(
+ '*-amin:access time (minutes)'
+ '*-cmin:inode change time (minutes)'
+ '*-mmin:modification time (minutes)'
+ '*-iname:name pattern to match (case insensitive)'
+ '*-print0'
+ )
+ ;|
+ netbsd*|freebsd*|dragonfly*|darwin*|gnu)
+ args+=( '(-H -L)-P[never follow symlinks]' )
+ ;|
+ netbsd*|freebsd*|dragonfly*|openbsd*|darwin*|gnu)
+ args+=( '-d[depth first traversal]' )
+ ;|
+ darwin*|freebsd*|gnu)
+ args+=(
+ '*-Bmin:birth time (minutes)'
+ '*-Bnewer:file to compare (birth time):_files'
+ '*-Btime:birth time (hours)'
+ )
+ ;|
+ freebsd*|dragonfly*|darwin*|openbsd*|gnu)
+ args+=(
+ '*-anewer:file to compare (access time):_files'
+ '*-cnewer:file to compare (inode change time):_files'
+ '*-mnewer:file to compare (modification time):_files'
+ '*-maxdepth:maximum search depth'
+ '*-mindepth:minimum search depth'
+ '*-path:path pattern to search:'
+ )
+ ;|
+ freebsd*|dragonfly*|darwin*|gnu)
+ args+=(
+ '*-delete'
+ '*-empty'
+ '*-execdir:program: _command_names -e:*\;::program arguments: _normal'
+ '*-gid:numeric group ID'
+ '*-uid:numeric user ID'
+ '*-noleaf'
+ '*-lname:link pattern to search'
+ '*-ilname:link pattern to search (case insensitive)'
+ '*-ipath:path pattern to search (case insensitive)'
+ '*-regex:regular expression to search'
+ '*-iregex:regular expression to search (case insensitive)'
+ '*-wholename:full path pattern to search' \
+ '*-iwholename:full path pattern to search (case insensitive)'
+ '*-ignore_readdir_race'
+ '*-noignore_readdir_race'
+ '*-okdir:program: _command_names -e:*\;::program arguments: _normal'
+ '*-samefile:file to compare inode:_files' \
+ '*-true'
+ '*-false'
+ '*-and'
+ '*-or'
+ '*-not'
+ )
+ ;|
+ freebsd*|dragonfly*|gnu) args+=( '*-quit' ) ;|
+ netbsd*|freebsd*|dragonfly*|darwin*)
+ args+=(
+ '-E[use extended regular expressions with -regex/-iregex]'
+ '-X[warn if filename contains characters special to xargs]'
+ '-f[specify file hierarchy to traverse]:path:_directories'
+ '-s[traverse directories in sorted order]'
+ "-x[don't span filesystems]"
+ '*-flags:flags:_chflags'
+ )
+ ;|
+ freebsd*|dragonfly*) args+=( '*-sparse' ) ;|
+ darwin*) args+=( '*-xattrname:name' ) ;|
+ gnu)
+ args+=(
+ '(- *)-help' '(-)--help'
+ '(- *)-version' '(-)--version'
+ '-D[print diagnostics]:debug option:(help tree search stat rates opt exec)'
+ '-O+[enable query optimisation]:level:(1 2 3)'
+ '*-daystart'
+ '-regextype:regexp syntax:(emacs posix-awk posix-basic posix-egrep posix-extended)'
+ '*-warn'
+ '*-nowarn'
+ '*-xautofs'
+ '*-used:access after inode change (days)'
+ '*-executable'
+ '*-readable'
+ '*-writable'
+ '*-xtype:file type:((b\:block\ special\ file c\:character\ special\ file d\:directory p\:named\ pipe f\:normal\ file l\:symbolic\ link s\:socket))'
+ '*-fls:output file:_files'
+ '*-fprint:output file:_files'
+ '*-fprint0:output file:_files'
+ '*-fprintf:output file:_files:output format'
+ '*-printf:output format'
+ )
+ [[ $OSTYPE = linux-gnu ]] && args+=( '*-context:SELinux context' )
+ ;;
+esac
+
+_arguments $args \
'(-L -P)-H[only follow symlinks when resolving command-line arguments]' \
'(-H -P)-L[follow symlinks]' \
- '(-H -L)-P[never follow symlinks]' \
- '-D[print diagnostics]:deb option:(help tree search stat rates opt exec)' \
- '-O+[enable query optimisation]:level:(1 2 3)' \
- '*-daystart' \
- '*-d' '*-depth' \
+ '*-atime:access time (days)' \
+ '*-ctime:inode change time (days)' \
+ '*-depth' \
+ '*-exec:program: _command_names -e:*\;::program arguments: _normal' \
'*-follow' \
- '(-noignore_readdir_race)-ignore_readdir_race' \
- '*-maxdepth:maximum search depth' \
- '*-mindepth:minimum search depth' \
- '*-mount' \
- '(-ignore_readdir_race)-noignore_readdir_race' \
- '*-noleaf' \
- '-regextype:regexp syntax:(emacs posix-awk posix-basic posix-egrep posix-extended)' \
- '*-warn' \
- '*-nowarn' \
- '*-xdev' \
- '*-amin:access time (minutes):' \
- '*-cmin:inode change time (minutes):' \
- '*-mmin:modification time (minutes):' \
- '*-atime:access time (days):' \
- '*-ctime:inode change time (days):' \
- '*-mtime:modification time (days):' \
- '*-anewer:file to compare (access time):_files' \
- '*-cnewer:file to compare (inode change time):_files' \
- '*-newer:file to compare (modification time):_files' \
- '*-used:access after inode change (days):' \
- '*-empty' \
- '*-executable' \
- '*-false' \
'*-fstype:file system type:_file_systems' \
- '*-gid:numeric group ID:' \
'*-group:group:_groups' \
- '*-uid:numeric user ID:' \
- '*-user:user:_users' \
- '*-lname:link pattern to search:' \
- '*-ilname:link pattern to search (case insensitive):' \
- '*-name:name pattern to search:' \
- '*-iname:name pattern to search (case insensitive):' \
- '*-path:path pattern to search:' \
- '*-ipath:path pattern to search (case insensitive):' \
- '*-regex:regular expression to search:' \
- '*-iregex:regular expression to search (case insensitive):' \
- '*-wholename:full path pattern to search:' \
- '*-iwholename:full path pattern to search (case insensitive):' \
'*-inum:inode number:' \
'*-links:number of links:' \
- '*-nouser' \
+ '*-ls' \
+ '*-mount' \
+ '*-mtime:modification time (days)' \
+ '*-name:name pattern' \
+ '*-newer:file to compare (modification time):_files' \
'*-nogroup' \
- '*-perm:file permission bits:' \
- '*-readable' \
- '*-writable' \
- '*-size:file size:' \
- '*-samefile:same inode as:_files' \
- '*-true' \
- '*-type:file type:((b\:block\ special\ file c\:character\ special\ file d\:directory p\:named\ pipe f\:normal\ file l\:symbolic\ link s\:socket))' \
- '*-xtype:file type:((b\:block\ special\ file c\:character\ special\ file d\:directory p\:named\ pipe f\:normal\ file l\:symbolic\ link s\:socket))' \
- '*-delete' \
- '*-exec:program: _command_names -e:*\;::program arguments: _normal' \
- '*-execdir:program: _command_names -e:*\;::program arguments: _normal' \
+ '*-nouser' \
'*-ok:program: _command_names -e:*\;::program arguments: _normal' \
- '*-okdir:program: _command_names -e:*\;::program arguments: _normal' \
- '*-fls:output file:_files' \
- '*-fprint:output file:_files' \
- '*-fprint0:output file:_files' \
- '*-fprintf:output file:_files:output format:' \
+ '*-perm:file permission bits' \
'*-print' \
- '*-print0' \
- '*-printf:output format:' \
'*-prune' \
- '*-quit' \
- '*-ls' \
- '*-and' '*-a' \
- '*-or' '*-o' \
- '*-not' \
+ '*-size:file size (blocks)' \
+ '*-type:file type:((b\:block\ special\ file c\:character\ special\ file d\:directory p\:named\ pipe f\:normal\ file l\:symbolic\ link s\:socket))' \
+ '*-user:user:_users' \
+ '*-xdev' \
+ '*-a' '*-o' \
'*:directory:_files -/'
diff --git a/Completion/Unix/Command/_fuser b/Completion/Unix/Command/_fuser
index ba0f301ea..f497729fc 100644
--- a/Completion/Unix/Command/_fuser
+++ b/Completion/Unix/Command/_fuser
@@ -1,10 +1,18 @@
#compdef fuser
-local -a args arg1
+local -a args argf variant
typeset -A opt_args
-if _pick_variant -c $words[1] psmisc='(#i)psmisc' unix -V; then
+args=(
+ '-u[append the user name of the process owner to each PID]'
+ '(-f)-c[list all processes accessing files on the filesystem specified by name]'
+ '(-c)-f[list all processes accessing named files]'
+)
+argf=( '*:file:_files' )
+_pick_variant -r variant psmisc='(#i)psmisc' $OSTYPE -V
+case $variant in
+ psmisc)
(( $+functions[_fuser_services] )) ||
_fuser_services() {
local expl suf ret=1
@@ -23,45 +31,51 @@ if _pick_variant -c $words[1] psmisc='(#i)psmisc' unix -V; then
compset -S ',*' || suf=( -S ${${opt_args[-n]/?*/,}:-/} -r "/, \t\n\-" )
_ports $suf && ret=0
fi
-
+
return ret
}
- _arguments \
- '(-s)-a[show all files specified on the command line]' \
- {-c,-m}'[list all processes accessing files on the filesystem specified by name]' \
- '-k[kill processes accessing the file]' \
- '-i[ask for confirmation before killing]' \
- '-l[list all known signal names]' \
- '-n[select name space]:namespace:(file udp tcp)' \
- '(-a)-s[silent operation]' \
- '-signal[send alternate signal with -k]:signal:_signals' \
- '-u[append the user name of the process owner to each PID]' \
- '-v[verbose mode]' \
- '-V[display version information]' \
- '-4[search only for IPv4 sockets]' \
- '-6[search only for IPv6 sockets]' \
- '*:name: _alternative "files:file:_files" "services:service:_fuser_services"'
-
-else
- case $OSTYPE in
- solaris2.9 )
- args=(
- '-n[list only processes with non-blocking mandatory locks]'
- '-s[send alternate signal with -k]:signal:_signals'
- )
- ;;
- sysv4 )
- (( $+words[(r)-k] )) && arg1=( ':name: _alternative signals\:signal\:_signals\ -p files:file:_files' )
- ;;
- esac
+ args+=(
+ '(-s)-a[show all files specified on the command line]' \
+ {-c,-m}'[list all processes accessing files on the filesystem specified by name]' \
+ '-k[kill processes accessing the file]' \
+ '-i[ask for confirmation before killing]' \
+ '(-)-l[list all known signal names]' \
+ '-n[select name space]:namespace:(file udp tcp)' \
+ '(-a -u -v)-s[silent operation]' \
+ '-v[verbose mode]' \
+ '-V[display version information]' \
+ '-4[search only for IPv4 sockets]' \
+ '-6[search only for IPv6 sockets]' \
+ )
+ argf=( '*:name: _alternative "files:file:_files" "services:service:_fuser_services"' )
+ [[ -prefix - && -z ${${words[1,CURRENT-1]}[(r)-[A-Z][A-Z]*]} ]] &&
+ argf[1]+=' "signal:signals:_signals -P-"'
+ ;;
+ freebsd*|openbsd*|solaris2.<9->)
+ args+=(
+ '-s[send alternate signal]:signal:_signals'
+ '-k[send SIGKILL to each process]'
+ )
+ ;|
+ openbsd*|freebsd*)
+ args+=(
+ '-M[extra values from specified core file]:core file:_files'
+ '-N[extract name list from specified system]:system'
+ )
+ ;|
+ freebsd*) args+=( '-m[include mapped files]' ) ;;
+ solaris2.<9->)
+ args+=(
+ '-n[list only processes with non-blocking mandatory locks]'
+ )
+ ;;
+ solaris2.<10->)
+ args+=( '-d[report device usage for all minor nodes bound to same device]' )
+ ;;
+ sysv4 )
+ (( $+words[(r)-k] )) && argf=( ':name: _alternative signals\:signal\:_signals\ -p files:file:_files' )
+ ;;
+esac
- _arguments \
- '(-f)-c[list all processes accessing files on the filesystem specified by name]' \
- '(-c)-f[list all processes accessing named files]' \
- '-k[kill processes accessing the file]' \
- '-u[append the user name of the process owner to each PID]' \
- $args \
- $arg1 \
- '*:file:_files'
-fi
+_arguments -s $args $argf
diff --git a/Completion/Unix/Command/_gcc b/Completion/Unix/Command/_gcc
index c6bbabbe9..2c5ffdc8a 100644
--- a/Completion/Unix/Command/_gcc
+++ b/Completion/Unix/Command/_gcc
@@ -1,4 +1,4 @@
-#compdef gcc g++ cc c++ llvm-gcc llvm-g++ clang clang++ -value-,LDFLAGS,-default- -value-,CFLAGS,-default- -value-,CPPFLAGS,-default-
+#compdef gcc g++ cc c++ llvm-gcc llvm-g++ clang clang++ -value-,LDFLAGS,-default- -value-,CFLAGS,-default- -value-,CXXFLAGS,-default- -value-,CPPFLAGS,-default-
local curcontext="$curcontext" state line ret=1 expl args args2 march
typeset -A opt_args
@@ -13,7 +13,7 @@ if [[ "$service" = -value-* ]]; then
args2=()
fi
else
- args2=( '*:input file:_files -g "*.([cCmisSoak]|cc|cxx|ii|k[ih])(-.)"' )
+ args2=( '*:input file:_files -g "*.([cCmisSoak]|cc|cpp|cxx|ii|k[ih])(-.)"' )
fi
args=()
diff --git a/Completion/Unix/Command/_gcore b/Completion/Unix/Command/_gcore
new file mode 100644
index 000000000..4933ffee6
--- /dev/null
+++ b/Completion/Unix/Command/_gcore
@@ -0,0 +1,50 @@
+#compdef gcore
+
+case $OSTYPE in
+ solaris*)
+ local -a content
+
+ content=(
+ 'anon[anonymous private mappings]'
+ 'ctf[CTF type information]'
+ 'data[writable private file mappings]'
+ 'dism[DISM mappings]'
+ 'heap[process heap]'
+ 'ism[ISM mappings]'
+ 'rodata[read-only private file mappings]'
+ 'shanon[anonymous shared mappings]'
+ 'shfile[file-backed shared mappings]'
+ 'shm[System V shared memory]'
+ 'stack[process stack]'
+ 'symtab[symbol table sections for loaded files]'
+ 'text[readable and executable private file mappings]'
+ )
+
+ _arguments -s \
+ '(-c -g)-p[use per-process core file repository]' \
+ '(-c -p)-g[use global core file repository]' \
+ '-F[force grabbing the target process]' \
+ '(-p -g)-c[set core file content]: :_values -s + "content" $content' \
+ '-o[set core file base name]:file base name:_files' \
+ '*:pid:_pids'
+ ;;
+ netbsd*)
+ _arguments \
+ '-c+[write core file to specified file]:file:_files' \
+ '*:pid:_pids'
+ ;;
+ freebsd*)
+ _arguments -s \
+ '-c+[write core file to specified file]:file:_files' \
+ '-f[dump all available segments]' \
+ '-s[stop process while gathering image]' \
+ '::executable:' \
+ ':pid:_pids'
+ ;;
+ *)
+ # GNU GDB gcore
+ _arguments \
+ '-o[set core file base name]:file base name:_files' \
+ ':pid:_pids'
+ ;;
+esac
diff --git a/Completion/Unix/Command/_getent b/Completion/Unix/Command/_getent
index 3ea148b71..b9aff6642 100755
--- a/Completion/Unix/Command/_getent
+++ b/Completion/Unix/Command/_getent
@@ -5,7 +5,7 @@ local services databases keys
local -a args
typeset -A opt_args
-if _pick_variant -r is_gnu gnu='(GNU|EGLIBC)' unix --version; then
+if _pick_variant -r is_gnu gnu='(GNU|EGLIBC|Gentoo)' unix --version; then
args+=(
'(- 1 *)'{-\?,--help}'[display help information]'
'(- 1 *)--usage[display a short usage message]'
diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git
index c4e386b15..979e3e76f 100644
--- a/Completion/Unix/Command/_git
+++ b/Completion/Unix/Command/_git
@@ -4,7 +4,7 @@
#
# Say you got your own git sub-commands (git will run a program `git-foo'
# when you run "git foo") and you want "git f<tab>" to complete that sub
-# commands name for you. You can make that sub-command know to the completion
+# commands name for you. You can make that sub-command known to the completion
# via the user-command style:
#
# % zstyle ':completion:*:*:git:*' user-commands foo:'description for foo'
@@ -20,17 +20,13 @@
# completion as well. Place such a function inside an autoloaded #compdef file
# and you should be all set. You can add a description to such a function by
# adding a line matching
-#
+#
# #description DESCRIPTION
#
# as the second line in the file. See
# Completion/Debian/Command/_git-buildpackage in the Zsh sources for an
# example.
#
-# As this solution is so much better than the user-commands zstyle method, the
-# zstyle method is now DEPRECATED. It will most likely be removed in the next
-# major release of Zsh (5.0).
-#
# When _git does not know a given sub-command (say `bar'), it falls back to
# completing file names for all arguments to that sub command. I.e.:
#
@@ -651,8 +647,8 @@ _git-commit () {
# TODO: --interactive isn't explicitly listed in the documentation.
_arguments -w -S -s \
'(-a --all --interactive -o --only -i --include *)'{-a,--all}'[stage all modified and deleted paths]' \
- '--fixup=[construct a commit message for use with rebase --autosquash]:' \
- '--squash=[construct a commit message for use with rebase --autosquash]:' \
+ '--fixup=[construct a commit message for use with rebase --autosquash]:commit to be amended:__git_recent_commits' \
+ '--squash=[construct a commit message for use with rebase --autosquash]:commit to be amended:__git_recent_commits' \
$reset_author_opt \
'( --porcelain --dry-run)--short[output dry run in short format]' \
'(--short --dry-run)--porcelain[output dry run in porcelain-ready format]' \
@@ -1339,13 +1335,13 @@ _git-rebase () {
'(-i --interactive --ignore-whitespace --whitespace --committer-date-is-author-date)'{-i,--interactive}'[make a list of commits to be rebased and open in $EDITOR]' \
'--edit-todo[edit interactive instruction sheet in an editor]' \
'(-p --preserve-merges --interactive)'{-p,--preserve-merges}'[try to recreate merges instead of ignoring them]' \
- {-x,--exec}'[with -i\: append "exec <cmd>" after each line]:command' \
+ {-x,--exec=}'[with -i\: append "exec <cmd>" after each line]:command:_command_names -e' \
'(1)--root[rebase all reachable commits]' \
$autosquash_opts \
'(--autostash --no-autostash)--autostash[stash uncommitted changes before rebasing and apply them afterwards]' \
'(--autostash --no-autostash)--no-autostash[do not stash uncommitted changes before rebasing and apply them afterwards]' \
'--no-ff[cherry-pick all rebased commits with --interactive, otherwise synonymous to --force-rebase]' \
- '--onto[start new branch with HEAD equal to given revision]:newbase:__git_revisions' \
+ '--onto=[start new branch with HEAD equal to given revision]:newbase:__git_revisions' \
':upstream branch:__git_revisions' \
'::working branch:__git_branch_names'
}
@@ -1523,6 +1519,7 @@ _git-stash () {
case $state in
(command)
local -a commands
+ local -a save_arguments
commands=(
save:'save your local modifications to a new stash'
@@ -1535,19 +1532,24 @@ _git-stash () {
drop:'remove a single stashed state from the stash list'
create:'create a stash without storing it in the ref namespace')
+ save_arguments=(
+ '(--keep-index)--patch[interactively select hunks from diff between HEAD and working tree to stash]' \
+ '( --no-keep-index)--keep-index[all changes already added to the index are left intact]' \
+ '(--keep-index )--no-keep-index[all changes already added to the index are undone]' \
+ '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
+ '(-u --include-untracked)'{-u,--include-untracked}'[include untracked files]' \
+ )
_describe -t commands command commands && ret=0
+ _arguments -S $save_arguments && ret=0 # "stash" defaults to "save", but without "message".
;;
(option-or-argument)
curcontext=${curcontext%:*}-$line[1]:
case $line[1] in
(save)
+ _arguments -S $save_arguments && ret=0
_arguments -S \
- '(--keep-index)--patch[interactively select hunks from diff between HEAD and working tree to stash]' \
- '( --no-keep-index)--keep-index[all changes already added to the index are left intact]' \
- '(--keep-index )--no-keep-index[all changes already added to the index are undone]' \
- '(-q --quiet)'{-q,--quiet}'[suppress all output]' \
- '(-u --include-untracked)'{-u,--include-untracked}'[include untracked files]' \
+ $save_arguments \
':: :_guard "([^-]?#|)" message' && ret=0
;;
(list)
@@ -3161,7 +3163,15 @@ _git-remote () {
'(-m --master)'{-m,--master=}'[set HEAD of remote to point to given master branch]: :__git_branch_names' \
'--mirror[do not use separate remotes]' \
':name:__git_remotes' \
- ':url:_urls' && ret=0
+ ':repository:->repository' && ret=0
+ case $state in
+ (repository)
+ _alternative \
+ 'local-repositories::__git_local_repositories' \
+ 'remote-repositories::__git_remote_repositories' \
+ 'urls::_urls' && ret=0
+ ;;
+ esac
;;
(rename)
_arguments \
@@ -3326,7 +3336,7 @@ _git-count-objects () {
_git-difftool () {
# TODO: Is this fine, or do we need to modify the context or similar?
_git-diff \
- '--dir-diff[diff a whole tree by prepare a temporary copy]' \
+ '(-d --dir-diff)'{-d,--dir-diff}'[diff a whole tree by preparing a temporary copy]' \
'(-y --no-prompt --prompt)'{-y,--no-prompt}'[do not prompt before invocation of diff tool]' \
'(-y --no-prompt)--prompt[prompt before invocation of diff tool]' \
'(-t --tool -x --extcmd)'{-t,--tool=-}'[merge resolution program to use]: :__git_difftools' \
@@ -3721,7 +3731,7 @@ _git-send-email () {
'(--format-patch )--no-format-patch[interpret ambiguous arguments file-name arguments]' \
'--quiet[be less verbose]' \
'( --no-validate)--validate[perform sanity checks on patches]' \
- '(--validate )--validate[do not perform sanity checks on patches]' \
+ '(--validate )--no-validate[do not perform sanity checks on patches]' \
'--force[send emails even if safety checks would prevent it]' \
'*: :_files'
}
@@ -5198,20 +5208,60 @@ _git_commands () {
integer ret=1
- # TODO: Is this the correct way of doing it? Should we be using _alternative
- # and separate functions for each set of commands instead?
- _describe -t aliases alias unique_aliases && ret=0
- _describe -t main-porcelain-commands 'main porcelain command' main_porcelain_commands && ret=0
- _describe -t user-commands 'user command' user_commands && ret=0
- _describe -t third-party-commands 'third-party command' third_party_commands && ret=0
- _describe -t ancillary-manipulator-commands 'ancillary manipulator command' ancillary_manipulator_commands && ret=0
- _describe -t ancillary-interrogator-commands 'ancillary interrogator command' ancillary_interrogator_commands && ret=0
- _describe -t interaction-commands 'interaction command' interaction_commands && ret=0
- _describe -t plumbing-manipulator-commands 'plumbing manipulator command' plumbing_manipulator_commands && ret=0
- _describe -t plumbing-interrogator-commands 'plumbing interrogator command' plumbing_interrogator_commands && ret=0
- _describe -t plumbing-sync-commands 'plumbing sync command' plumbing_sync_commands && ret=0
- _describe -t plumbing-sync-helper-commands 'plumbing sync helper command' plumbing_sync_helper_commands && ret=0
- _describe -t plumbing-internal-helper-commands 'plumbing internal helper command' plumbing_internal_helper_commands && ret=0
+ _tags \
+ aliases \
+ main-porcelain-commands \
+ user-commands \
+ third-party-commands \
+ ancillary-manipulator-commands \
+ ancillary-interrogator-commands \
+ interaction-commands \
+ plumbing-manipulator-commands \
+ plumbing-interrogator-commands \
+ plumbing-sync-commands \
+ plumbing-sync-helper-commands \
+ plumbing-internal-helper-commands
+
+ while _tags; do
+
+ _requested aliases && \
+ _describe -t aliases 'alias' unique_aliases && ret=0
+
+ _requested main-porcelain-commands && \
+ _describe -t main-porcelain-commands 'main porcelain command' main_porcelain_commands && ret=0
+
+ _requested user-commands && \
+ _describe -t user-commands 'user command' user_commands && ret=0
+
+ _requested third-party-commands && \
+ _describe -t third-party-commands 'third-party command' third_party_commands && ret=0
+
+ _requested ancillary-manipulator-commands && \
+ _describe -t ancillary-manipulator-commands 'ancillary manipulator command' ancillary_manipulator_commands && ret=0
+
+ _requested ancillary-interrogator-commands && \
+ _describe -t ancillary-interrogator-commands 'ancillary interrogator command' ancillary_interrogator_commands && ret=0
+
+ _requested interaction-commands && \
+ _describe -t interaction-commands 'interaction command' interaction_commands && ret=0
+
+ _requested plumbing-manipulator-commands && \
+ _describe -t plumbing-manipulator-commands 'plumbing manipulator command' plumbing_manipulator_commands && ret=0
+
+ _requested plumbing-interrogator-commands && \
+ _describe -t plumbing-interrogator-commands 'plumbing interrogator command' plumbing_interrogator_commands && ret=0
+
+ _requested plumbing-sync-commands && \
+ _describe -t plumbing-sync-commands 'plumbing sync command' plumbing_sync_commands && ret=0
+
+ _requested plumbing-sync-helper-commands && \
+ _describe -t plumbing-sync-helper-commands 'plumbing sync helper command' plumbing_sync_helper_commands && ret=0
+
+ _requested plumbing-internal-helper-commands && \
+ _describe -t plumbing-internal-helper-commands 'plumbing internal helper command' plumbing_internal_helper_commands && ret=0
+
+ (( ret )) || break
+ done
return ret
}
@@ -5262,12 +5312,10 @@ __git_gpg_secret_keys () {
(( $+functions[__git_merge_strategies] )) ||
__git_merge_strategies () {
local expl
- local -a merge_strategies
- merge_strategies=(${=${${(M)${(f)"$(_call_program merge-strategies "git merge -s '' 2>&1")"}:#[Aa]vailable (custom )#strategies are: *}#[Aa]vailable (custom )#strategies are: }%.})
- __git_command_successful $pipestatus || return 1
-
- _wanted merge-strategies expl 'merge strategy' compadd $* - $merge_strategies
+ _wanted merge-strategies expl 'merge strategy' compadd "$@" - \
+ ${=${${${(M)${(f)"$(_call_program merge-strategies \
+ "git merge -s '' 2>&1")"}:#[Aa]vailable (custom )#strategies are: *}#[Aa]vailable (custom )#strategies are: }%.}:-octopus ours recursive resolve subtree}
}
(( $+functions[__git_encodings] )) ||
@@ -5299,8 +5347,9 @@ __git_remotes () {
local remotes expl
remotes=(${(f)"$(_call_program remotes git remote 2>/dev/null)"})
+ __git_command_successful $pipestatus || return 1
- _wanted remotes expl remote compadd $* - $remotes
+ _wanted remotes expl remote compadd "$@" -a - remotes
}
(( $+functions[__git_ref_specs] )) ||
@@ -5431,13 +5480,7 @@ __git_reflog_entries () {
reflog_entries=(${${${(f)"$(_call_program reflog-entries git reflog 2>/dev/null)"}#* }%%:*})
__git_command_successful $pipestatus || return 1
- if compset -P '*@'; then
- reflog_entries=(${${(M)reflog_entries:#$IPREFIX*}#$IPREFIX})
- _wanted reflog-entries expl 'reflog entry' compadd $* - $reflog_entries
- else
- reflog_entries=(${reflog_entries%@*})
- _wanted reflog-entries expl 'reflog entry' compadd -qS @ $* - $reflog_entries
- fi
+ _wanted reflog-entries expl 'reflog entry' _multi_parts @ reflog_entries
}
(( $+functions[__git_ref_sort_keys] )) ||
@@ -5492,7 +5535,7 @@ __git_stashes () {
stashes=(${${(f)"$(_call_program stashes git stash list 2>/dev/null)"}/: */})
__git_command_successful $pipestatus || return 1
- _wanted stashes expl stash compadd $* - $stashes
+ _wanted stashes expl stash compadd "$@" -a - stashes
}
(( $+functions[__git_svn_revisions] )) ||
@@ -5531,7 +5574,7 @@ __git_branch_names () {
branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/})
__git_command_successful $pipestatus || return 1
- _wanted branch-names expl branch-name compadd $* - $branch_names
+ _wanted branch-names expl branch-name compadd "$@" -a - branch_names
}
(( $+functions[__git_remote_branch_names] )) ||
@@ -5542,7 +5585,7 @@ __git_remote_branch_names () {
branch_names=(${${(f)"$(_call_program remote-branch-refs git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}#refs/remotes/})
__git_command_successful $pipestatus || return 1
- _wanted remote-branch-names expl 'remote branch name' compadd $* - $branch_names
+ _wanted remote-branch-names expl 'remote branch name' compadd "$@" -a - branch_names
}
(( $+functions[__git_remote_branch_names_noprefix] )) ||
@@ -5553,7 +5596,7 @@ __git_remote_branch_names_noprefix () {
branch_names=(${${${(f)"$(_call_program remote-branch-refs-noprefix git for-each-ref --format='"%(refname)"' refs/remotes 2>/dev/null)"}##*/}:#HEAD})
__git_command_successful $pipestatus || return 1
- _wanted remote-branch-names-noprefix expl 'remote branch name' compadd $* - $branch_names
+ _wanted remote-branch-names-noprefix expl 'remote branch name' compadd "$@" -a - branch_names
}
(( $+functions[__git_commits] )) ||
@@ -5580,14 +5623,57 @@ __git_heads () {
for f in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do
[[ -f $gitdir/$f ]] && heads+=$f
done
+ [[ -f $gitdir/refs/stash ]] && heads+=stash
fi
- _wanted heads expl head compadd $* - $heads
+ _wanted heads expl head compadd "$@" -a - heads
}
(( $+functions[__git_commit_objects] )) ||
__git_commit_objects () {
- _guard '[[:xdigit:]](#c,40)' 'commit object name'
+ local gitdir expl start
+ declare -a commits
+
+ # Note: the after-the-colon part must be unique across the entire array;
+ # see workers/34768
+ : ${(A)commits::=${(f)"$(_call_program commits git --no-pager log -20 --format='%h:\\\[%h\\\]\ %s')"}}
+ __git_command_successful $pipestatus || return 1
+
+ _describe -V -t commits 'commit object name' commits || _guard '[[:xdigit:]](#c,40)' 'commit object name'
+}
+
+(( $+functions[__git_recent_commits] )) ||
+__git_recent_commits () {
+ local gitdir expl start
+ declare -a descr tags heads commits
+ local i j k
+
+ # Careful: most %d will expand to the empty string. Quote properly!
+ : "${(A)commits::=${(@f)"$(_call_program commits git --no-pager log -20 --format='%h%n%d%n%s')"}}"
+ __git_command_successful $pipestatus || return 1
+
+ for i j k in "$commits[@]" ; do
+ # Note: the after-the-colon part must be unique across the entire array;
+ # see workers/34768
+ descr+=("$i:[$i] $k")
+ j=${${j# \(}%\)} # strip leading ' (' and trailing ')'
+ for j in ${(s:, :)j}; do
+ if [[ $j == 'tag: '* ]] ; then
+ tags+=( ${j#tag: } )
+ else
+ heads+=( $j )
+ fi
+ done
+ done
+
+ ret=1
+ # Resetting expl to avoid it 'leaking' from one line to the next.
+ expl=()
+ _wanted commit-tags expl 'commit tag' compadd "$@" -a - tags && ret=0
+ expl=()
+ _wanted heads expl 'head' compadd "$@" -a - heads && ret=0
+ expl=()
+ _describe -2Vx -t commits 'commit object name' descr && ret=0
}
(( $+functions[__git_blob_objects] )) ||
@@ -5678,7 +5764,7 @@ __git_submodules () {
submodules=(${${${(f)"$(_call_program submodules git submodule 2>/dev/null)"}#?* }%% *})
__git_command_successful $pipestatus || return 1
- _wanted submodules expl submodule compadd $* - $submodules
+ _wanted submodules expl submodule compadd "$@" -a - submodules
}
# Tag Argument Types
@@ -5691,7 +5777,7 @@ __git_tags () {
tags=(${${(f)"$(_call_program tagrefs git for-each-ref --format='"%(refname)"' refs/tags 2>/dev/null)"}#refs/tags/})
__git_command_successful $pipestatus || return 1
- _wanted tags expl tag compadd $* - $tags
+ _wanted tags expl tag compadd "$@" -a - tags
}
(( $+functions[__git_commit_tags] )) ||
@@ -5714,7 +5800,7 @@ __git_tags_of_type () {
tags=(${${(M)${(f)"$(_call_program $type-tag-refs "git for-each-ref --format='%(*objecttype)%(objecttype) %(refname)' refs/tags 2>/dev/null")"}:#$type(tag|) *}#$type(tag|) refs/tags/})
__git_command_successful $pipestatus || return 1
- _wanted $type-tags expl "$type tag" compadd $* - $tags
+ _wanted $type-tags expl "$type tag" compadd "$@" -a - tags
}
# Reference Argument Types
@@ -5737,7 +5823,7 @@ __git_references () {
_git_refs_cache_pwd=$PWD
fi
- _wanted references expl 'references' compadd - $_git_refs_cache
+ _wanted references expl 'reference' compadd -a - _git_refs_cache
}
(( $+functions[__git_local_references] )) ||
@@ -5750,7 +5836,7 @@ __git_local_references () {
_git_local_refs_cache_pwd=$PWD
fi
- _wanted references expl 'references' compadd - $_git_local_refs_cache
+ _wanted references expl 'reference' compadd -a - _git_local_refs_cache
}
(( $+functions[__git_remote_references] )) ||
@@ -5766,7 +5852,7 @@ __git_notes_refs () {
notes_refs=(${${(f)"$(_call_program notes-refs git for-each-ref --format='"%(refname)"' refs/notes 2>/dev/null)"}#$type refs/notes/})
__git_command_successful $pipestatus || return 1
- _wanted notes-refs expl 'notes ref' compadd $* - $notes_refs
+ _wanted notes-refs expl 'notes ref' compadd "$@" -a - notes_refs
}
# File Argument Types
@@ -6406,7 +6492,6 @@ __git_config_values () {
# Git Config Sections and Types
(( $+functions[__git_browsers] )) ||
__git_browsers () {
- integer ret=1
local expl
declare -a userbrowsers builtinbrowsers
@@ -6431,16 +6516,9 @@ __git_browsers () {
cygstart
xdg-open)
- _tags user-browsers builtin-browsers
-
- while _tags; do
- _requested user-browsers expl 'user-defined browser' compadd $* - $userbrowsers && ret=0
- _requested builtin-browsers expl 'builtin browser' compadd $* - $builtinbrowsers && ret=0
-
- (( ret )) || break
- done
-
- return ret
+ _alternative \
+ 'user-browsers:user-defined browser:compadd -a - userbrowsers' \
+ 'builtin-browsers:builtin browser:compadd -a - builtinbrowsers'
}
(( $+functions[__git_difftools] )) ||
@@ -6458,21 +6536,28 @@ __git_diff-or-merge-tools () {
[[ $type == diff ]] && __git_config_get_regexp '^difftool\..+\.cmd$' userdifftools
__git_config_get_regexp '^mergetool\..+\.cmd$' usermergetools
builtintools=(
+ araxis
+ bc
+ bc3
+ codecompare
+ deltawalker
+ diffmerge
+ diffuse
+ ecmerge
+ emerge
+ gvimdiff
+ gvimdiff2
+ gvimdiff3
kdiff3
- tkdiff
- xxdiff
meld
opendiff
+ p4merge
+ tkdiff
+ tortoisemerge
vimdiff
- gvimdiff
vimdiff2
vimdiff3
- gvimdiff2
- emerge
- ecmerge
- diffuse
- araxis
- p4merge)
+ xxdiff)
builtindifftools=($builtintools kompare)
builtinmergetools=($builtintools tortoisemerge)
@@ -6483,10 +6568,10 @@ __git_diff-or-merge-tools () {
esac
while _tags; do
- _requested user-difftools expl 'user-defined difftool' compadd $* - $userdifftools && ret=0
- _requested user-mergetools expl 'user-defined mergetool' compadd $* - $usermergetools && ret=0
- _requested builtin-difftools expl 'builtin difftool' compadd $* - $builtindifftools && ret=0
- _requested builtin-mergetools expl 'builtin mergetool' compadd $* - $builtinmergetools && ret=0
+ _requested user-difftools expl 'user-defined difftool' compadd "$@" -a - userdifftools && ret=0
+ _requested user-mergetools expl 'user-defined mergetool' compadd "$@" -a - usermergetools && ret=0
+ _requested builtin-difftools expl 'builtin difftool' compadd "$@" -a - builtindifftools && ret=0
+ _requested builtin-mergetools expl 'builtin mergetool' compadd "$@" -a - builtinmergetools && ret=0
(( ret )) || break
done
@@ -6577,20 +6662,18 @@ __git_sendemail_suppresscc_values () {
(( $+functions[__git_colors] )) ||
__git_colors () {
- declare -a colors
+ declare -a expl
- colors=(black red green yellow blue magenta cyan white)
-
- _describe -t colors color colors $*
+ _wanted colors expl color compadd "$@" - \
+ black red green yellow blue magenta cyan white
}
(( $+functions[__git_color_attributes] )) ||
__git_color_attributes () {
- declare -a attributes
-
- attributes=(bold dim ul blink reverse)
+ declare -a expl
- _describe -t attributes attribute attributes $*
+ _wanted attributes expl attribute compadd "$@" - \
+ bold dim ul blink reverse
}
# Now, for the main drive...
@@ -6657,12 +6740,12 @@ _git() {
(option-or-argument)
curcontext=${curcontext%:*:*}:git-$words[1]:
- if (( $+functions[_git-$words[1]] )); then
- _call_function ret _git-$words[1]
- elif zstyle -T :completion:$curcontext: use-fallback; then
- _files && ret=0
- else
- _message 'unknown sub-command'
+ if ! _call_function ret _git-$words[1]; then
+ if zstyle -T :completion:$curcontext: use-fallback; then
+ _default && ret=0
+ else
+ _message "unknown sub-command: $words[1]"
+ fi
fi
;;
esac
diff --git a/Completion/Unix/Command/_global b/Completion/Unix/Command/_global
index bb6f7a0fa..c4714cb05 100644
--- a/Completion/Unix/Command/_global
+++ b/Completion/Unix/Command/_global
@@ -11,14 +11,30 @@ _arguments \
"$cmds"{-P,--path}'[print paths matching pattern]:pattern:' \
"$cmds"{-u,--update}'[locate tag files and update incrementally]' \
'(-a --absolute)'{-a,--absolute}'[print absolute path names]' \
+ '(--color)--color=-[color matches]::color:(always auto never)' \
+ '(-d --definition)'{-d,--definition}'[print locations of definitions]' \
'(-e --regexp :)'{-e,--regexp}'[specify pattern]:pattern:_global_tags' \
+ '(--encode-path)--encode-path=-[encode path charcters in hexadecimal representation]:format' \
+ '(-F --first-match)'{-f,--first-match}'[stop searching if tag is found in current tag file]' \
+ '(--from-here)--from-here=-[decide tag type by context]:line_path:' \
'(-G --basic-regexp :)'{-G,--basic-regexp}'[specify basic regexp to use]:word:_global_tags' \
+ '(--gtagsconf)--gtagsconf=-[set environment variable GTAGSCONF]:file:_files' \
+ '(--gtagslabel)--gtagslabel=-[set environment variable GTAGSLABEL]:file:_files' \
'(-i --ignore-case)'{-i,--ignore-case}'[ignore case in patterns]' \
+ '(-L --file-list)'{-L,--file-list}'[obtain files from file in addition to the arguments]:file:_files' \
'(-l --local)'{-l,--local}'[print just objects which exist under the current directory]' \
+ '(--literal)--literal[use leteral search instead of regexp search]' \
+ '(-M --match-case)'{-m,--match-case}'[enable case sensitive search]' \
+ '(--match-part)--match-part=-[speficy how path name completion should match]::part:(first last all)' \
'(-n --nofilter)'{-n,--nofilter}'[suppress sort filter and path conversion filter]' \
+ '(-O --only-other)'{-O,--only-other}'[search only text files]' \
'(-o --other)'{-o,--other}'[search in other files, not just source files (with -g)]' \
+ '(--path-style)--path-style=-[specify path style]::style:(relative absolute shorter abslib through)' \
+ '(--print0)--print0[print each record followed by a null character]' \
'(-q --quiet)'{-q,--quiet}'[quiet mode]' \
'(-r --reference --rootdir)'{-r,--reference,--rootdir}'[find object references instead of definitions]' \
+ '(--result)--result=-[specify result format]::format:(path ctags ctags-x grep cscope)' \
+ '(- :)--single-update=-[updata tag for specified file]:file:_files' \
'(-s --symbol)'{-s,--symbol}'[find symbols instead of function names]:pattern' \
'(-t --tags)'{-t,--tags}'[output in standard ctags format]' \
'(-T --through -s -r -l)'{-T,--through}'[search through all tag files in GTAGSLIBPATH]' \
diff --git a/Completion/Unix/Command/_gpg b/Completion/Unix/Command/_gpg
index 6f2fd4834..fe236d5bf 100644
--- a/Completion/Unix/Command/_gpg
+++ b/Completion/Unix/Command/_gpg
@@ -1,23 +1,30 @@
-#compdef gpg gpgv gpg-zip
+#compdef gpg gpgv gpg-zip gpg2=gpg
local curcontext="$curcontext" state line expl ret=1
-local -a gpgbasic gpgextra gpgv gpgzip
+local -a args allopts dups
typeset -A opt_args
-gpgv=('(-q --quiet)*'{-v,--verbose}'[increase amount of output]'
- '(-q --quiet -v --verbose)'{-q,--quiet}'[reduce amount of output]'
- '--keyring=[add specified file to list of keyrings]:file:_files'
- '--'{status,logger}'-fd:file descriptor:_file_descriptors'
- '--ignore-time-conflict'
- '--homedir:directory:_directories')
-
-gpgzip=('--gpg[command to use instead of gpg]:command:_command'
- '--gpg-args[gpg arguments]:gpg arguments:'
- '--tar[command to use instead of tar]:command:_command'
- '--tar-args[tar arguments]:tar arguments:'
- '--list-archive[list archive contents]')
+if [[ $service = gpg-zip ]]; then
+ args=(
+ '--gpg[command to use instead of gpg]:command:_command'
+ '--gpg-args[gpg arguments]:gpg arguments:'
+ '--tar[command to use instead of tar]:command:_command'
+ '--tar-args[tar arguments]:tar arguments:'
+ '--list-archive[list archive contents]'
+ )
+else
+ allopts=( $(_call_program options $words[1] --dump-options) )
+ args=(
+ '(-q --quiet)*'{-v,--verbose}'[increase amount of output]'
+ '(-q --quiet -v --verbose)'{-q,--quiet}'[reduce amount of output]'
+ '--keyring=[add specified file to list of keyrings]:file:_files'
+ '--'{status,logger}'-fd:file descriptor:_file_descriptors'
+ '--homedir:directory:_directories'
+ )
+fi
-gpgbasic=('(-e --encrypt)'{-e,--encrypt}'[encrypt data. this option may be combined with --sign]'
+[[ $service = gpgv ]] || args+=(
+ '(-e --encrypt)'{-e,--encrypt}'[encrypt data. this option may be combined with --sign]'
{-d,--decrypt}'[decrypt file or stdin]'
'(-c --symmetric)'{-c,--symmetric}'[encrypt with symmetric cypher only]'
'(-s --sign)'{-s,--sign}'[make a signature]'
@@ -25,9 +32,11 @@ gpgbasic=('(-e --encrypt)'{-e,--encrypt}'[encrypt data. this option may be combi
'(-u --local-user)'{-u+,--local-user}'[use name as the user ID to sign]:user attachment:_users'
'(-o --output)'{-o+,--output}'[write output to file]:output file:_files'
'(-h --help)'{-h,--help}'[display usage information]'
- '--version[print info on program version and supported algorithms]')
+ '--version[print info on program version and supported algorithms]'
+)
-gpgextra=('--decrypt-files[decrypt multiple files]'
+[[ $service = gpg ]] && args+=(
+ '--decrypt-files[decrypt multiple files]'
'(-b --detach-sign)'{-b,--detach-sign}'[make a detached signature]'
'--clearsign[make a clear text signature]'
'--store[store only]'
@@ -46,16 +55,14 @@ gpgextra=('--decrypt-files[decrypt multiple files]'
'--edit-key[a menu for edit yours keys]:key attachment:->public-keys'
'--sign-key[sign a key]:key attachment:->public-keys'
'--lsign-key[sign a key but mark as non-exportable]:key attachment:->public-keys'
- '--nrsign-key[sign a key non-revocably]'
- '--delete-key[remove key from public keyring]:key attachment:->public-keys'
- '--delete-secret-key[remove key from public & private keyring]:key attachment:->secret-keys'
- '--delete-secret-and-public-key:key attachment:->secret-keys'
+ '--delete-keys[remove key from public keyring]:key attachment:->public-keys'
+ '--delete-secret-keys[remove key from public & private keyring]:key attachment:->secret-keys'
+ '--delete-secret-and-public-keys:key attachment:->secret-keys'
'--gen-revoke[generate a revocation certificate]'
'--desig-revoke[generate a designated revocation certificate]'
'--export[export all key from all keyrings]'
'--send-keys[send keys to a keyserver]:key attachment:->public-keyids'
- '--export-all[export all key and not OpenPGP compatible keys]'
- '--export-secret-keys:key attachment:->secret-keys'
+ '--export-secret-keys:key attahment:->secret-keys'
'--export-secret-subkeys:key attachment:->secret-keys'
'--import[import a gpg key from a file]:_files attachment:_files'
'--fast-import[import a file without build trustdb]:_files attachment:_files'
@@ -81,7 +88,7 @@ gpgextra=('--decrypt-files[decrypt multiple files]'
'--no-default-recipient[reset default recipient]'
'*--encrypt-to[specify recipient]:key:->public-keys'
'(--encrypt-to)--no-encrypt-to[disable the use of all --encrypt-to keys]'
- '(-z --compress)'{-z,--compress}'[specify compression level]:compression level:((0\:no\ compression 1\:minimum 2 3 4 5 6\:default 7 8 9\:maximum))'
+ '-z[specify compression level]:compression level:((0\:no\ compression 1\:minimum 2 3 4 5 6\:default 7 8 9\:maximum))'
'(-t --textmode)'{-t,--textmode}'[use canonical text mode]'
'(-n --dry-run)'{-n,--dry-run}"[don't make any changes]"
'(-i --interactive --batch)'{-i,--interactive}'[prompt before overwriting files]'
@@ -97,7 +104,7 @@ gpgextra=('--decrypt-files[decrypt multiple files]'
'--keyserver-options[specify keyserver options]:options'
'--import-options[specify options for importing keys]:options'
'--export-options[specify options for exporting keys]:options'
- '--show-photos' '--no-show-photos' '--photo-viewer:command:_command_names -e'
+ '--photo-viewer:command:_command_names -e'
'--exec-path:path:_dir_list'
'--show-keyring[display keyring name when listing keys]'
'--secret-keyring[add specified file to list of secret keyrings]:file:_files'
@@ -113,70 +120,45 @@ gpgextra=('--decrypt-files[decrypt multiple files]'
'(--no-show-notation)--show-notation[show key signature notations]'
"(--show-notation)--no-show-notation[don't show key signature notations]"
'--set-policy-url:policy URL'
- '(--no-show-policy-url)--show-policy-url'
- '(--show-policy-url)--no-show-policy-url'
'--set-filename[specify file which is stored in messages]:file:_files'
- '(--for-your-eyes-only)--for-your-eyes-only'
- '(--for-your-eyes-only)--no-for-your-eyes-only'
'--completes-needed:number' '--marginals-needed:number' '--max-cert-depth:number'
'--'{{,disable-,s2k-}cipher,{,s2k-,cert-}digest,disable-pubkey}'-algo:cipher:->ciphers'
- '--s2k-mode:value' '--simple-sk-checksum'
+ '--s2k-mode:value'
'--compress-algo:compression algorithm:((0\:disable\ compression 1\:zlib 2\:rfc1950))'
- '--no-sig-cache' '--no-sig-create-check' '--'{,no-}'auto-check-trustdb' '--throw-keyid'
- '--not-dash-escaped' '--'{,no-}'escape-from-lines' '--'{,no-}'use-agent'
- '--rfc1991' '--'{,no-}'pgp2' '--'{,no}'pgp6' '--'{,no}'pgp7' '--openpgp'
- '--'{,no-}'force-v3-sigs' '--'{,no}'force-v4-certs' '--force-mdc' '--disable-mdc'
- '--'{,no-}'allow-non-selfsigned-uid' '--allow-freeform-uid'
- '--ignore-valid-from'
- '--ignore-crc-error' '--ignore-mdc-error' '--lock-once' '--lock-multiple' '--lock-never'
- '--no-random-seed-file' '--no-verbose' '--no-greeting' '--no-secmem-warning'
- '--no-permission-warning' '--no-mdc-warning' '--no-armor' '--no-default-keyring'
- '--skip-verify' '--with-colons' '--with-key-data' '--with-fingerprint'
- '--fast-list-mode' '--fixed-list-mode' '--list-only' '--no-literal' '--set-filesize'
- '--emulate-md-encode-bug' '--show-session-key' '--override-session-key:string'
- '--'{,no-}'ask-sig-expire' '--'{,no}'ask-cert-expire' '--'{,no}'expert'
- '--merge-only' '--allow-secret-key-import' '--try-all-secrets'
- '--enable-special-filenames' '--no-expensive-trust-checks' '--group:name=value'
- '--preserve-permissions' '--personal-'{cipher,digest,compress}'-preferences:string'
+ '--personal-'{cipher,digest,compress}'-preferences:string'
'--card-edit[present smartcard menu]' '--card-status[show smartcard content]'
'--change-pin[present menu to change smartcard pin]'
'--list-config[display internal configuration parameters]'
'--hidden-recipient[hidden recipient]:recipient:->public-keys'
'--dump-options[show all options]' '--default-preference-list:string'
- '--fetch-keys:URIs:' '--gpgconf-list' '--gpgconf-test'
+ '--fetch-keys:URIs'
'--hidden-encrypt-to:recipient:->public-keys'
- '--compress-level:integer:'
- '--bzip2-compress-level:integer:' '--bzip2-decompress-lowmem'
- '--default-sig-expire' '--default-cert-expire' '--no-ask-cert-expire'
- '--default-cert-level:integer:'
- '--min-cert-level' '--ask-cert-level' '--no-ask-cert-level'
+ '--compress-level:integer'
+ '--bzip2-compress-level:integer'
+ '--default-cert-level:integer'
'--max-output[maximum output generated when processing file]:bytes:'
'--gpg-agent-info[override GPG_AGENT_INFO]:'
'--primary-keyring:file:_files'
- '--'{,no-}'verify-options:parameters:_multi_parts -q -S, ","
+ '--verify-options:parameters:_multi_parts -q -S, ","
"(show-photos show-policy-urls show-notations show-std-notations
show-user-notations show-keyserver-urls show-uid-validity show-unusable-uids
show-primary-uid-only pka-lookups pka-trust-increase)"'
- '--debug:flags:' '--debug-all' '--status-file:file:'
- '--attribute-file:file:' '--load-extension:file:_files'
- '--gnupg' '--rfc2440' '--rfc4880' '--pgp8'
- '--s2k-count:integer:' '--'{,no-}'throw-keyids'
+ '--debug:flags:' '--status-file:file:_files'
+ '--attribute-file:file:_files' '--load-extension:file:_files'
+ '--s2k-count:integer'
'--sig-notation:name=value:' '--cert-notation:name=value:'
'--passphrase-file:file:_files' '--passphrase-repeat:integer:'
'--command-file:file:_files' '--trustdb-name:file:_files'
- '--'{,no-}'require-secmem'
'--trust-model:trust model:((pgp classic direct always auto))'
'--sig-policy-url:string:' '--cert-policy-url:string:'
'--sig-keyserver-url:string:' '--comment[comment]:comment:'
'--no-comments[disable comments]'
'--logger-file[write log to file]:file:_files'
- '--'{,no-}'use-embedded-filename'
'--rebuild-keydb-caches[create signature caches in keyring]'
'--default-keyserver-url:name:'
'--display-charset[set native charset]:charset:((iso-8859-1 iso-8859-2 iso-8859-15 koi8-r utf-8))'
'--ungroup[remove group]:group name:'
'--no-groups[remove all entries from --group list]'
- '--'{,no}'mangle-dos-filenames'
'--enable-progress-filter[enable progress status output]'
'--multifile[process multiple files]'
'--keyid-format[key id format]:key format:((short 0xshort long 0xlong))'
@@ -185,25 +167,13 @@ gpgextra=('--decrypt-files[decrypt multiple files]'
'--reader-port[card reader port]:port:'
'--ctapi-driver[file to use to access smartcard reader]:file:_files'
'--pcsc-driver[file to use to access smartcard reader]:file:_files'
- '--disable-ccid' '--debug-ccid-driver'
- '--'{enable,disable}'-dsa2'
- '--'{,no-}'allow-multiple-messages' '--'{,no-}'require-cross-certification'
- '--auto-key-locate:parameters:' '--no-auto-key-locate'
- '--dump-options[show all options]')
-
-case "$service" in
- gpg)
- _arguments -C -s -S -A "-*" $gpgbasic $gpgextra $gpgv '*:args:->args' && ret=0
- ;;
+ '--auto-key-locate:parameters'
+ '--dump-options[show all options]'
+)
- gpgv)
- _arguments -C -s -S -A "-*" $gpgv '*:args:->args' && ret=0
- ;;
-
- gpg-zip)
- _arguments -C -s -S -A "-*" $gpgbasic $gpgzip '*:args:->args' && ret=0
- ;;
-esac
+extra=( ${${${args#\([^\)]#\)}#\*}%%[:=\[]*} )
+extra=( ${allopts:|extra} )
+_arguments -C -s -S -A "-*" $args $extra '*:args:->args' && ret=0
if [[ $state = args ]]; then
if (( ${+opt_args[--export]} || ${+opt_args[--list-keys]} || ${+opt_args[--list-public-keys]} )); then
diff --git a/Completion/Unix/Command/_grep b/Completion/Unix/Command/_grep
index 5068f6e48..d987c2b1e 100644
--- a/Completion/Unix/Command/_grep
+++ b/Completion/Unix/Command/_grep
@@ -1,4 +1,4 @@
-#compdef grep egrep fgrep -value-,GREP_OPTIONS,-default-
+#compdef grep egrep fgrep bsdgrep zgrep, zegrep, zfgrep -value-,GREP_OPTIONS,-default-
# Ulrik Haugen 2001
local arguments matchers command
diff --git a/Completion/Unix/Command/_hg b/Completion/Unix/Command/_hg
index c18500bcb..e7c21b9d1 100644
--- a/Completion/Unix/Command/_hg
+++ b/Completion/Unix/Command/_hg
@@ -162,15 +162,24 @@ _hg_revrange() {
_hg_tags "$@"
}
-_hg_tags() {
- typeset -a tags
- local tag rev
+_hg_tags_internal() {
+ local expl
+ typeset -a hgtags
+ hgtags=( ${(f)"$(_hg_cmd tags -q 2>/dev/null)"} )
+ _wanted tags expl 'tags' compadd -a - hgtags
+}
- _hg_cmd tags 2> /dev/null | while read tag
- do
- tags+=(${tag/ # [0-9]#:*})
- done
- (( $#tags )) && _describe -t tags 'tags' tags
+_hg_bookmarks_internal() {
+ local expl
+ typeset -a hgbookmarks
+ hgbookmarks=( ${(f)"$(_hg_cmd bookmarks -q 2>/dev/null)"} )
+ _wanted bookmarks expl 'bookmarks' compadd -a - hgbookmarks
+}
+
+_hg_tags() {
+ _alternative \
+ 'bookmarks:bookmark:_hg_bookmarks_internal' \
+ 'tags:tag:_hg_tags_internal'
}
# likely merge candidates
diff --git a/Completion/Unix/Command/_iconv b/Completion/Unix/Command/_iconv
index 82c2d320a..d040be756 100644
--- a/Completion/Unix/Command/_iconv
+++ b/Completion/Unix/Command/_iconv
@@ -1,8 +1,8 @@
#compdef iconv
-local expl curcontext="$curcontext" state line ret=1
+local expl curcontext="$curcontext" state line variant ret=1
-if _pick_variant libiconv='GNU*libiconv' glibc='(GNU*libc|EGLIBC)' unix --version; then
+if _pick_variant -r variant libiconv='GNU*libiconv' glibc='(GNU*libc|EGLIBC|Gentoo)' unix --version; then
local -a args
local exargs="-l --list -? --help --usage --version -V"
@@ -13,22 +13,22 @@ if _pick_variant libiconv='GNU*libiconv' glibc='(GNU*libc|EGLIBC)' unix --versio
"($exargs)-c[omit invalid characters from output]"
"(-s --silent --verbose $exargs)"{-s,--silent}'[suppress warnings]'
'(-)'{-\?,--help}'[display help information]'
- '(-)--usage[display a short usage message]'
'(-)'{-V,--version}'[print program version]'
'1:input file:_files'
)
- case $_cmd_variant[$service] in
+ case $variant in
(libiconv)
args=( ${(R)args:#(|\*)(|\(*\))-[V\?]*} ) # remove -V and -?
args+=(
- '--byte-subst=[format for unconvertible bytes]:format string:'
- '--widechar-subst=[format for unconvertible wide chars]:format string:'
- '--unicode-subst=[format for unconvertible Unicode chars]:format string:'
+ '--byte-subst=[format for unconvertible bytes]:format string'
+ '--widechar-subst=[format for unconvertible wide chars]:format string'
+ '--unicode-subst=[format for unconvertible Unicode chars]:format string'
)
;;
(glibc)
args+=(
+ '(-)--usage[display a short usage message]'
"(-o --output $exargs)"{-o+,--output=}'[specify output file]:output file:_files'
"(-s --silent $exargs)--verbose[print progress information]"
)
@@ -44,7 +44,7 @@ if _pick_variant libiconv='GNU*libiconv' glibc='(GNU*libc|EGLIBC)' unix --versio
else
_wanted codesets expl 'code set' compadd "$@" \
-M 'm:{a-zA-Z}={A-Za-z} r:|-=* r:|=*' \
- ${$(_call_program codesets iconv --list)%//} && ret=0
+ ${$(_call_program codesets $words[1] --list)%//} && ret=0
fi
fi
@@ -55,12 +55,17 @@ else
local -U codeset
_arguments -C \
- '-f[specify code set of input file]:code set:->codeset' \
- '-t[specify code set for output]:code set:->codeset' \
+ '(-l)-f[specify code set of input file]:code set:->codeset' \
+ '(-l)-t[specify code set for output]:code set:->codeset' \
+ '(-l)-c[omit invalid characters from output]' \
+ '(-l)-s[suppress warnings]' \
+ '(- 1)-l[list all character code sets]' \
'1:file:_files' && return 0
if [[ $state = codeset ]]; then
- if [[ -f /usr/lib/iconv/iconv_data ]]; then # IRIX & Solaris
+ if [[ $OSTYPE = freebsd* ]]; then
+ codeset=( $(_call_program codesets $words[1] -l) )
+ elif [[ -f /usr/lib/iconv/iconv_data ]]; then # IRIX & Solaris
codeset=( ${${(f)"$(</usr/lib/iconv/iconv_data)"}%%[[:blank:]]*} )
codeset+=( /usr/lib/iconv/*%*.so(Ne.'reply=( ${${REPLY:t}%%%*} ${${REPLY:r}#*%} )'.) )
elif [[ -d $LOCPATH/iconv ]]; then # OSF
@@ -70,7 +75,7 @@ else
return 1
fi
- _wanted codesets expl 'code set' compadd "$@" -a codeset
+ _wanted codesets expl 'code set' compadd -a codeset
fi
fi
diff --git a/Completion/Unix/Command/_id b/Completion/Unix/Command/_id
index 36cdf4c19..74fe6d9e1 100644
--- a/Completion/Unix/Command/_id
+++ b/Completion/Unix/Command/_id
@@ -1,13 +1,49 @@
-#compdef id
+#compdef id gid
-_arguments \
- '-a[no-op]' \
- '(-Z --context)'{-Z,--context}'[print only context]' \
- '(-g --group)'{-g,--group}'[print only EGID]' \
- '(-G --groups)'{-G,--groups}'[print all GIDs]' \
- '(-n --name)'{-n,--name}'[print name instead of number]' \
- '(-r --real)'{-r,--real}'[print real ID instead of effective]' \
- '(-u --user)'{-u,--user}'[print only EUID]' \
- '--help[display help]' \
- '--version[display version]' \
- ':user:_users'
+local args choices
+
+if _pick_variant gnu=GNU $OSTYPE --version; then
+ choices='--help --version -Z --context -g --group -G --groups -u --user'
+ _arguments \
+ "($choices)"{-Z,--context}'[print only security context]' \
+ "($choices)"{-g,--group}'[print only EGID]' \
+ "($choices -r --real)"{-G,--groups}'[print all GIDs]' \
+ '(-n --name --help --version)'{-n,--name}'[show name instead of number]' \
+ '(-r --real -g --groups --help --version)'{-r,--real}'[show real ID instead of effective]' \
+ "($choices)"{-u,--user}'[print only EUID]' \
+ '(-z --zero --help --version)'{-z,--zero}'[delimit entries with NUL characters]' \
+ '(- :)--help[display help information]' \
+ '(- :)--version[display version]' \
+ ':user:_users'
+else
+ choices="-A -a -c -G -g -M -p -P -u"
+ args=(
+ "($choices)-g[print only EGID]"
+ "($choices -r)-G[print all GIDs]"
+ "($choices)-u[print only EUID]"
+ '(-A -c -M -P)-n[show name instead of number]'
+ '(-A -c -M -P)-r[show real ID instead of effective]'
+ )
+ case $OSTYPE in
+ solaris*)
+ args+=(
+ '(-g -G -u -n -r)-a[show user name, user ID and all the groups]'
+ '(-g -G -u -n -r)-p[show project membership]'
+ )
+ ;;
+ darwin*|dragonfly*|freebsd*)
+ args+=( '(-)-P[print id in the form of a password file entry]' )
+ ;|
+ darwin*|freebsd*)
+ args+=(
+ '(-)-A[print process audit user ID]'
+ '(-)-M[print MAC label of the current process]'
+ )
+ ;|
+ freebsd*) args+=( '(-)-c[print current login class]' ) ;|
+ darwin*|dragonfly*|freebsd*|netbsd*|openbsd*)
+ args+=( '(-)-p[human readable output]' )
+ ;;
+ esac
+ _arguments -s $args ':user:_users'
+fi
diff --git a/Completion/Unix/Command/_ip b/Completion/Unix/Command/_ip
index f880f2683..bfa7d995b 100644
--- a/Completion/Unix/Command/_ip
+++ b/Completion/Unix/Command/_ip
@@ -8,8 +8,11 @@
#
# Values encoding simple types
#
-local -a subcmd_dev
-subcmd_dev=(/$'[[:alpha:]]##[[:digit:]]##(\.[[:digit:]]##)#\0'/ ':interfaces:network interface:_net_interfaces')
+local -a subcmd_dev net_intf_disp net_intf_list
+# subcmd_dev=(/$'[[:alnum:][:punct:][:cntrl:][:digit:]]##\0'/ ':interfaces:network interface:_net_interfaces')
+_find_net_interfaces
+subcmd_dev=(/"(${(j.|.)net_intf_list})"$'\0'/
+ ':interfaces:network interface:_net_interfaces')
local -a subcmd_onoff
subcmd_onoff=(/$'(on|off)\0'/ ':onoff:state (on or off):(on off)')
@@ -38,6 +41,7 @@ subcmd_ipaddrs=(
/$'(<->(.<->(.<->(.<->|)|)|)|[:[:xdigit]]#:[:[:xdigit:]]#)(|/<->)\0'/
":ipaddress:IP address (v4 or v6) currently set:( $(ip addr show | sed -n 's/^ *inet6* \([0-9a-f\.:/]*\) .*$/\1/p') )"
)
+local -a subcmd_prefix_label
subcmd_prefix_label=(
/$'(<->(.<->(.<->(.<->|)|)|)|[:[:xdigit]]#:[:[:xdigit:]]#)(|/<->)\0'/
":ipaddresslabel:IP addrlabel prefix currently set:( $(ip -6 addrlabel list 2>/dev/null | sed -n 's/^prefix \([0-9a-f\.:/]*\) .*$/\1/p') )"
@@ -98,7 +102,7 @@ _regex_words nexthop 'nexthop route keyword' \
'weight:specify relative quality of route:$subcmd_number'
subcmd_nexthop=("$reply[@]" "#")
-local -a subcmd_rtproto
+local -a subcmd_rtprotocol
_regex_words rtprotocol 'route protocol' \
'redirect:installed from ICMP redirect' \
'kernel:installed automatically by kernel' \
diff --git a/Completion/Unix/Command/_join b/Completion/Unix/Command/_join
index 956d9d3b8..4915a0600 100644
--- a/Completion/Unix/Command/_join
+++ b/Completion/Unix/Command/_join
@@ -1,23 +1,29 @@
-#compdef join
+#compdef join gjoin
-# completions for GNU join version 5.97
-
-local arguments
-
-arguments=(
- '-a+[print unpairable lines coming from file FILENUM, where FILENUM is 1 or 2, corresponding to FILE1 or FILE2]:file number:(1 2)'
- '-e+[replace missing input fields with EMPTY]:replacement string:'
- '(-i --ignore-case)'{-i,--ignore-case}'[ignore differences in case when comparing fields]'
- "-j+[equivalent to '-1 FIELD -2 FIELD']:field number:"
- '-o+[obey FORMAT while constructing output line]:format string:'
- '-t+[use CHAR as input and output field separator]:separator:'
- '-v+[like -a FILENUM, but suppress joined output lines]:file number:(1 2)'
- '-1+[join on this FIELD of file 1]:field number:'
- '-2+[join on this FIELD of file 2]:field number:'
- --help'[display help and exit]'
- --version'[output version information and exit]'
- '1:file 1:_files'
- '2:file 2:_files'
+local args variant
+args=(
+ '*-a+[print unpairable lines from specified file]:file number:(1 2)'
+ '-e+[replace missing input fields with specified string]:replacement string'
+ "(-1 -2)-j+[join on specified field for both files]:field number"
+ '-o+[use specified output format]:format string'
+ '-t+[use specified character as field separator]:separator'
+ '*-v+[like -a, but suppress joined output lines]:file number:(1 2)'
+ '(-j -1 -j1)'{-j1,-1+}'[join on specified field of first file]:field number'
+ '(-j -2 -j2)'{-j2,-2+}'[join on specified field of second file]:field number'
+ '1:file:_files' '2:file:_files'
+)
+_pick_variant -r variant gnu=GNU $OSTYPE --version
+case $variant in
+ gnu)
+ args+=(
+ '(-i --ignore-case)'{-i,--ignore-case}'[ignore differences in case when comparing fields]'
+ '(-)--help[display help information]'
+ '(-)--version[output version information]'
+ '(--check-order --nocheck-order)'{--check-order,--nocheck-order}
+ '--header[treat first line in each file as field headers]'
+ '(-z --zero-terminated)'{-z,--zero-terminated}'[end lines with 0 byte, not newline]'
)
+ ;;
+esac
-_arguments -s $arguments
+_arguments -s $args
diff --git a/Completion/Unix/Command/_last b/Completion/Unix/Command/_last
index 43a08a709..706d82f26 100644
--- a/Completion/Unix/Command/_last
+++ b/Completion/Unix/Command/_last
@@ -1,17 +1,53 @@
#compdef last lastb
-_arguments -s \
- '-a[display hostname in last column]' \
- '-n[number]:number' \
- '-[number]:number' \
- '-f[filename]:filename:_files' \
- '-R[suppress display of hostname field]' \
- '-d[translate IP to hostname]' \
- '-i[display IP]' \
- '-o[read old-format wtmp]' \
- '-x[display shutdown/runlevel entries]' \
- '-h[hostname]:host:_hosts' \
- '-s[report duration in seconds]' \
- '-t[tty]:tty' \
- '-w[widen duration field]' \
- '*:user:_users'
+local pattern arg args ttys
+ttys=( /dev/tty*(N) /dev/pts/*(N) reboot )
+ttys=( ${ttys#/dev/} )
+
+for pattern arg in \
+ '(solaris*|linux-gnu)' '-a[display hostname in last column]' \
+ '((free|net|open)bsd*|darwin*|dragonfly*|linux-gnu)' '-h[limit sessions by hostname]:host:_hosts' \
+ '((free|open)bsd*|linux-gnu)' '-s[report duration in seconds]' \
+ '(freebsd*|openbsd*)' '-d[limit sessions to those active at snapshot time]:time ([[CC]YY][MMDD]hhmm[.SS])' \
+ '((net|free|open)bsd*|darwin*|dragonfly*)' '-t[limit sessions by tty]:tty:compadd -a ttys' \
+ 'openbsd*' '-c[calculate total time]' \
+ '^darwin*' '-f[specify account file]:file:_files' \
+ '(solaris*|linux-gnu|freebsd*|openbsd*)' '-n[specify number of lines to show]:number' \
+ '((open|net)bsd*|dragonfly*)' '-T[show more detailed time information including year and seconds]' \
+ 'netbsd*' '-x[assume file is in wtmpx(5) format]' \
+ 'netbsd*' '-n[show IP of remote hosts]' \
+ 'freebsd*' '-w[show seconds in durarion field]' \
+ 'freebsd*' '-y[show year in session start time]'
+do
+ [[ $OSTYPE = $~pattern ]] && args+=( $arg )
+done
+
+case $OSTYPE in
+ netbsd*|dragonfly*)
+ args+=(
+ '-H[specify width for host field]:width'
+ '-N[specify width for login name field]:width'
+ '-L[specify width for tty field]:width'
+ )
+ ;;
+ linux-gnu)
+ args+=(
+ '-R[suppress display of hostname field]'
+ '-d[translate IP to hostname]'
+ '-F[show full login and logout times and dates]'
+ '-i[show IP of remote hosts]'
+ '-o[read old-format wtmp]'
+ '-t[limit sessions to those active at snapshot time]:time (YYYYMMDDhhmmss)'
+ '-w[show full user and domain names]'
+ '-x[display shutdown/runlevel entries]'
+ )
+ ;;
+esac
+
+if [[ $OSTYPE = (linux-gnu|solaris*) ]]; then
+ args+=( '*:arg: _alternative "users:user:_users" "ttys:tty:compadd -a ttys"' )
+else
+ args+=( '*:user:_users' )
+fi
+
+_arguments -s $args
diff --git a/Completion/Unix/Command/_ldd b/Completion/Unix/Command/_ldd
index 0980bc043..19b8a9105 100644
--- a/Completion/Unix/Command/_ldd
+++ b/Completion/Unix/Command/_ldd
@@ -1,6 +1,6 @@
#compdef ldd
-if _pick_variant gnu='(GNU|EGLIBC)' solaris --version; then
+if _pick_variant gnu='(GNU|EGLIBC|Gentoo)' unix --version; then
args=(
'(- *)--version[display version information]'
'(- *)--help[display help information]'
@@ -10,20 +10,31 @@ if _pick_variant gnu='(GNU|EGLIBC)' solaris --version; then
'(-u --unused)'{-u,--unused}'[display any unused objects]'
)
else
- args=(
- -s
- '(-r)-d[check immediate references]'
- '(-d)-r[check immediate and lazy references]'
- '-u[display any unused objects]'
- '-U[display any unreferenced, or unused dependencies]'
- '-e[set specified environment variable]:environment variable:(LD_PRELOAD LD_LIBRARY_PATH LD_RUN_PATH LD_DEBUG LD_DEBUG_OUTPUT LD_NOCONFIG LD_NOAUXFLTR)'
- '-f[check for insecure executable]'
- '-i[display order of execution of initialization sections]'
- '-L[enable lazy loading]'
- '-l[force immediate processing of any filters]'
- '-s[display search path used]'
- '-v[displays all dependency relationships]'
- )
+ case $OSTYPE in
+ solaris*)
+ args=(
+ -s
+ '(-r)-d[check immediate references]'
+ '(-d)-r[check immediate and lazy references]'
+ '-u[display any unused objects]'
+ '-U[display any unreferenced, or unused dependencies]'
+ '-e[set specified environment variable]:environment variable:(LD_PRELOAD LD_LIBRARY_PATH LD_RUN_PATH LD_DEBUG LD_DEBUG_OUTPUT LD_NOCONFIG LD_NOAUXFLTR)'
+ '-f[check for insecure executable]'
+ '-i[display order of execution of initialization sections]'
+ '-L[enable lazy loading]'
+ '-l[force immediate processing of any filters]'
+ '-s[display search path used]'
+ '-v[displays all dependency relationships]'
+ )
+ ;;
+ freebsd*)
+ args=(
+ '-a[show all objects that are needed by each loaded object]'
+ '-v[verbose listing of the dynamic linking headers]'
+ '-f+[specify format]:format:((%a\:program\ name %A\:environment\ name %o\:library\ name %p\:path\ to\ library %x\:load\ address))'
+ )
+ ;;
+ esac
fi
_arguments $args \
diff --git a/Completion/Unix/Command/_less b/Completion/Unix/Command/_less
index ede54a49c..a3ba8f665 100644
--- a/Completion/Unix/Command/_less
+++ b/Completion/Unix/Command/_less
@@ -24,8 +24,8 @@ if compset -P '+[-0-9]#'; then
g:goto\ line
F:scroll\ to\ end\ and\ keep\ reading\ file
G:go\ to\ end\ of\ file
- %:go\ to\ position\ in\ file
- p:go\ to\ position\ in\ file
+ %:go\ to\ position\ in\ file
+ p:go\ to\ position\ in\ file
)'
return
fi
@@ -101,9 +101,9 @@ if [[ -n "$state" ]]; then
;;
tags)
if (( $+LESSGLOBALTAGS )); then
- _global_tags
+ _global_tags && ret=0
else
- _ctags_tags
+ _ctags_tags && ret=0
fi
;;
esac
diff --git a/Completion/Unix/Command/_lha b/Completion/Unix/Command/_lha
index 5a238d807..c2d5e7d8d 100644
--- a/Completion/Unix/Command/_lha
+++ b/Completion/Unix/Command/_lha
@@ -5,16 +5,16 @@ if (( CURRENT == 2 )); then
local lhacmds
lhacmds=(
- '( x l v u d m c p t)a[Add \(Or replace\) to archive]'
- '(a l v u d m c p t)x[EXtract from archive]'
- '(a x v u d m c p t)l[List]'
- '(a x l u d m c p t)v[Verbose List]'
- '(a x l v d m c p t)u[Update newer files to archive]'
- '(a x l v u m c p t)d[Delete from archive]'
- '(a x l v u d c p t)m[Move to archive]'
- '(a x l v u d m p t)c[re-Construct new archive]'
- '(a x l v u d m c t)p[Print to STDOUT from archive]'
- '(a x l v u d m c p )t[Test file CRC in archive]'
+ '( x l v u d m c p t)a[add \(or replace\) to archive]'
+ '(a l v u d m c p t)x[extract from archive]'
+ '(a x v u d m c p t)l[list]'
+ '(a x l u d m c p t)v[verbose List]'
+ '(a x l v d m c p t)u[update newer files to archive]'
+ '(a x l v u m c p t)d[delete from archive]'
+ '(a x l v u d c p t)m[move to archive]'
+ '(a x l v u d m p t)c[re-construct new archive]'
+ '(a x l v u d m c t)p[print to stdout from archive]'
+ '(a x l v u d m c p )t[test file CRC in archive]'
)
if [ "${words[2]#-}" != "" ]; then
@@ -23,22 +23,22 @@ if (( CURRENT == 2 )); then
'q[quiet]'
'n[not execute]'
'f[force\(over write at extract\)]'
- 't[FILES are TEXT file]'
- 'e[TEXT code convert from/to EUC]'
- 'g[Generic format \(for compatibility\)]'
+ 't[files are text files]'
+ 'e[text code convert from/to EUC]'
+ 'g[use generic format \(for compatibility\)]'
)
case ${words[2]#-} in
a*|u*)
lhacmds=($lhacmds
- 'd[delete FILES after]'
- 'z[files not compress]'
+ 'd[delete files after]'
+ "z[don't compress files]"
'( 1 2)0[header level 0]'
'(0 2)1[header level 1]'
'(0 1 )2[header level 2]'
)
;;
c*)
- lhacmds=($lhacmds 'd[delete FILES after]')
+ lhacmds=($lhacmds 'd[delete files after]')
;;
x*)
lhacmds=($lhacmds 'i[ignore directory path]')
@@ -46,32 +46,25 @@ if (( CURRENT == 2 )); then
esac
fi
- _values -s '' 'lha command' \
- $lhacmds \
- && return 0
+ _values -s '' 'lha command' $lhacmds
elif (( CURRENT == 3 )); then
- _arguments -C \
- '*:LHA file:_files -g \*.lzh' && return 0
+ _wanted files expl 'lha file' _files -g '*.lzh(-.)'
else
case ${words[2]#-} in
l*|x*|d*)
if [ -f "$words[3]" ]; then
- _lzh_cache_list=`$words[1] lq $words[3] | awk '{print $8}'`
+ _lzh_cache_list=`$words[1] lq $words[3] | awk '{print $NF}'`
_lzh_cache_list=("${(@f)${_lzh_cache_list}}")
_wanted files expl 'file from archive' _multi_parts / _lzh_cache_list
-
- return 0
else
- _message -r "Archive file is not found : ${words[3]}"
+ _message -r "archive file is not found : ${words[3]}"
return 1
fi
;;
*)
- _arguments -C \
- '*:file:_files' && return 0
+ _files
+ ;;
esac
fi
-
-return 0
diff --git a/Completion/Unix/Command/_ln b/Completion/Unix/Command/_ln
index 89b7177ab..c903fee02 100644
--- a/Completion/Unix/Command/_ln
+++ b/Completion/Unix/Command/_ln
@@ -1,12 +1,19 @@
-#compdef ln gln
+#compdef ln gln zf_ln
local curcontext="$curcontext" state line ret=1
local -A opt_args
-local -a args
+local -a args bsd
args=(
'-f[remove existing destination files]'
- '-s[create symbolic links instead of hard links]')
+ '-s[create symbolic links instead of hard links]'
+)
+bsd=(
+ '-F[remove existing destination directories]'
+ {-h,-n}'[do not dereference destination]'
+ '-i[prompt before removing destination files]'
+ '-v[print name of each linked file]'
+)
local -a opts
@@ -44,14 +51,16 @@ elif (( ${+builtins[ln]} )); then
{-h,-n}'[do not dereference destination]'
'-i[prompt before removing destination files]')
elif [[ $OSTYPE == darwin* ]]; then
- args+=(
- '-F[remove existing destination directories]'
- {-h,-n}'[do not dereference destination]'
- '-i[prompt before removing destination files]'
- '-v[print name of each linked file]')
+ args+=( $bsd )
+elif [[ $OSTYPE == freebsd* ]]; then
+ args+=( $bsd
+ '(-L)-P[create hard links directly to symbolic links]'
+ '(-P)-L[create hard links to symbolic link references]'
+ "-w[warn if source of a symbolic link doesn't currently exist]"
+ )
fi
-_arguments -s $opts \
+_arguments -C -s $opts \
$args \
':link target:_files' \
'*:: :->files' && ret=0
diff --git a/Completion/Unix/Command/_ls b/Completion/Unix/Command/_ls
index 7680f9273..f2e149453 100644
--- a/Completion/Unix/Command/_ls
+++ b/Completion/Unix/Command/_ls
@@ -1,11 +1,8 @@
#compdef ls gls
-# Ulrik Haugen 2001
local arguments is_gnu
-_pick_variant -r is_gnu gnu=gnu unix --help
-
-if [[ "$OSTYPE" = (netbsd*|freebsd*|openbsd*|darwin*) && "$is_gnu" != gnu ]]; then
+if ! _pick_variant gnu=gnu unix --help; then
arguments=(
'(-A)-a[list entries starting with .]'
'(-a)-A[list all except . and ..]'
@@ -14,10 +11,8 @@ if [[ "$OSTYPE" = (netbsd*|freebsd*|openbsd*|darwin*) && "$is_gnu" != gnu ]]; th
'-R[list subdirectories recursively]'
'(-k)-h[print sizes in human readable form]'
- '(-h)-k[print sizes of 1k]'
'-i[print file inode numbers]'
-
'(-l -g -1 -C -m -x)-l[long listing]'
'(-l -1 -C -m -x)-g[long listing but without owner information]'
'(-l -g -C -m -x)-1[single column output]'
@@ -25,35 +20,36 @@ if [[ "$OSTYPE" = (netbsd*|freebsd*|openbsd*|darwin*) && "$is_gnu" != gnu ]]; th
'(-l -g -1 -C -x)-m[comma separated]'
'(-l -g -1 -C -m)-x[sort horizontally]'
- '-o[display file flags]'
-
'-s[display size of each file in blocks]'
'(-u)-c[status change time]'
'(-c)-u[access time]'
- '-f[unsorted, all, short list]'
'-r[reverse sort order]'
- '(-t)-S[sort by size]'
'(-S)-t[sort by modification time]'
'(-p)-F[append file type indicators]'
'(-F)-p[append file type indicators for directory]'
- '-f[output is not sorted]'
-
'-n[numeric uid, gid]'
- '-T[show complete time information]'
-
- '(-B -b -w -q)-B[print octal escapes for control characters]'
'(-B -b -w -q)-b[as -B, but use C escape codes whenever possible]'
'(-B -b -w -q)-q[hide control chars]'
- '(-B -b -w -q)-w[print raw characters]'
'*:files:_files'
)
+ if [[ "$OSTYPE" = (netbsd*|dragonfly*|freebsd*|openbsd*|darwin*) ]]; then
+ arguments+=(
+ '(-h)-k[print sizes of 1k]'
+ '(-t)-S[sort by size]'
+ '-T[show complete time information]'
+ '-o[display file flags]'
+ '-f[output is not sorted]'
+ '(-B -b -w -q)-w[print raw characters]'
+ '(-B -b -w -q)-B[print octal escapes for control characters]'
+ )
+ fi
if [[ "$OSTYPE" = (freebsd*|darwin*) ]]; then
arguments+=(
'-G[enable colorized output]'
@@ -61,6 +57,18 @@ if [[ "$OSTYPE" = (netbsd*|freebsd*|openbsd*|darwin*) && "$is_gnu" != gnu ]]; th
'-P[do not follow symlinks]'
)
fi
+ if [[ $OSTYPE = solaris* ]]; then
+ arguments+=(
+ '(-l -1 -C -m -x)-o[long listing but without group information]'
+ '(-l -t -s -r -a)-f[interpret each argument as a directory]'
+ '(-E -l)-e[long listing with full and consistent date/time]'
+ '(-e -l)-E[long listing with ISO format date/time]'
+ '-H[follow symlinks on the command line]'
+ '-v[long listing with verbose ACL information]'
+ '-V[long listing with compact ACL information]'
+ '-@[long listing with marker for extended attribute information]'
+ )
+ fi
else
arguments=(
'(--all -a -A --almost-all)'{--all,-a}'[list entries starting with .]'
@@ -131,10 +139,6 @@ else
'(- :)--version[display version information]'
'*:files:_files'
)
- # remove long options?
- if [[ $is_gnu != gnu ]]; then
- arguments=( ${${${arguments:#(|*\))--*}//--[^ )]#/}/\( #\)/} )
- fi
fi
_arguments -s $arguments
diff --git a/Completion/Unix/Command/_lsof b/Completion/Unix/Command/_lsof
index aca9963c2..c12b9910a 100644
--- a/Completion/Unix/Command/_lsof
+++ b/Completion/Unix/Command/_lsof
@@ -1,20 +1,35 @@
#compdef lsof
-_arguments -s -S \
+local curcontext="$curcontext" state line fields args
+
+case $OSTYPE in
+ linux*) args=( '-X[skip reporting of info on network connections]' ) ;;
+ solaris*)
+ args=(
+ '-X[include deleted files]'
+ '-z[zone information]::zone:_zones'
+ )
+ ;;
+esac
+
+_arguments -C -s -S $args \
'(-)'{-\?,-h}'[list help]' \
'-a[AND selections]' \
'-b[avoid kernel blocks]' \
'-C[disable reporting of path name components]' \
- '-c[list files for command beginning with specified char]:char' \
+ '+c[truncate command name to specified characters]:characters' \
+ '-c[list files with specified command name beginning]:command name' \
'+d[search for open instances for contents of specified dir]:search directory:_files -/' \
- '-d[specify list of file descriptors to exclude/include]:file descriptors' \
+ '-d[specify list of file descriptors to exclude/include]:file descriptors:->filedes' \
'+D[recursively search from specified dir]:search directory:_files -/' \
'-D[direct use of device cache file]:function:((\?\:report\ device\ cache\ file\ paths b\:build\ the\ device\ cache\ file i\:ignore\ the\ device\ cache\ file r\:read\ the\ device\ cache\ file u\:read\ and\ update\ the\ device\ cache\ file))' \
- '-f[inhibit listing of kernel file structure info]::info type or path' \
- '+f[enable listing of kernel file structure info]::info type' \
- '-F[select output fields]:fields' \
+ '*-+e[exempt filesystem from blocking kernel calls]:file system:_directories' \
+ '-f[inhibit listing of kernel file structure info]::info type or path:(c f g G n)' \
+ '+f[enable listing of kernel file structure info]::info type:(c f g G n)' \
+ '-F[select output fields]:fields:->fields' \
'-g[select by process group id]::process group id' \
'*-i[select internet files]:address' \
+ '-K[select listing of tasks of processes]' \
'-k[specify kernel name list file]:kernel file:_files' \
'-l[inhibit conversion of UIDs to user names]' \
'-L[list no link counts]' \
@@ -24,10 +39,10 @@ _arguments -s -S \
'+M[enable reporting of portmapper registrations]' \
'-n[inhibit conversion of network numbers to hostnames]' \
'-N[select listing of NFS files]' \
- '(-s)-o[list file offset]' \
+ '(-s)-o[list file offset]::digits for file offset' \
'-O[avoid overheads of bypassing potential blocking]' \
'-P[inhibit conversion of port numbers to port names]' \
- '-p[list files for specified processes]:process ID:_pids' \
+ '-p[list files for specified processes]:process ID:_sequence -s , _pids' \
'-r[repeat listing endlessly]::delay (seconds)' \
'+r[repeat listing until no files listed]::delay (seconds)' \
'-R[list parent PID]' \
@@ -41,4 +56,19 @@ _arguments -s -S \
'-V[indicate unsuccessfully searched for items]' \
'(-t)+w[suppress warnings]' \
'(-t)-w[enable warnings]' \
- '*:file:_files'
+ '-x[cross filesystems/traverse symlinks with +d/+D]::type:((f\:filesystems s\:symlinks))' \
+ '*:file:_files' && return
+
+case $state in
+ fields)
+ fields=( ${${${${(f)"$($words[1] -F \? 2>&1)"}[2,-1]#??}// ##/:}:#(#s)[${PREFIX:-:}]:*} )
+ compset -P '*'
+ _describe -t fields "field" fields -S '' && return
+ ;;
+ filedes)
+ _sequence -s , _wanted -x file-descriptors expl "file descriptor" compadd - \
+ cwd err jld ltz mem mmap pd rtd tr txt v86 && return
+ ;;
+esac
+
+return 1
diff --git a/Completion/Unix/Command/_mail b/Completion/Unix/Command/_mail
index 90c75359d..d618cf366 100644
--- a/Completion/Unix/Command/_mail
+++ b/Completion/Unix/Command/_mail
@@ -1,9 +1,9 @@
#compdef mail mailx=mail Mail=mail mush zmail nail=mail
_arguments -s \
- '(-f -u)*-b[specify a BCC recipient]:BCC recipient:->userhost' \
- '(-f -u)*-c[specify a CC recipient]:CC recipient:->userhost' \
+ '(-f -u)*-b[specify a BCC recipient]:BCC recipient:_email_addresses -n $service' \
+ '(-f -u)*-c[specify a CC recipient]:CC recipient:_email_addresses -n $service' \
'(-b -c -u -s *)-f+[specify mail folder]:mailbox:_mailboxes' \
- '(-f -u)-s+[specify a subject]:subject:' \
+ '(-f -u)-s+[specify a subject]:subject' \
"(-b -c -f -s *)-u+[read specified user's mail]:user:_users" \
"(-f -u)*:recipient:_email_addresses -n $service"
diff --git a/Completion/Unix/Command/_make b/Completion/Unix/Command/_make
index e5a513f64..225c0af85 100644
--- a/Completion/Unix/Command/_make
+++ b/Completion/Unix/Command/_make
@@ -64,18 +64,18 @@ _make-parseMakefile () {
while read input
do
case "$input " in
- # VARIABLE = value
- ([[:alnum:]][[:alnum:]_]#[ $TAB]#=*)
- var=${input%%[ $TAB]#=*}
+ # VARIABLE = value OR VARIABLE ?= value
+ ([[:alnum:]][[:alnum:]_]#[ $TAB]#(\?|)=*)
+ var=${input%%[ $TAB]#(\?|)=*}
val=${input#*=}
val=${val##[ $TAB]#}
VARIABLES[$var]=$val
;;
- # VARIABLE := value
+ # VARIABLE := value OR VARIABLE ::= value
# Evaluated immediately
- ([[:alnum:]][[:alnum:]_]#[ $TAB]#:=*)
- var=${input%%[ $TAB]#:=*}
+ ([[:alnum:]][[:alnum:]_]#[ $TAB]#:(:|)=*)
+ var=${input%%[ $TAB]#:(:|)=*}
val=${input#*=}
val=${val##[ $TAB]#}
val=$(_make-expandVars $val)
diff --git a/Completion/Unix/Command/_md5sum b/Completion/Unix/Command/_md5sum
index 2351d1abd..c881a4e6d 100644
--- a/Completion/Unix/Command/_md5sum
+++ b/Completion/Unix/Command/_md5sum
@@ -1,10 +1,13 @@
-#compdef md5sum
+#compdef md5sum gmd5sum
_arguments -S \
'(-b --binary)'{-b,--binary}'[read in binary mode]' \
'(-c --check)'{-c,--check}'[read MD5 sums from the FILEs and check them]' \
+ '--tag[create a BSD-style checksum]' \
'(-t --text)'{-t,--text}'[read in text mode]' \
+ '(-q --quiet)'{-q,--quiet}"[don't print OK for each successfully verified file]" \
'--status[no output, status code shows success]' \
+ '--strict[exit non-zero for improperly formatted checksum lines]' \
'(-w --warn)'{-w,--warn}'[warn about improperly formatted checksum lines]' \
'--help[display help and exit]' \
'--version[output version information and exit]' \
diff --git a/Completion/Unix/Command/_metaflac b/Completion/Unix/Command/_metaflac
index 14095e9f9..65b9eb292 100644
--- a/Completion/Unix/Command/_metaflac
+++ b/Completion/Unix/Command/_metaflac
@@ -1,16 +1,13 @@
#compdef metaflac
local _metaflac_opts _metaflac_shorts _metaflac_opers
-typeset -A opt_args
-function _metaflac_tags () {
- echo "\n\nBEEP - $line - BEEP\n\n"
-}
-_metaflac_opts=(
- '--preserve-modtime'
- '--with-filename[prefix output with filename]'
- '--no-filename'
+
+_metaflac_opts=(
+ '--preserve-modtime'
+ '--with-filename[prefix output with filename]'
+ '--no-filename'
'--no-utf8-convert'
- '--dont-use-padding[always rewrite the file]'
+ '--dont-use-padding[always rewrite the file]'
)
_metaflac_shorts=(
'--show-md5sum'
@@ -23,7 +20,7 @@ _metaflac_shorts=(
'--show-bps'
'--show-total-samples'
'--show-vendor-tag'
- '--show-tag=:FLAC tags:_metaflac_tags'
+ '--show-tag=:FLAC tags'
'--remove-tag=:FLAC tags: '
'--remove-first-tag=:FLAC tags: '
'--remove-all-tags'
@@ -51,9 +48,7 @@ _metaflac_opers=(
_arguments "$_metaflac_opts[@]" \
"*:FLAC file:_files -g \*.flac\(-.\)" \
- - "shortcuts" \
+ - "shortcuts" \
"$_metaflac_shorts[@]" \
- - "(operations)" \
- "$_metaflac_opers[@]" \
- && return 0
-
+ - "(operations)" \
+ "$_metaflac_opers[@]"
diff --git a/Completion/Unix/Command/_mkdir b/Completion/Unix/Command/_mkdir
index b5f75198f..f2299f7c7 100644
--- a/Completion/Unix/Command/_mkdir
+++ b/Completion/Unix/Command/_mkdir
@@ -1,33 +1,23 @@
-#compdef mkdir
+#compdef mkdir gmkdir zf_mkdir
-local curcontext="$curcontext" line state \
- args args_zsh args_cmd variant expl ret=1
-typeset -a opt_args
+local curcontext="$curcontext" state line expl args variant ret=1
+typeset -A opt_args
args=(
'(-m --mode)'{-m,--mode=}'[set permission mode]:numeric mode'
'(-p --parents)'{-p,--parents}'[make parent directories as needed]'
- )
-
-args_zsh=('(-)*: :->directories')
-
-args_cmd=(
- '(-v --verbose)'{-v,--verbose}'[print message for each created directory]'
- '(- :)--help[display help information]'
- '(- :)--version[display version information]'
- '*: :->directories'
- )
+ '(-)*: :->directories'
+)
case "$OSTYPE" in
linux*)
- args_cmd=(
+ args+=(
'(-Z --context)'{-Z,--context=}'[set SELinux context]:SELinux context'
- $args_cmd)
- ;;
+ )
+ ;;
esac
-_pick_variant -r variant gnu=gnu zsh='\(eval\)' unix --help
-
+_pick_variant -r variant gnu=gnu zsh='\(eval\)' $OSTYPE --help
# It can still happen that there is a precommand command or builtin in the line.
# In such cases, the variant has to be modified suitably, after further checking
# the variant of the _command_ mkdir.
@@ -44,26 +34,34 @@ _pick_variant -r variant gnu=gnu zsh='\(eval\)' unix --help
# variant=zsh
# fi
-if [[ $variant == zsh ]]; then
- args+=($args_zsh)
-else
- args+=($args_cmd)
-fi
-
-# remove long options?
-[[ $variant != gnu ]] && args=( ${${${args:#(|*\))--*}//--[^ )]#/}/\( #\)/} )
+case $variant in
+ gnu|freebsd*|dragonfly*)
+ args+=(
+ '(-v --verbose)'{-v,--verbose}'[print message for each created directory]'
+ )
+ ;|
+ gnu)
+ args+=(
+ '(- :)--help[display help information]'
+ '(- :)--version[display version information]'
+ )
+ ;;
+ zsh) # remove all options
+ args=( '*: :->directories' )
+ ;;
+ *) # non-GNU: remove long options
+ args=( ${${${args:#(|*\))--*}//--[^ )]#/}/\( #\)/} )
+ ;;
+esac
_arguments -C -s $args && ret=0
case "$state" in
directories)
- if (( $ret )) && [[ ! -prefix - ]] || \
- [[ $variant == zsh && ${#${${words[2,-1]}:#-*}} -gt 0 ]]; then
- _wanted directories expl \
- 'parent directory (alternatively specify name of directory)' \
- _path_files -/ && ret=0 || _message 'name of directory'
- fi
- ;;
+ _wanted directories expl \
+ 'parent directory (alternatively specify name of directory)' \
+ _path_files -/ && ret=0
+ ;;
esac
return ret
diff --git a/Completion/Unix/Command/_module b/Completion/Unix/Command/_module
index c1c9f5c08..060f05b86 100644
--- a/Completion/Unix/Command/_module
+++ b/Completion/Unix/Command/_module
@@ -52,9 +52,9 @@ _module()
)
if (( CURRENT == 1 )); then
- _describe -t commands 'module command' _module_cmds || compadd "$@"
+ _describe -t commands 'module command' _module_cmds
else
- local curcontext="$curcontext"
+ local curcontext="$curcontext" ret
cmd="${${_module_cmds[(r)$words[1]:*]%%:*}}"
# Deal with any aliases
@@ -65,7 +65,7 @@ _module()
show) cmd="display";;
keyword) cmd="apropos";;
esac
-
+
if (( $#cmd ));
then
local update_policy
@@ -132,7 +132,7 @@ _module_available_modules()
{
_arguments -s \
'(-a --append)'{--append,-a}'[append the directories instead of prepending]' \
- '*:directory:_files -/'
+ '*:directory:_files -/'
}
# Completion function for unuse
diff --git a/Completion/Unix/Command/_monotone b/Completion/Unix/Command/_monotone
index 83e18e306..bcaab87f0 100644
--- a/Completion/Unix/Command/_monotone
+++ b/Completion/Unix/Command/_monotone
@@ -1,8 +1,22 @@
#compdef mtn
-local context state line ret
-typeset -a cmds
-typeset -A opt_args
+local -a cmds
+cmds=(
+ automate:automation db:database fdiff:debug fload:debug fmerge:debug
+ get_roster:debug identify:debug rcs_import:debug annotate:informative
+ cat:informative complete:informative diff:informative help:informative
+ list:informative log:informative ls:informative show_conflicts:informative
+ status:informative cert:key+cert chkeypass:key+cert dropkey:key+cert
+ genkey:key+cert trusted:key+cert pull:network push:network serve:network
+ sync:network privkey:packet\ i/o pubkey:packet\ i/o read:packet\ i/o
+ cvs_import:rcs approve:review comment:review disapprove:review tag:review
+ testresult:review checkout:tree co:tree explicit_merge:tree heads:tree
+ merge:tree merge_into_dir:tree migrate_workspace:tree propagate:tree
+ refresh_inodeprints:tree setup:tree set:vars unset:vars add:workspace
+ attr:workspace ci:workspace commit:workspace drop:workspace mv:workspace
+ pivot_root:workspace pluck:workspace rename:workspace revert:workspace
+ rm:workspace update:workspace
+)
_arguments \
'--brief[print a brief version of the normal output]' \
@@ -25,17 +39,5 @@ _arguments \
'--ticker[set ticker style]:ticker style:(count dot none)' \
'--version[print version number, then exit]' \
'(-@ --xargs)'{-@,--xargs}'[insert command line arguments taken from the given file]:file:_files' \
- '*:command:->cmd' && return 0
-
-case "$state" in
- (cmd)
- if (( CURRENT == 2 )); then
- cmds=(automate:automation db:database fdiff:debug fload:debug fmerge:debug get_roster:debug identify:debug rcs_import:debug annotate:informative cat:informative complete:informative diff:informative help:informative list:informative log:informative ls:informative show_conflicts:informative status:informative cert:key+cert chkeypass:key+cert dropkey:key+cert genkey:key+cert trusted:key+cert pull:network push:network serve:network sync:network privkey:packet\ i/o pubkey:packet\ i/o read:packet\ i/o cvs_import:rcs approve:review comment:review disapprove:review tag:review testresult:review checkout:tree co:tree explicit_merge:tree heads:tree merge:tree merge_into_dir:tree migrate_workspace:tree propagate:tree refresh_inodeprints:tree setup:tree set:vars unset:vars add:workspace attr:workspace ci:workspace commit:workspace drop:workspace mv:workspace pivot_root:workspace pluck:workspace rename:workspace revert:workspace rm:workspace update:workspace)
- _describe -t commands 'cmds' cmds && ret=0
- else
- _files
- fi
- ;;
-esac
-
-return ret
+ '1:command: _describe -t commands command cmds' \
+ '*:file:_files'
diff --git a/Completion/Unix/Command/_mosh b/Completion/Unix/Command/_mosh
index dacbd1018..c19f6ebde 100644
--- a/Completion/Unix/Command/_mosh
+++ b/Completion/Unix/Command/_mosh
@@ -1,9 +1,8 @@
#compdef mosh
local curcontext="$curcontext" state line
-local -a suf
-_arguments \
+_arguments -C \
'(-)--help[display help information]' \
'(-)--version[display version information]' \
"--no-init[don't set terminal init string]" \
diff --git a/Completion/Unix/Command/_mount b/Completion/Unix/Command/_mount
index 04282225f..a3b58bb87 100644
--- a/Completion/Unix/Command/_mount
+++ b/Completion/Unix/Command/_mount
@@ -959,27 +959,9 @@ udevordir)
esac
local MATCH MBEGIN MEND
- # "Mummy, why is mount point matching full of squiggles?"
- #
- # "Well, dear, the clever people who wrote Linux decided that some
- # funny characters that might confuse programmes looking at the names
- # would be encoded as octal escapes, like for example \040 for space.
- # The clever people who wrote zsh decided that nothing would
- # ever be quite as simple as it should be, so to substitute octal
- # escapes everywhere in a string, even though the shell understands
- # them natively in print escapes, needs some hackery where you match
- # the octal number using the numeric closure syntax introduced after
- # 4.3.4, then reinput the number in a standard math mode format as 8#OOO,
- # and turn that into a character using the (#) parameter flag."
- #
- # "Mummy, why is nothing ever quite as simple as it should be?"
- #
- # "Well, dear, if it was then the clever people who write programmes would
- # have been replaced by intelligent monkeys and then they'd be out
- # of working roaming the streets, and we wouldn't want that, would we?"
- mp_tmp=("${(@q)mp_tmp//(#m)\\[0-7](#c3)/${(#)$(( 8#${MATCH[2,-1]} ))}}")
- dpath_tmp=( "${(@Mq)dev_tmp:#/*}" )
- dev_tmp=( "${(@q)dev_tmp:#/*}" )
+ mp_tmp=("${(@qg::)mp_tmp}")
+ dpath_tmp=( "${(@Mqg::)dev_tmp:#/*}" )
+ dev_tmp=( "${(@qg::)dev_tmp:#/*}" )
_alternative \
'device-labels:device label:compadd -a dev_tmp' \
diff --git a/Completion/Unix/Command/_mpc b/Completion/Unix/Command/_mpc
index 12707677f..11eab8463 100644
--- a/Completion/Unix/Command/_mpc
+++ b/Completion/Unix/Command/_mpc
@@ -68,21 +68,21 @@ _mpc_command() {
)
if (( CURRENT == 1 )); then
- _describe -t command "mpc commands" mpc_cmds
+ _describe -t commands "mpc command" mpc_cmds
else
- local curcontext="$curcontext"
+ local cmd=$words[1]
+ local curcontext="${curcontext%:*}:mpc-${cmd}" ret=1
+ if ! _call_function ret _mpc_$cmd; then
+ _default && ret=0
+ fi
+ return ret
fi
-
- local cmd=$words[1]
-
- local curcontext="${curcontext%:*}:mpc-${cmd}"
- _call_function ret _mpc_$cmd
}
_mpc_helper_bool() {
local expl states
states=(on off yes no 1 0 true false)
- _wanted states expl boolean compadd $expl -a states
+ _wanted states expl boolean compadd -a states
}
(( $+functions[_mpc_helper_songnumbers] )) ||
@@ -100,7 +100,7 @@ _mpc_helper_songnumbers() {
NM="$compstate[nmatches]"
fi
- out=("${(@f)$(_call_program song-numbers mpc $foo playlist 2>/dev/null)}")
+ out=("${(@f)$(_call_program song-numbers mpc $foo playlist)}")
out=("${(@M)out[@]:#${~MATCH}}")
sn=("${(@)${(@M)out}//(#b)(#s)(\#|[ >]#)([0-9]#)*/$match[2]}")
diff --git a/Completion/Unix/Command/_mtr b/Completion/Unix/Command/_mtr
index f4df5b3cf..5eda9bc1a 100644
--- a/Completion/Unix/Command/_mtr
+++ b/Completion/Unix/Command/_mtr
@@ -4,13 +4,19 @@ _arguments -C \
'(-h --help)'{-h,--help}'[help]' \
'(-v --version)'{-v,--version}'[version]' \
'(-r --report)'{-r,--report}'[report mode]' \
+ '(-w --report-wide)'{-w,--report-wide}'[wide report mode\: do not truncate hostnames]' \
'(-c --report-cycles)'{-c,--report-cycles}'[report cycles]:number of pings' \
- '(-p --psize)'{-p,--psize}'[packet size]:number of bytes' \
+ '(-s --psize)'{-s,--psize}'[packet size]:number of bytes' \
'(-t --curses)'{-t,--curses}'[curses UI]' \
+ '(-e --mpls)'{-e,--mpls}'[display ICMP MPLS information]' \
+ '(-o --order)'{-o,--order}'[order output fields]:fields order' \
'(-n --no-dns)'{-n,--no-dns}'[no DNS lookups]' \
'(-g --gtk)'{-g,--gtk}'[GTK+ UI]' \
- '(-s --split)'{-s,--split}'[output for a split-user interface]' \
+ '(-p --split)'{-p,--split}'[output for a split-user interface]' \
'(-l --raw)'{-l,--raw}'[raw output format]' \
'(-a --address)'{-a,--address}'[source address]:source IP:_hosts' \
'(-i --interval)'{-i,--interval}'[ping interval]:number of seconds' \
+ '-u[use UDP instead of ICMP echo]' \
+ '-4[use IPv4 only]' \
+ '-6[use IPv6 only]' \
':destination host:_hosts'
diff --git a/Completion/Unix/Command/_mysqldiff b/Completion/Unix/Command/_mysqldiff
index 094694d32..4b46c86df 100644
--- a/Completion/Unix/Command/_mysqldiff
+++ b/Completion/Unix/Command/_mysqldiff
@@ -1,8 +1,5 @@
#compdef mysqldiff
-local curcontext="$curcontext" state line expl
-typeset -A opt_args
-
_mysqldiff () {
_arguments -s \
{-h{,1,2},--host{,1,2}=}':server hostname:_mysql_hosts' \
diff --git a/Completion/Unix/Command/_netcat b/Completion/Unix/Command/_netcat
index 396fc8e09..4e4006b30 100644
--- a/Completion/Unix/Command/_netcat
+++ b/Completion/Unix/Command/_netcat
@@ -1,11 +1,10 @@
#compdef nc netcat
-local curcontext="$curcontext" state line expl
-typeset -A opt_args
-
# handle name clash with the nedit client
-[[ $service = nc ]] && ! _pick_variant netcat=connect nedit -h &&
- _nedit && return
+if [[ $service = nc ]] && ! _pick_variant netcat=connect nedit -h; then
+ _nedit
+ return
+fi
if (( ! $+_nc_args )); then
local help="$(_call_program options $words[1] -h < /dev/null 2>&1)"
@@ -14,17 +13,17 @@ if (( ! $+_nc_args )); then
'*-e prog*' '-e+[program to exec after connect]:prog:_command_names -e'
'*-g gateway*' '-g+[source-routing hop point]:gateway:_hosts'
'*-G num*' '-G[source-routing pointer: 4, 8, 12]'
- '*-i secs*' '-i+[delay interval for lines sent or ports scanned]:secs:'
+ '*-i secs*' '-i+[delay interval for lines sent or ports scanned]:delay (secs)'
'*-l*' '-l[listen mode]'
'*-n*' '-n[numeric-only IP addresses, no DNS]'
'*-o file*' '-o+[hex dump of traffic]:file:_files'
'*-p port*' '-p+[local port number]:port:_ports'
'*-r*' '-r[randomize local and remote ports]'
- '*-q secs*' '-q+[quit after EOF on stdin and delay of secs]:secs:'
+ '*-q secs*' '-q+[quit after EOF on stdin and delay of secs]:delay (secs)'
'*-t*' '-t[answer TELNET negotiation]'
'*-u*' '-u[UDP mode]'
'*-v*' '-v[verbose]'
- '*-w secs*' '-w+[timeout for connects and final net reads]:secs:'
+ '*-w secs*' '-w+[timeout for connects and final net reads]:timeout (secs)'
'*-z*' '-z[zero-I/O mode]'
'*-x*' '-x'
'*-b*' '-b[allow broadcasts]'
@@ -32,7 +31,7 @@ if (( ! $+_nc_args )); then
_nc_args=($optionmap[(K)"$help"])
fi
-_arguments -C -s \
+_arguments -s \
"$_nc_args[@]" \
':host:_hosts' \
- ':port:_ports' && return 0
+ ':port:_ports'
diff --git a/Completion/Unix/Command/_nl b/Completion/Unix/Command/_nl
new file mode 100644
index 000000000..b3876dc65
--- /dev/null
+++ b/Completion/Unix/Command/_nl
@@ -0,0 +1,40 @@
+#compdef nl gnl
+
+local curcontext="$curcontext" state line args ret=1
+
+args=(
+ '(-b --body-numbering)'{-b+,--body-numbering=}'[specify style for body lines]:style:->styles'
+ '(-d --section-delimiter)'{-d+,--section-delimiter=}'[separate logical pages with specified delimiter]:delimiter'
+ '(-f --footer-numbering)'{-f+,--footer-numbering=}'[specify style for footer lines]:style:->styles'
+ '(-h --header-numbering)'{-h+,--header-numbering=}'[specify style for header lines]:style:->styles'
+ '(-i --line-increment)'{-i+,--line-increment=}'[line number increment at each line]:increment'
+ '(-l --join-blank-lines)'{-l+,--join-blank-lines=}'[count consecutive empty lines as one]:number'
+ '(-n --number-format)'{-n+,--number-format=}'[specify format for line numbers]:format:((ln\:left\ justified rn\:right\ justified rz\:right\ justified\ with\ leading\ zeroes))'
+ '(-p --no-renumber)'{-p,--no-renumber}"[don't reset line numbers at logical pages]"
+ '(-s --number-separator)'{-s+,--number-separator=}'[add specified string after line numbers]:string'
+ '(-v --starting-line-number)'{-v+,--starting-line-number=}'[specify first line number on each logical page]:initial number'
+ '(-w --number-width)'{-w+,--number-width=}'[specify number of columns for line numbers]:columns'
+)
+
+if _pick_variant gnu=GNU unix --version; then
+ args+=(
+ '(- *)--help[display help information]'
+ '(- *)--version[display version information]'
+ )
+else
+ args=( ${(R)args:#(|\*)(|\(*\))--*} ) # remove long options
+fi
+
+_arguments -C -s $args '*:file:_files' && ret=0
+
+if [[ -n $state ]]; then
+ if compset -P p; then
+ _message -e regex 'regular expression'
+ else
+ _describe -t styles style '( p:number\ only\ lines\ matching\ regex )' -S '' -- '(
+ a:number\ all\ lines
+ t:number\ only\ non-empty\ lines
+ n:no\ line\ numbering
+ )'
+ fi
+fi || return ret
diff --git a/Completion/Unix/Command/_nm b/Completion/Unix/Command/_nm
index 6c95a0d85..80136329d 100644
--- a/Completion/Unix/Command/_nm
+++ b/Completion/Unix/Command/_nm
@@ -1,12 +1,12 @@
-#compdef nm
+#compdef nm eu-nm
-local args files
+local args files variant
_nm_object_file() {
- [[ -x $REPLY || $REPLY = *.([ao]|so) ]]
+ [[ -x $REPLY || $REPLY = *.([ao]|so|elf) ]]
}
-files="*:object file:_path_files -g '*(-.e:_nm_object_file:)'"
+files="*:object file:_files -g '*(-.e:_nm_object_file:)'"
args=(
'(-A -o --print-file-name)'{-A,-o,--print-file-name}'[print name of input file on each line]'
'(--demangle)-C[decode symbol names]'
@@ -15,7 +15,7 @@ args=(
'(-t --radix -o -x)'{-t,--radix}'[specify radix for numeric values]:radix:((d\:decimal o\:octal x\:hexadecimal))'
)
-if _pick_variant gnu=GNU unix -V; then
+if _pick_variant -r variant binutils=GNU elftoolchain=elftoolchain elfutils=elfutils unix -V; then
compset -P '@' && files='*:options file:_files'
args+=(
'(- *)--help[display help information]'
@@ -24,22 +24,47 @@ if _pick_variant gnu=GNU unix -V; then
'(-C --no-demangle)--demangle=-[decode symbol names]::style:(auto gnu lucid arm hp edg gnu-v3 java gnat)'
"(-C --demangle)--no-demangle[don't decode symbol names]"
'(-u --undefined-only)--defined-only[display only defined symbols]'
- '(-f --format -P)'{-f+,--format=}'[specify output format]:format:(bsd sysv posix)'
- '(-l --line-numbers)'{-l,--line-numbers}'[display source file and line numbers from debug information]'
- '(-n --numeric-sort -p --no-sort --size-sort)'{-n,--numeric-sort}'[sort symbols numerically by address]'
+ '(-f --format -P)--format=[specify output format]:format:(bsd sysv posix)'
+ '(-n --numeric-sort -p --no-sort --size-sort -v)'{-n,--numeric-sort}'[sort symbols numerically by address]'
'(-p --no-sort -n --numeric-sort -r -P --reverse-sort --size-sort)'{-p,--no-sort}'[do not sort symbols]'
'(-P --portability -B -f --format)'{-P,--portability}'[same as --format=posix]'
- '(-r --reverse-sort -p --no-sort --size-sort)'{-r,--reverse-sort}'[reverse sort order]'
- '--plugin[load specified plugin]:plugin'
+ '(-r --reverse-sort -p --no-sort --size-sort -v)'{-r,--reverse-sort}'[reverse sort order]'
'(-u --undefined-only --defined-only)'{-u,--undefined-only}'[display only undefined symbols]'
- "--target=[target object format]:targets:(${${(@M)${(f)$(_call_program targets nm --help)}:#*supported targets:*}##*: })"
'(-a --debug-syms)'{-a,--debug-syms}'[display debugger-only symbols]'
'(-S --print-size)'{-S,--print-size}'[print size of defined symbols]'
'(-s --print-armap)'{-s,--print-armap}'[include index for symbols from archive members]'
- '(-p --no-sort -n --numeric-sort -r)--size-sort[sort symbols by size]'
- '--special-syms[include special symbols in the output]'
- '--synthetic[display synthetic symbols as well]'
+ '(-p --no-sort -n --numeric-sort -r -v)--size-sort[sort symbols by size]'
)
+ case $variant in
+ elftoolchain|binutils)
+ args+=(
+ '(-l --line-numbers)'{-l,--line-numbers}'[display source file and line numbers from debug information]'
+ )
+ ;|
+ elftoolchain)
+ args=( ${args:#*--(portability|extern-only)\[*}
+ '(- *)-h[display help information]'
+ '(-t -x)-o[print values in octal]'
+ '(-t -o)-x[print values in hexadecimal]'
+ '(--size-sort)-v[sort output by value]'
+ )
+ ;;
+ elfutils)
+ args+=(
+ '--mark-special[mark special symbols]'
+ '--color=[use color in output]:color:(always auto never)'
+ )
+ ;;
+ binutils)
+ args+=(
+ '(-f --format -P)-f+[specify output format]:format:(bsd sysv posix)'
+ '--plugin[load specified plugin]:plugin'
+ '--special-syms[include special symbols in the output]'
+ '--synthetic[display synthetic symbols as well]'
+ "--target=[target object format]:targets:(${${(@M)${(f)$(_call_program targets nm --help)}:#*supported targets:*}##*: })"
+ )
+ ;;
+ esac
else
# following flags are accurate for Solaris
args=( ${args:#(|*\)(\*|))-[o-]*}
diff --git a/Completion/Unix/Command/_notmuch b/Completion/Unix/Command/_notmuch
index b576d2b29..d6cc58deb 100644
--- a/Completion/Unix/Command/_notmuch
+++ b/Completion/Unix/Command/_notmuch
@@ -57,12 +57,15 @@ _notmuch_search()
_notmuch()
{
+ local ret=1
if (( CURRENT > 2 )) ; then
local cmd=${words[2]}
curcontext="${curcontext%:*:*}:notmuch-$cmd"
(( CURRENT-- ))
shift words
- _call_function ret _notmuch_$cmd
+ if ! _call_function ret _notmuch_$cmd; then
+ _default && ret=0
+ fi
return ret
else
_notmuch_commands
diff --git a/Completion/Unix/Command/_od b/Completion/Unix/Command/_od
index d542597e0..db75b3f96 100644
--- a/Completion/Unix/Command/_od
+++ b/Completion/Unix/Command/_od
@@ -1,6 +1,6 @@
-#compdef od
+#compdef od god
-local context state state_descr line args ret=1
+local curcontext="$curcontext" state state_descr line args ret=1
local -A opt_args
args=(
@@ -19,13 +19,14 @@ args=(
{-l,-I,-L}'[output decimal longs (-t dL)]'
{-o,-B}'[output octal shorts (-t o2)]'
'-s[output decimal shorts (-t d2)]'
- '*:files:_files'
)
if _pick_variant gnu=GNU unix --version; then
# -h -B -I and -L are obsolescent and undocumented
args=( ${(R)args:#(|\*)(|\(*\))-[hBIL]*} )
args+=(
+ '--traditional'
+ '--endian=[swap input bytes]:endianess:(big little)'
{-S+,--strings=-}'[output strings of at least specfied bytes long]:length'
{-w-,--width=-}'[output specified bytes per line]:bytes'
'(- : *)--help[display help and exit]'
@@ -34,22 +35,33 @@ if _pick_variant gnu=GNU unix --version; then
else
args=( ${(R)args:#(|\*)(|\(*\))--*} ) # remove long options
case "$OSTYPE" in
- (darwin*|freebsd*|dragonfly*|openbsd*)
+ darwin*|freebsd*|dragonfly*|openbsd*)
args+=(
- '-D[output unsigned decimal ints (-t u4)]'
+ '-D[output unsigned decimal integers (-t u4)]'
{-e,-F}'[output double-precision floats (-t fD)]'
{-H,-X}'[output hexadecimal ints (-t x4)]'
'-O[output octal ints (-t o4)]'
)
- ;;
+ ;;
+ solaris*)
+ args=(
+ ${(M)args:#(|\*)(|\(*\))-[AjNtvbcdfosx]*}
+ '-C[output all printable characters and use C-style escapes]'
+ '-D[output unsigned decimal long words (-t u4)]'
+ '-F[output double-precision floats (-t f8)]'
+ '-O[output octal ints (-t o4)]'
+ '-S[output decimal ints (-t d4)]'
+ '-X[output hexadecimal ints (-t x4)]'
+ )
+ ;;
(*)
# POSIX options only
args=( ${(M)args:#(|\*)(|\(*\))-[AjNtvbcdosx]*} )
- ;;
+ ;;
esac
fi
-_arguments -s -S : "$args[@]" && return 0
+_arguments -C -s -S : "$args[@]" '*:files:_files' && return 0
case "$state" in
(format)
diff --git a/Completion/Unix/Command/_patch b/Completion/Unix/Command/_patch
index add436702..c0df00c00 100644
--- a/Completion/Unix/Command/_patch
+++ b/Completion/Unix/Command/_patch
@@ -1,7 +1,7 @@
-#compdef patch
+#compdef patch gpatch
if (( ! $+_patch_args )); then
- local help="$(LC_ALL=C patch --help 2>&1)"
+ local help="$(LC_ALL=C $words[1] --help 2>&1)"
local -A optionmap
local arg
local comp_p='compadd "$expl[@]" -S0 -r "1-9" - ""'
diff --git a/Completion/Unix/Command/_pgrep b/Completion/Unix/Command/_pgrep
index 95d0ea284..3af55a379 100644
--- a/Completion/Unix/Command/_pgrep
+++ b/Completion/Unix/Command/_pgrep
@@ -1,6 +1,6 @@
#compdef pgrep pkill
-local context state line ret=1 expl
+local curcontext="$curcontext" state line ret=1 expl
typeset -A opt_args
typeset -a arguments
@@ -66,7 +66,7 @@ esac
arguments=( ${(M)arguments:#(|\*)(|\(*\))-[$optchars]*}
'*:process name:->pname')
-_arguments -s -w $arguments && ret=0
+_arguments -C -s -w $arguments && ret=0
case $state in
(tty)
diff --git a/Completion/Unix/Command/_ping b/Completion/Unix/Command/_ping
index e59f6fa9f..a1a50e11f 100644
--- a/Completion/Unix/Command/_ping
+++ b/Completion/Unix/Command/_ping
@@ -33,31 +33,37 @@ if _pick_variant iputils=iputils unix -V; then
else
-# FreeBSD 4.11
-
_arguments \
'-A[audible for no packet]' \
- '-Q[somewhat quiet]' \
- '-R[record route]' \
'-a[audible for each packet]' \
+ '-c:count' \
+ "-D[set the don't fragment bit]" \
'-d[set SO_DEBUG on the socket]' \
'-f[flood ping]' \
- '-n[numeric output only]' \
- '-q[quiet]' \
- '-r[bypass normal routing tables]' \
- '-v[verbose]' \
- '-c:count' \
+ '-G[specify maximum size for ICMP payload for sweeping pings]:size' \
+ '-g[specify minimum size for ICMP payload for sweeping pings]:size [0]' \
+ '-h[specify size increment for ICMP payload for sweeping pings]:size [1]' \
'-i:wait seconds' \
+ '-I[source interface for multicast packets]:iface:_net_interfaces' \
+ '-L[suppress loopback of multicast packets]' \
'-l:preload number' \
+ '-M:icmp:(mask time)' \
'-m:ttl' \
- '-p:padding pattern' \
+ '-n[numeric output only]' \
+ '-o[exit after receiving one packet]' \
'-P:IPsec policy' \
+ '-p:padding pattern' \
+ '-Q[somewhat quiet]' \
+ '-q[quiet]' \
+ '-R[record route]' \
+ '-r[bypass normal routing tables]' \
+ '-S:source address' \
'-s:packet size in bytes' \
- '-S:src addr' \
- '-t:timeout in seconds' \
- '-L[suppress loopback of multicast packets]' \
- '-I:iface:_net_interfaces' \
'-T:ttl for multicasted packets' \
+ '-t:timeout in seconds' \
+ '-v[verbose]' \
+ '-W:wait time (ms)' \
+ '-z:type of service' \
':host:_hosts'
fi
diff --git a/Completion/Unix/Command/_pkg-config b/Completion/Unix/Command/_pkg-config
index 48b788a1b..e44b36897 100644
--- a/Completion/Unix/Command/_pkg-config
+++ b/Completion/Unix/Command/_pkg-config
@@ -1,6 +1,6 @@
#compdef pkg-config
-local arguments packages curcontext="$curcontext" stat line
+local arguments packages curcontext="$curcontext" state line ret=1
declare -A opt_args
arguments=(
@@ -11,31 +11,33 @@ arguments=(
"--print-errors[cause errors to be printed]"
"--silence-errors[prevent the printing of errors]"
"--errors-to-stdout[print errors to stdout rather than stderr]"
- "--cflags[prints the preprocessor and compile flags]"
+ "--cflags[print the preprocessor and compiler flags]"
"--cflags-only-I[output -I flags only]"
"--cflags-only-other[output cflags not covered by the cflags-only-I option]"
"--debug[show verbose debug information]"
- "--libs[prints the link flags]"
- "--libs-only-L[prints the -L and -R parts of \"--libs\"]"
- "--libs-only-l[prints the -l part of \"--libs\"]"
+ "--libs[print the link flags]"
+ "--libs-only-L[print the -L and -R parts of \"--libs\"]"
+ "--libs-only-l[print the -l part of \"--libs\"]"
"--libs-only-other[output other libs]"
"--list-all[list all known packages]"
"--variable=[return the value of the specified variable]:variable"
"--define-variable=[set the global value for a variable]:name value pair"
- "--uninstalled[return successfully if any \"-uninstalled\" packages are being used and fails otherwise]"
- "--exists[tests whether the package exists or not]"
+ "--uninstalled[return success if any \"-uninstalled\" packages are being used]"
+ "--exists[test whether the package exists or not]"
"--atleast-version=[test whether the version is at least that of the specified value]:least value"
"--exact-version=[test whether the version is exactly that of the specified value]:exact value"
"--max-version=[test whether the version is no greater than some specific value]:max version"
# "--msvc-syntax[output linker flags in a form compatible with MSVC++ (Windows only)]"
# "--dont-define-prefix[disables automatic overiding of the variable \"prefix\" (Windows only)]"
# "--prefix-variable=[set the name of the variable \"prefix\" (Windows only)]:prefix value"
- "*:package name:->package"
+ "*: :->packages"
)
-_arguments -C $arguments
+_arguments -C $arguments && ret=0
if [[ -n $state ]] ; then
- packages=( ${(f)"$((pkg-config --list-all | cut -d' ' -f1) 2>/dev/null)"} )
- compadd -a - packages
+ packages=( ${${(f)"$(_call_program packages pkg-config --list-all)"}%% *} )
+ _wanted packages expl 'package' compadd -a - packages && ret=0
fi
+
+return ret
diff --git a/Completion/Unix/Command/_prove b/Completion/Unix/Command/_prove
index 75e83c360..1f21423e6 100644
--- a/Completion/Unix/Command/_prove
+++ b/Completion/Unix/Command/_prove
@@ -45,7 +45,7 @@ _arguments \
'--source=[load or configure a SourceHandler]:source:' \
{-a,--archive}'[store output in archive file]:file:_files' \
{-j,--jobs}'[run N jobs in parallel]:jobs:' \
- '*--state=[control persistent state]:state:' \
+ '*--state=[control persistent state]: :_values -s , state last failed passed all hot todo slow fast new old fresh save' \
'--rc=[custom rcfile]:file:_files' \
- '*:file or directory:_files' \
- && return 0
+ '*--rules=[limit tests run (or not) in parallel]:rules' \
+ '*:file or directory:_files'
diff --git a/Completion/Unix/Command/_ps b/Completion/Unix/Command/_ps
new file mode 100644
index 000000000..925f48390
--- /dev/null
+++ b/Completion/Unix/Command/_ps
@@ -0,0 +1,188 @@
+#compdef ps
+
+_ps_props() {
+ local opts
+
+ if [[ $1 = -s ]]; then
+ shift
+ compset -P '[+-]' || _describe -t modifiers modifier \
+ '( +:ascending\ order -:descending\ order )' -S ''
+ fi
+
+ case $OSTYPE in
+ linux-gnu) opts=( ${${(f)"$(_call_program properties $words[1] L)"}%% *} ) ;;
+ freebsd*) opts=( $(_call_program properties $words[1] L) ) ;;
+ solaris*) opts=( ${=${(f)"$(_call_program properties $words[1] - 2>&1)"}[-3,-1]} ) ;;
+ esac
+
+ compadd "$@" -a opts
+}
+
+local curcontext="$curcontext" state line expl ret=1
+local short long
+local -a args bsd bsdarg pids
+local -A equivs
+
+args=(
+ '-a[select processes with tty except session leaders]'
+ {-A,-e}'[select every process]'
+ '-d[select all processes except session leaders]'
+ '*-p+[select processes by ID]:process ID:_sequence -s , _pids'
+ '*-G+[select processes by real group]:group:_sequence -s , _groups'
+ '*-g+[select processes by effective group or session]:group:_sequence -s , _groups'
+ '*-s+[select processes by session leaders]:session leader:_sequence -s , _pids'
+ '*-t+[select processes by attached terminal]:tty:_sequence -s , compadd - /dev/pts/<->(N\:s/\\/dev\\//) /dev/tty*(N\:t)'
+ '*-u+[select processes by effective user]:user:_sequence -s , _users'
+ '*-U+[select processes by real user]:user:_sequence -s , _users'
+ '-o+[specify output format]:property:_sequence -s , _ps_props -'
+
+ '-c[show scheduler properties]'
+ '-f[full listing]'
+ '-j[show session ID and process group ID]'
+ '-l[long listing]'
+ '-L[show information about each light weight process]'
+ '-y[show RSS in place of ADDR (used with -l)]'
+)
+
+bsd=(
+ 'a[include processes belonging to other users]'
+ 'e[show environment after command]'
+ '(j s u v X)l[output in long format]'
+ '(l s u v X)j[output in job control format]'
+ 'x[include processes with no controlling terminal]'
+ '(j l s v X)u[output in resource usage format]'
+ '(j l s u X)v[output in virtual memory format]'
+ '*w[wide output]'
+ 'H[show threads as if they were processes]'
+ 'L[display all format specifiers]'
+ 'S[include child process data with the parent]'
+ 'T[select processes attached to current terminal]'
+ 'Z[show security data]'
+)
+bsdarg=(
+ '*p[select processes by ID]'
+ '*t[select processes by attached terminal]'
+ '*U[select processes by effective user]'
+ 'O[specify additional output fields]'
+ 'o[specify output format]'
+ 'N[set namelist file for WCHAN display]'
+)
+
+case $OSTYPE in
+ solaris2.<11->)
+ args+=(
+ '-h[select processes homed to the specified lgrp]:lgrp list'
+ '-H[show home lgroup of the process]'
+ )
+ ;|
+ solaris*)
+ args+=(
+ '-P[show processor to which the process or lwp is bound]'
+ '*-z[select processes by zone]:zone list:_sequence _zones'
+ '-Z[show zone with which process is associated]'
+ )
+ ;;
+ darwin*|dragonfly*|freebsd*|netbsd*|openbsd*)
+ bsd+=(
+ 'A[select every process]'
+ 'C[ignore resident time for CPU percentage]'
+ 'c[show just executable name for command]'
+ 'h[repeat header lines, one per page of output]'
+ '(r)m[sort by memory usage]'
+ '(m)r[sort by CPU usage]'
+ )
+ bsdarg+=(
+ 'M[extract values from specified core]'
+ )
+ ;|
+ linux-gnu|netbsd*) bsdarg+=( 'k[specify sort order]' ) ;|
+ darwin*|freebsd*) bsdarg+=( 'G[select processes by real group]' ) ;|
+ freebsd*)
+ bsd+=(
+ 'd[show process hierarchy]'
+ 'f[show command and environment for swapped out processes]'
+ '*J[select processes by jail ID]'
+ )
+ ;;
+ netbsd*) bsd+=( '(j l u v)s[output in thread format]' ) ;;
+ openbsd*)
+ bsd+=(
+ 'k[display information about kernel threads]'
+ )
+ bsdarg+=( 'W[extract swap information from the specified file]' )
+ ;;
+ linux-gnu)
+ args+=(
+ '-O+[specify additional output fields]:property:_sequence -s , _ps_props -'
+ '(-N --deselect)'{-N,--deselect}'[negate selection: all processes except those selected]'
+ '*-C[select processes by command name]:command:_sequence -s , _command_names -e'
+ '*--ppid[select processes by parent process ID]:parent process:_sequence -S , _pids'
+ '(-f)-F[extra full format listing]'
+ '--context[show SELinux security context format]'
+ '-M[show security data]'
+ '(--forest -H)'{--forest,-H}'[show process hierarchy]'
+ '--headers[repeat header lines, one per page of output]'
+ '(--cols --columns --width)'{--cols,--columns,--width}'[set screen width]:width'
+ '(--lines --rows)'{--lines,--rows}'[set screen height]'
+ '--cumulative[include child process data with the parent]'
+ '-n[set namelist file for WCHAN display]:file:_files'
+ '(--no-headers --no-heading)'{--no-headers,--no-heading}'[suppress headers]'
+ '--sort=[specify sort order]:order:_ps_props -s'
+ '-w[wide output]'
+ '-m[show threads after processes]'
+ '-T[show threads, with SPID column]'
+ '-Z[show security context format (SELinux)]'
+ '(- *)--help[display help information]::subject:(simple list output threads misc all)'
+ '(- *)--info[display debugging information]'
+ '(- *)'{-V,--version}'[display version information]'
+ )
+ equivs=( G Group g group p pid s sid t tty U User u user o format )
+ for short long in ${(kv)equivs}; do
+ args+=( ${${(M)args:#(\*|)-$short*}/$short+/-$long=} )
+ done
+ bsd+=(
+ 'c[show true command name]'
+ 'f[show process hierarchy]'
+ 'h[suppress header]'
+ 'm[show threads after processes]'
+ 'n[numeric output for WCHAN and USER]'
+ 'r[select running processes]'
+ '(j l u v X)s[output in signal format]'
+ 'V[display version information]'
+ '(j l s u v)X[output in register format]'
+ )
+ ;;
+esac
+
+if (( CURRENT > 1 )) && [[ $OSTYPE != solaris* || ( $OSTYPE = linux-gnu && $words[CURRENT-1] != -* ) ]]; then
+ case $words[CURRENT-1] in
+ *k)
+ _wanted -C option-k-1 properties expl 'property' _sequence -s , _ps_props -s - && return
+ ;;
+ *G) _sequence -s , _groups && return ;;
+ *J) _sequence -s , _jails && return ;;
+ *[MNW]) _files && return ;;
+ *t)
+ _wanted -C option-t-1 ttys expl tty _sequence -s , \
+ compadd - /dev/pts/<->(N\:s/\\/dev\\//) /dev/tty*(N\:t) && return
+ ;;
+ *p) _wanted -C option-p-1 processes expl 'process ID' _sequence -s , _pids && return;;
+ *U) _wanted -C option-U-1 users expl user _sequence -s , _users && return ;;
+ *[oO]) _wanted -C "option-${words[CURRENT-1][-1]}-1" properties \
+ expl 'property' _sequence -s , _ps_props - && return ;;
+ esac
+fi
+
+if [[ $OSTYPE = (*bsd*|darwin*|dragonfly*) ]]; then
+ compset -P - && pids=1
+else
+ _arguments -C -s $args '*:: :->rest' && ret=0
+ [[ -z "$state" || $OSTYPE = solaris* ]] && return ret
+fi
+
+_values -s '' -S ' ' 'options' $bsd && ret=0
+_values -S ' ' 'options' $bsdarg && ret=0
+if [[ -z $pids ]]; then
+ _pids && compstate[insert]=
+fi
+return ret
diff --git a/Completion/Unix/Command/_pydoc b/Completion/Unix/Command/_pydoc
index 92a01a76f..677c96ad6 100644
--- a/Completion/Unix/Command/_pydoc
+++ b/Completion/Unix/Command/_pydoc
@@ -1,16 +1,34 @@
-#compdef pydoc
+#compdef -P pydoc[0-9.]#
-local context state line
+local curcontext=$curcontext state state_descr line ret=1
typeset -A opt_args
+local -a args
-_arguments \
- '-k[keyword]:keyword:' \
- '-p[port]:port:_ports' \
- '-g[gui]' \
- '-w[write out HTML]:file or dir:_files' \
- ':keyword, topic, module, package, or dotted reference:->lookup' && return 0
+args=(
+ '(- *)-k[search keyword]:keyword'
+ '(-k -g -w *)-p[start web server on specified port]:port number'
+ '(-)-w[write out HTML in current directory]'
+ '(-)*: :->lookup'
+)
-_alternative \
- 'keywords:keyword:compadd ${=${${(f)"$(pydoc keywords)"}[2,-1]}}' \
- 'topics:topic:compadd ${=${${(f)"$(pydoc topics)"}[2,-1]}}' \
- 'modules:module:'
+if _pick_variant pydoc3='pydoc3 -b' pydoc2 -h; then
+ args+=( '(-k -w *)-b[start server and open browser]' )
+else
+ args+=( '(- *)-g[start gui]' )
+fi
+
+_arguments -C : $args && return 0
+
+case $state in
+(lookup)
+ if [[ $words[CURRENT] = */* ]]; then
+ _files && ret=0
+ else
+ _alternative \
+ 'keywords:keyword:compadd ${=${${(f)"$(_call_program keywords $words[1] keywords)"}[2,-1]}}' \
+ 'topics:topic:compadd ${=${${(f)"$(_call_program topics $words[1] topics)"}[2,-1]}}' \
+ 'modules:module:_python_modules' && ret=0
+ fi
+esac
+
+return ret
diff --git a/Completion/Unix/Command/_python b/Completion/Unix/Command/_python
index 8e32bdf55..dedb9ceda 100644
--- a/Completion/Unix/Command/_python
+++ b/Completion/Unix/Command/_python
@@ -1,11 +1,10 @@
-#compdef python python2 python2.4 python2.5 python2.6 python2.7 python3.0 python3.1 python3.2 python3.3 python3.4
+#compdef -P python[0-9.]#
# Python 2.7
# Python 3.4
-local curcontext="$curcontext" state line expl
+local curcontext="$curcontext" state state_descr line
typeset -A opt_args
-
local -a args
if _pick_variant python3=Python\ 3 python2 --version; then
@@ -32,7 +31,7 @@ _arguments -C -s -S "$args[@]" \
'-E[ignore PYTHON* environment variables (such as PYTHONPATH)]' \
'(1 * -)-h[display help information]' \
'-i[inspect interactively after running script]' \
- '(1 -)-m[run library module as a script (terminates option list)]:module:->modules' \
+ '(1 -)-m[run library module as a script (terminates option list)]:module:_python_modules' \
'-O[optimize generated bytecode slightly]' \
'-OO[remove doc-strings in addition to the -O optimizations]' \
"-s[don't add user site directory to sys.path]" \
@@ -46,14 +45,6 @@ _arguments -C -s -S "$args[@]" \
'*::script argument:= ->normal' && return
case "$state" in
- modules)
- local -a modules
- modules=(
- ${${=${(f)"$(_call_program modules $words[1] -c \
- 'from\ pydoc\ import\ help\;\ help\(\"modules\"\)')"}[2,-3]}:#\(package\)}
- )
- _wanted modules expl module compadd -a modules && return
- ;;
normal)
if [[ -z "$opt_args[(I)-(c|m)]" ]]; then
shift words
diff --git a/Completion/Unix/Command/_rar b/Completion/Unix/Command/_rar
index 1e3a26166..e2081f6e7 100644
--- a/Completion/Unix/Command/_rar
+++ b/Completion/Unix/Command/_rar
@@ -38,7 +38,7 @@ common=(
case $service in
unrar)
if (( CURRENT == 2 )); then
- _values 'rar command' \
+ _values 'rar command' \
'e[extract files to current directory]' \
'l[list archive]' \
'lt[list archive (technical format)]' \
@@ -48,7 +48,7 @@ case $service in
'v[verbosely list archive]' \
'vt[verbosely list archive (technical format)]' \
'vb[verbosely list archive (bare format)]' \
- 'x[extract files with full path]' && return
+ 'x[extract files with full path]'
else
_arguments -S \
'-ep3[expand paths to full including the drive letter]' \
@@ -58,7 +58,7 @@ case $service in
'-n+:file to include:_files' \
'-n@+:file of files to include:_files' \
"$common[@]" \
- '*:RAR files:_files -g \*.rar\(-.\)' && return
+ '*:RAR files:_files -g \*.rar\(-.\)'
fi
;;
rar)
@@ -89,7 +89,7 @@ case $service in
'v[verbosely list archive]' \
'vt[verbosely list archive (technical format)]' \
'vb[verbosely list archive (bare format)]' \
- 'x[extract files with full path]' && return
+ 'x[extract files with full path]'
else
_arguments -S \
'-ag[generate archive name using the current date]' \
@@ -126,7 +126,7 @@ case $service in
'-w+[assign work directory]:work directory:_files -/' \
"$common[@]" \
'-z+[read archive comment from file]:comment file:_files' \
- '*:files:_files' && return
+ '*:files:_files'
fi
;;
esac
diff --git a/Completion/Unix/Command/_readelf b/Completion/Unix/Command/_readelf
new file mode 100644
index 000000000..9312ea864
--- /dev/null
+++ b/Completion/Unix/Command/_readelf
@@ -0,0 +1,62 @@
+#compdef readelf eu-readelf
+
+local variant args sections
+
+_elf_file() {
+ [[ -x $REPLY || $REPLY = (core*|*.([ao]|so|elf)) ]]
+}
+
+sections=( .bss .data .dynamic .dynsym .got .interp .shstrtab .symtab .text )
+_pick_variant -r variant elftoolchain=elftoolchain elfutils=elfutils binutils --version
+
+args=(
+ '(-a --all)'{-a,--all}'[show all tables]'
+ '(-h --file-header)'{-h,--file-header}'[show file header]'
+ '(-l --program-headers --segments)'{-l,--program-headers,--segments}'[show program headers]'
+ '(-S --section-headers --sections)'{-S,--section-headers,--sections}'[show sections header]'
+ '(-s --syms --symbols)'{-s,--syms,--symbols}'[show symbol table]'
+ '(-n --notes)'{-n,--notes}'[show core notes (if present)]'
+ '(-r --relocs)'{-r,--relocs}'[show relocations (if present)]'
+ '(-d --dynamic)'{-d,--dynamic}'[show dynamic section (if present)]'
+ '(-V --version-info)'{-V,--version-info}'[show version sections (if present)]'
+ '(-A --arch-specific)'{-A,--arch-specific}'[show architecture specific information (if any)]'
+ '(-c --archive-index)'{-c,--archive-index}'[show symbol/file index in an archive]'
+ \*{-x,--hex-dump=}"[dump contents of specified section as bytes]:section:($sections)"
+ \*{-p,--string-dump=}"[dump contents of specified section as strings]:section:($sections)"
+ '-w+[show the contents of DWARF2 debug sections]::debug section:(l L i a p r m f F s o R t)'
+ '--debug-dump=[show the contents of DWARF2 debug sections]::section:(rawline decodedline info abbrev pubnames aranges macro frames frames-interp str loc Ranges pubtypes gdb_index trace_info trace_abbrev trace_aranges)'
+ '(-I --histogram)'{-I,--histogram}'[show histogram of bucket list lengths]'
+ '(-W --wide)'{-W,--wide}'[allow output width to exceed 80 characters]'
+ '(- *)'{-H,--help}'[display help information]'
+ '(- *)'{-v,--version}'[display version information]'
+ "*:elf file:_files -g '*(-.e:_elf_file:)'"
+)
+
+case $variant in
+ elftoolchain|binutils)
+ args+=(
+ '(-g --section-groups)'{-g,--section-groups}'[show section groups]'
+ '(-t --section-details)'{-t,--section-details}'[show section details]'
+ '(-e --headers)'{-e,--headers}'[show file, program and sections headers]'
+ '(-u --unwind)'{-u,--unwind}'[show unwind info (if present)]'
+ '(-D --use-dynamic)'{-D,--use-dynamic}'[use dynamic section info when showing symbols]'
+ )
+ ;|
+ binutils)
+ args+=(
+ '--dyn-syms[show dynamic symbol table]'
+ \*{-R,--relocated-dump=}"[dump contents of specified section as relocated bytes]:section:($sections)"
+ "--dwarf-depth=[don't show DIEs at greater than specified depth]:depth"
+ '--dwarf-start=[show DIEs starting at specified depth or deeper]:depth'
+ )
+ ;;
+ elfutils)
+ args+=(
+ '--elf-section[used specified section as ELF input data]::section'
+ '(-e --exception)'{-e,--exception}'[show sections for exception handling]'
+ '(-N --numeric-addresses)'{-N,--numeric-addresses}"[don't find symbol names for addresses in DWARF data]"
+ )
+ ;;
+esac
+
+_arguments -s "$args[@]"
diff --git a/Completion/Unix/Command/_ri b/Completion/Unix/Command/_ri
index feb10ec91..070f46ac2 100644
--- a/Completion/Unix/Command/_ri
+++ b/Completion/Unix/Command/_ri
@@ -3,7 +3,7 @@
local curcontext="$curcontext" state line ret=1
typeset -A opt_args
-_arguments \
+_arguments -C \
'(- *)'{-h,--help}'[print help information and exit]' \
'(- *)'{-v,--version}'[display the version of ri]' \
'*'{-d,--doc-dir}'[directory to search for documentation]:ri doc directory:_files -/' \
@@ -42,8 +42,6 @@ if [[ "$state" = ri-name ]]; then
if compset -P '?*(::|\#|.)'; then
class_dir=${IPREFIX//(::|\#|.)/\/}
- #else
- # :
fi
esc_name=${${(Q)PREFIX}//(#b)([^A-Za-z0-9_])/$(printf %%%x ${(qq)match[1]})}
diff --git a/Completion/Unix/Command/_rm b/Completion/Unix/Command/_rm
index 1f156c481..4728ad464 100644
--- a/Completion/Unix/Command/_rm
+++ b/Completion/Unix/Command/_rm
@@ -1,4 +1,4 @@
-#compdef rm
+#compdef rm grm zf_rm
declare -a opts args
args=(
@@ -16,12 +16,25 @@ if _pick_variant gnu=gnu unix --help; then
'--one-file-system[stay within filesystems of files given as arguments]'
'( --preserve-root)--no-preserve-root[do not treat / specially]'
'(--no-preserve-root )--preserve-root[do not remove / (default)]'
+ '(-d --dir)'{-d,--dir}'[remove directories as well]'
'(-v --verbose)'{-v,--verbose}'[explain what is being done]'
'(- *)--help[display help message and exit]'
'(- *)--version[output version information and exit]'
)
else
args=(${args:#*--(force|recursive)\[*})
+ case $OSTYPE in
+ freebsd*)
+ args+=(
+ '-d[remove directories as well]'
+ '(-i)-I[prompt when removing many files]'
+ '-P[overwrite files before deleting them]'
+ '-v[explain what is being done]'
+ '-W[attempt to undelete named files]'
+ "-x[don't cross file systems when removing a hierarchy]"
+ )
+ ;;
+ esac
fi
local curcontext=$curcontext state line ret=1
diff --git a/Completion/Unix/Command/_rsync b/Completion/Unix/Command/_rsync
index 7bad03a05..79d8243e1 100644
--- a/Completion/Unix/Command/_rsync
+++ b/Completion/Unix/Command/_rsync
@@ -35,10 +35,10 @@ if compset -P '*::*/' || compset -P 'rsync://*/*/'; then
# attrs size date time name
_wanted files expl 'remote file or directory' \
- compadd -d remdispf ${${${${remdispf##[^ ]## ##}##[^ ]## ##}##[^ ]## ##}##[^ ]## ##}
+ compadd -d remdispf ${${${${remdispf##[^ ]## ##}##[^ ]## ##}##[^ ]## ##}##[^ ]## ##} && ret=0
_wanted files expl 'remote file or directory' \
- compadd -S/ -d remdispd ${${${${remdispd##[^ ]## ##}##[^ ]## ##}##[^ ]## ##}##[^ ]## ##}
+ compadd -S/ -d remdispd ${${${${remdispd##[^ ]## ##}##[^ ]## ##}##[^ ]## ##}##[^ ]## ##} || (( ! ret ))
elif compset -P 1 '*::' || compset -P 1 'rsync://*/'; then
diff --git a/Completion/Unix/Command/_rubber b/Completion/Unix/Command/_rubber
index 09e289aa2..f66540a9f 100644
--- a/Completion/Unix/Command/_rubber
+++ b/Completion/Unix/Command/_rubber
@@ -15,24 +15,24 @@ else
fi
_rubber_args=(
- \*{-c,--command}'=[run the directive CMD before parsing]:command'
- \*{-e,--epilogue}'=[run the directive CMD after parsing]:command'
- {-z,--gzip}'[compress the final document]'
- '(- *)'{-h,--help}'[show help]'
- '--into=[go to directory DIR before compiling]:directory:_files -/'
- {-l,--landscape}'[change paper orientation (if relevant)]'
- {-n,--maxerr}'=[display at most NUM errors]:num'
- \*{-m,--module}'=[use module]:module:($_rubber_modules)'
- '--only=[only include the specified SOURCES]:sources'
- \*{-o,--post}'=[postprocess with module]:postprocessor:($_rubber_modules)'
- {-d,--pdf}'[produce PDF output instead of DVI]'
- {-p,--ps}'[produce a PostScript document]'
- {-q,--quiet}'[suppress messages]'
- \*{-r,--read}'[read additional directives from a file]:directives files:_files'
- {-s,--short}'[display errors in a compact form]'
- \*{-I,--texpath}'=[add DIR to the search path for LaTeX]:tex path:_files -/'
- \*{-v,--verbose}'[increase verbosity]'
- '--version[print version information and exit]'
+ \*{-c,--command}'=[run specified directive command before parsing]:command'
+ \*{-e,--epilogue}'=[run specified directive command after parsing]:command'
+ '(-z --gzip)'{-z,--gzip}'[compress the final document]'
+ '(- *)'{-h,--help}'[show help information]'
+ '--into=[go to specified directory before compiling]:directory:_files -/'
+ '(-l --landscape)'{-l,--landscape}'[change paper orientation (if relevant)]'
+ '(-n --maxerr)'{-n,--maxerr}'=[display at most specified number of errors]:number'
+ \*{-m,--module}'=[use module]:module:($_rubber_modules)'
+ '--only=[only include the specified sources]:sources'
+ \*{-o,--post}'=[postprocess with module]:postprocessor:($_rubber_modules)'
+ '(-d --pdf -p -ps)'{-d,--pdf}'[produce PDF output instead of DVI]'
+ '(-p -ps -d --pdf)'{-p,--ps}'[produce a PostScript document]'
+ {-q,--quiet}'[suppress messages]'
+ \*{-r,--read}'[read additional directives from a file]:directives files:_files'
+ {-s,--short}'[display errors in compact form]'
+ \*{-I,--texpath}'=[add directory to the search path for LaTeX]:tex path:_files -/'
+ \*{-v,--verbose}'[increase verbosity]'
+ '--version[print version information and exit]'
)
case "$service" in
@@ -42,17 +42,15 @@ case "$service" in
'--clean[remove produced files instead of compiling]' \
{-f,--force}'[force at least one compilation]' \
'--inplace[compile the documents from their source directory]' \
- \*{-W,--warn}'=[report warnings of the given TYPE]:warnings:(all boxes misc refs)' \
+ \*{-W,--warn}'=[report warnings of the given type]:warnings:(all boxes misc refs)' \
'*:LaTeX files:_files -g "*.(tex|dtx|lhs|w)(-.)"'
- return 0
;;
rubber-pipe)
_arguments -s \
"$_rubber_args[@]" \
{-k,--keep}'[keep the temporary files after compiling]' \
- \*{-W,--warn}'=[report warnings of the given TYPE]:warnings:(all boxes misc refs)'
- return 0
+ \*{-W,--warn}'=[report warnings of the given type]:warnings:(all boxes misc refs)'
;;
rubber-info)
@@ -65,8 +63,5 @@ case "$service" in
'--refs[show the list of undefined references]' \
'--warnings[show all LaTeX warnings]' \
':LaTeX file:_files -g "*.(tex|dtx|lhs|w)(-.)"'
- return 0
;;
esac
-
-return 1
diff --git a/Completion/Unix/Command/_ruby b/Completion/Unix/Command/_ruby
index 946ebe270..49a1170ef 100644
--- a/Completion/Unix/Command/_ruby
+++ b/Completion/Unix/Command/_ruby
@@ -95,7 +95,7 @@ case "$service" in
_arguments -C -s : $irb $all $common && ret=0
;;
erb[0-9.]#)
- RUBY=${words[1]/irb/ruby}
+ RUBY=${words[1]/erb/ruby}
_arguments -C -s : $erb $all \
'*:erb file:_files -g "*.erb(-.)"' && ret=0
;;
diff --git a/Completion/Unix/Command/_runit b/Completion/Unix/Command/_runit
new file mode 100644
index 000000000..81ba26a44
--- /dev/null
+++ b/Completion/Unix/Command/_runit
@@ -0,0 +1,73 @@
+#compdef sv
+
+_sv_commands() {
+ local -a sv_ary
+ sv_ary=(
+ 'status':'get status of service (and log service if available)'
+ 'up':'start if service is running. If service stops, restart'
+ 'down':'send SIGTERM and SIGCONT if service is running. After it stops, do not restart'
+ 'once':'start if service is not running. Do not restart if it stops'
+ 'pause':'send SIGSTOP if service is running'
+ 'cont':'send SIGCONT if service is running'
+ 'hup':'send SIGHUP if service is running'
+ 'alarm':'send SIGALRM if service is running'
+ 'interrupt':'send SIGINT if service is running'
+ 'quit':'send SIGQUIT if service is running'
+ '1':'send SIGUSR1 if service is running'
+ '2':'send SIGUSR2 if service is running'
+ 'term':'send SIGTERM if service is running'
+ 'kill':'send SIGKILL if service is running'
+ 'exit':'send SIGTERM and SIGCONT if service is running. Do not restart service.'
+ )
+ _describe -t commands "sv commands" sv_ary -V sv_commands
+}
+
+_sv_lsb() {
+ local -a sv_lsb_ary
+ sv_lsb_ary=(
+ 'start':'up with check/timeout'
+ 'stop':'down with check/timeout'
+ 'reload':'hup with check'
+ 'restart':'down and up with check'
+ 'shutdown':'exit with check/timeout'
+ 'force-stop':'stop with kill on timeout'
+ 'force-reload':'reload with kill on timeout'
+ 'force-restart':'restart with kill on timeout'
+ 'force-shutdown':'shutdown with kill on timeout'
+ 'try-restart':'restart if service is already running'
+ )
+
+ _describe -t lsb-commands "sv LSM init compat" sv_lsb_ary -V sv_init_compat
+}
+
+_sv_additional() {
+ _describe -t additional-commands "sv additional commands" '("check:check status of service")' -V sv_addl_comm
+}
+
+local curcontext="$curcontext" state line
+_arguments -C \
+ '-v[verbose]' \
+ '-w[wait time]:time (seconds)' \
+ '1: :->command' \
+ '*:: :->options'
+
+case $state in
+ (command)
+ _alternative \
+ _sv_commands \
+ _sv_lsb \
+ _sv_additional
+ ;;
+
+ (options)
+ local -a sv_services
+ local svdir=${SVDIR:-/etc/service}
+ sv_services=(
+ $svdir/*(N)
+ $svdir/*/log(N)
+ )
+
+ sv_services=( ${sv_services#$svdir/} )
+ _describe -t services "sv services" sv_services
+ ;;
+esac
diff --git a/Completion/Unix/Command/_sablotron b/Completion/Unix/Command/_sablotron
index 170f08abd..53e0bec92 100644
--- a/Completion/Unix/Command/_sablotron
+++ b/Completion/Unix/Command/_sablotron
@@ -20,15 +20,8 @@ _arguments -C \
if [[ -n "$state" ]]; then
mode="${opt_args[(i)-c|--chain-xsl]:+chain}${opt_args[(i)-x|--batch-xml]:+batch-x}${opt_args[(i)-s|--batch-xsl]:+batch-s}"
[[ $mode = (chain|batch-[xs]) ]] || mode=default
- _tags assignments files
+ _tags files assignments
while _tags; do
- if _requested assignments; then
- if [[ -prefix *= ]]; then
- _message -e value value
- else
- _message -e parameter 'parameter name'
- fi
- fi
if _requested files; then
case $mode:${#words[1,CURRENT-1]:#(-*|*=*)}; in
default:1|chain:<3->|batch-x:2|batch-s:1)
@@ -45,6 +38,13 @@ if [[ -n "$state" ]]; then
;;
esac
fi
+ if _requested assignments; then
+ if [[ -prefix *= ]]; then
+ _message -e value value
+ else
+ _message -e parameter 'parameter name' && ret=0
+ fi
+ fi
(( ret )) || break
done
fi
diff --git a/Completion/Unix/Command/_screen b/Completion/Unix/Command/_screen
index 931946c78..510fd7195 100644
--- a/Completion/Unix/Command/_screen
+++ b/Completion/Unix/Command/_screen
@@ -1,20 +1,8 @@
#compdef screen
-local curcontext="$curcontext" state line expl
+local curcontext="$curcontext" state line expl ret=1
local scr_cmds sessions
-function __screen_normal() {
- if (( CURRENT == 1 )) && [[ $PREFIX == /dev/* ]]; then
- _path_files -g '*(%)'
- elif (( CURRENT == 2 )) && [[ ${words[1]} == /dev/* ]]; then
- _message "baud rate"
- elif (( CURRENT > 2 )) && [[ ${words[1]} == /dev/* ]]; then
- _message "no more parameters"
- else
- _normal "$@"
- fi
-}
-
scr_cmds=(
acladd aclchg acldel aclgrp
aclumask activity addacl allpartial
@@ -103,10 +91,21 @@ _arguments -C \
'-Dx: :->any-sessions' \
'-dx: :->any-sessions' \
'-X[execute command as a screen command in the specified session]:screencmd:(${scr_cmds[@]})' \
- '*::arguments: __screen_normal'
+ '*:: :->normal' && ret=0
if [[ -n $state ]]; then
case $state in
+ normal)
+ if (( CURRENT == 1 )) && [[ $PREFIX == /dev/* ]]; then
+ _path_files -g '*(%)'
+ elif (( CURRENT == 2 )) && [[ ${words[1]} == /dev/* ]]; then
+ _message "baud rate"
+ elif (( CURRENT > 2 )) && [[ ${words[1]} == /dev/* ]]; then
+ _message "no more parameters"
+ else
+ _normal
+ fi
+ ;;
attached-sessions)
sessions=(
${${${(M)${(f)"$(_call_program screen-sessions $words[1] \
@@ -134,4 +133,6 @@ if [[ -n $state ]]; then
_wanted screen-sessions expl "${state%-*} screen process" \
compadd ${sessions#*.}
fi
-fi
+fi && ret=0
+
+return ret
diff --git a/Completion/Unix/Command/_sed b/Completion/Unix/Command/_sed
index 476575205..8e2385cc8 100644
--- a/Completion/Unix/Command/_sed
+++ b/Completion/Unix/Command/_sed
@@ -1,22 +1,29 @@
-#compdef sed
+#compdef sed gsed psed s2p
-local args
+local args inplace extended
args=(
'(-n --quiet --silent)'{-n,--quiet,--silent}'[suppress automatic printing of pattern space]'
- '(1)*'{-e,--expression=-}'[add sed commands to run]:sed script'
+ '(1)*'{-e,--expression=-}'[specify sed commands to run]:sed script'
'(1)*'{-f,--file=-}'[add contents of file to commands to run]:file:_files'
'(-e)1: :_guard "^-*" sed script'
'*:input file:_files'
)
+inplace='[edit files in-place, running scripts separately for each file]::suffix for backup'
+extended='[use extended regular expressions]'
-if _pick_variant gnu=GNU unix --version; then
+if [[ $service = (psed|s2p) ]]; then
+ args=(
+ "${(@)args:#(|\(*\))(|\*)--*}"
+ '-a[delay opening files listed with w function]'
+ )
+elif _pick_variant gnu=GNU unix --version; then
args+=(
'--follow-symlinks[follow symlinks when processing in place]'
- '(-i --in-place)'{-i-,--in-place=-}'[edit files in place]::suffix for backup'
+ '(-i --in-place)'{-i-,--in-place=-}$inplace
'(-l --line-length)'{-l,--line-length=-}'[specify line-wrap length for the l command]'
'(-r)--posix[disable GNU extensions]'
- '(-r --regexp-extended)'{-r,--regexp-extended}'[use extended regular expressions]'
+ '(-r --regexp-extended)'{-r,--regexp-extended}$extended
'(-s --separate)'{-s,--separate}'[consider files separately instead of as a combined stream]'
'(-u --unbuffered)'{-u,--unbuffered}'[disable data buffering]'
'(- 1 :)--help[print program usage]'
@@ -24,6 +31,27 @@ if _pick_variant gnu=GNU unix --version; then
)
else
args=( "${(@)args:#(|\(*\))(|\*)--*}" )
+ case $OSTYPE in
+ openbsd*|freebsd*|netbsd*|darwin*|dragonfly*)
+ args+=(
+ '(-r -E)'{-r,-E}$extended
+ '-a[delay opening files listed with w function]'
+ )
+ ;|
+ darwin*|freebsd*|netbsd*)
+ args+=(
+ '-i'$inplace
+ '-l[make output line buffered]'
+ )
+ ;|
+ freebsd*) args+=( '-u[disable data buffering]' ) ;|
+ freebsd*|netbsd*)
+ args+=(
+ '-I[edit files in-place, treating all files as a single input stream]::suffix for backup'
+ )
+ ;;
+ openbsd*) args+=( '-u[make output line buffered]' ) ;;
+ esac
fi
-_arguments "$args[@]"
+_arguments -s "$args[@]"
diff --git a/Completion/Unix/Command/_sh b/Completion/Unix/Command/_sh
index 104c7576c..21ebfc3b2 100644
--- a/Completion/Unix/Command/_sh
+++ b/Completion/Unix/Command/_sh
@@ -10,8 +10,7 @@ if [[ $service == zsh ]]; then
fi
if (( CURRENT == ${words[(i)-c]} + 1 )); then
- compset -q
- _normal
+ _cmdstring
else
local n=${words[(b:2:i)[^-]*]}
if (( n <= CURRENT )); then
diff --git a/Completion/Unix/Command/_sort b/Completion/Unix/Command/_sort
index ff36b9b3d..2e7f0a01a 100644
--- a/Completion/Unix/Command/_sort
+++ b/Completion/Unix/Command/_sort
@@ -1,37 +1,76 @@
-#compdef sort
+#compdef sort gsort
+local args variant
local ordering='(-d --dictionary-order -g --general-numeric-sort -M --month-sort -h --human-numeric-sort -n --numeric-sort --sort -V --version-sort --help --version)'
-_arguments -s -S \
- '(-b --ignore-leading-blanks)'{-b,--ignore-leading-blanks}'[ignore leading blanks]' \
- "$ordering"{-d,--dictionary-order}'[consider only blanks and alphanumeric characters]' \
- '(-f --ignore-case)'{-f,--ignore-case}'[fold lower case to upper case characters]' \
- "$ordering"{-g,--general-numeric-sort}'[compare according to general numeric value]' \
- '(-i --ignore-nonprinting)'{-i,--ignore-nonprinting}'[consider only printable characters]' \
- "$ordering"{-M,--month-sort}"[compare (unknown) < 'JAN' < ... < 'DEC']" \
- "$ordering"{-h,--human-numeric-sort}'[compare human readable numbers (e.g., 2K 1G)]' \
- "$ordering"{-n,--numeric-sort}'[compare according to string numerical value]' \
- "$ordering"{-R,--random-sort}'[sort by random hash of keys]' \
- '--random-source=[get random bytes from file]:file:_files' \
- '(-r --reverse)'{-r,--reverse}'[reverse the result of comparisons]' \
- "$ordering--sort=[sort according to ordering]:ordering:(general-numeric human-numeric month numeric random version)" \
- "$ordering"{-V,--version-sort}'[sort version numbers]' \
- '--batch-size=[maximum inputs to merge]:number' \
- '(-c --check -C)'{-c,-C}'[check whether input is sorted; do not sort]' \
- '(-c --check -C)--check=-[check whether input is sorted; do not sort]::bad line handling:(diagnose-first silent quiet)' \
- '--compress-program=[specify program to compress temporary files with]:program:(gzip bzip2 lzop xz)' \
- '--debug[annotate the of the line used to sort]' \
- '--files0-from=[read input files from file]:file:_files' \
- '(-k --key)'{-k+,--key=}'[start a key at POS1, end it as POS2 (origin 1)]:key' \
- '(-m --merge)'{-m,--merge}'[merge already sorted files; do not sort]' \
- '(-o --output)'{-o+,--output=}'[write result to file instead of standard output]:output file:_files' \
- '(-s --stable)'{-s,--stable}'[preserve original order of lines with the same key]' \
- '(-S --buffer-size)'{-S+,--buffer-size=}'[specify size for main memory buffer]:size' \
- '(-t --field-separator)'{-t+,--field-separator=}'[specify field separator instead of non-blank to blank transition]:separator' \
- \*{-T+,--temporary-directory=}'[specify directory for temporary files]:directory:_directories' \
- '(-u --unique)'{-u,--unique}'[with -c, check for strict ordering; without -c, output only the first of an equal run]' \
- '--parallel=[set number of sorts run concurrently]:number' \
- '(-z --zero-terminated)'{-z,--zero-terminated}'[end lines with 0 byte, not newline]' \
- '(- *)--help[display help and exit]' \
- '(- *)--version[output version information and exit]' \
- '*:file:_files'
+args=(
+ '(-c --check -C)-c[check whether input is sorted; do not sort]'
+ '(-m --merge)'{-m,--merge}'[merge already sorted files; do not sort]'
+ '(-o --output)'{-o+,--output=}'[write result to file instead of standard output]:output file:_files'
+ \*{-T+,--temporary-directory=}'[specify directory for temporary files]:directory:_directories'
+ '(-u --unique)'{-u,--unique}'[with -c, check for strict ordering; without -c, output only the first of an equal run]'
+ "$ordering"{-d,--dictionary-order}'[consider only blanks and alphanumeric characters]'
+ '(-f --ignore-case)'{-f,--ignore-case}'[fold lower case to upper case characters]'
+ '(-i --ignore-nonprinting)'{-i,--ignore-nonprinting}'[consider only printable characters]'
+ "$ordering"{-n,--numeric-sort}'[compare according to string numerical value]'
+ '(-r --reverse)'{-r,--reverse}'[reverse the result of comparisons]'
+ '(-b --ignore-leading-blanks)'{-b,--ignore-leading-blanks}'[ignore leading blanks]'
+ '(-t --field-separator)'{-t+,--field-separator=}'[specify field separator instead of non-blank to blank transition]:separator'
+ '(-k --key)'{-k+,--key=}'[specified start and end fields for key]:key field'
+)
+
+_pick_variant -r variant gnu=GNU $OSTYPE --version
+case $variant in
+ dragonfly*|netbsd*|openbsd*|freebsd*|gnu)
+ args+=(
+ '(-s --stable)'{-s,--stable}'[preserve original order of lines with the same key]'
+ )
+ ;|
+ openbsd*|freebsd*|gnu)
+ args+=(
+ '(-c --check -C)-C[check whether input is sorted; do not sort]'
+ '(-z --zero-terminated)'{-z,--zero-terminated}'[end lines with 0 byte, not newline]'
+ )
+ ;|
+ freebsd*|gnu)
+ args+=(
+ '(-c --check -C)--check=-[check whether input is sorted; do not sort]::bad line handling:(diagnose-first silent quiet)'
+ "$ordering"{-g,--general-numeric-sort}'[compare according to general numeric value]'
+ "$ordering"{-M,--month-sort}"[compare (unknown) < 'JAN' < ... < 'DEC']"
+ "$ordering"{-h,--human-numeric-sort}'[compare human readable numbers (e.g., 2K 1G)]'
+ "$ordering"{-R,--random-sort}'[sort by random hash of keys]'
+ "$ordering"{-V,--version-sort}'[sort version numbers]'
+ "$ordering--sort=[sort according to ordering]:ordering:(general-numeric human-numeric month numeric random version)"
+ '(-i --ignore-nonprinting)'{-i,--ignore-nonprinting}'[consider only printable characters]'
+ '--random-source=[get random bytes from file]:file:_files'
+ '--batch-size=[maximum inputs to merge]:number'
+ '--compress-program=[specify program to compress temporary files with]:program:(gzip bzip2 lzop xz)'
+ '--debug[annotate the of the line used to sort]'
+ '--files0-from=[read input files from file]:file:_files'
+ '(-S --buffer-size)'{-S+,--buffer-size=}'[specify size for main memory buffer]:size'
+ '(- *)--help[display help and exit]'
+ '(- *)--version[output version information and exit]'
+ )
+ ;|
+ netbsd*|dragonfly*)
+ args+=(
+ "${ordering}-l[sort by string length of field]"
+ "(-s)-S[don't use stable sort"
+ )
+ ;|
+ openbsd*)
+ args+=(
+ '-H[use a merge sort instead of a radix sort]'
+ '-R[specify record separator]:separator'
+ )
+ ;|
+ gnu)
+ args+=( '--parallel=[set number of sorts run concurrently]:number' )
+ ;;
+ freebsd*)
+ args+=( --radixsort --mergesort --qsort --heapsort --mmap )
+ ;;
+ *) args=( "${(@)args:#(|\(*\))(|\*)--*}" ) ;;
+esac
+
+_arguments -s -S $args '*:file:_files'
diff --git a/Completion/Unix/Command/_stgit b/Completion/Unix/Command/_stgit
index 6248267eb..f313f651a 100644
--- a/Completion/Unix/Command/_stgit
+++ b/Completion/Unix/Command/_stgit
@@ -40,11 +40,11 @@ else
compadd ${${(M)${(f)"$(stg series 2> /dev/null)"}##[+>] *}#[+>] } \
&& ret=0
else
- _files
+ _files && ret=0
fi
;;
(*)
- _files
+ _files && ret=0
;;
esac
fi
diff --git a/Completion/Unix/Command/_strip b/Completion/Unix/Command/_strip
index 06f7243b5..726d87c2b 100644
--- a/Completion/Unix/Command/_strip
+++ b/Completion/Unix/Command/_strip
@@ -1,6 +1,6 @@
#compdef strip
-local curcontext=$curcontext state line ret=0
+local curcontext=$curcontext state line ret=1
declare -A opt_args
declare -a args
@@ -11,8 +11,8 @@ if _pick_variant gnu=GNU solaris --version; then
local expl
_description files expl 'command-line-options file'
- _files $expl && ret=0
- return $ret
+ _files "$expl[@]"
+ return
fi
args=(
'(-F --target)'{-F+,--target=}'[object code format to use]:bfd name:->bfdnames'
@@ -52,9 +52,9 @@ case $state in
local expl
declare -a bfdnames
- bfdnames=(${=${(M)${(f)"$(_call_program bfdnames strip --help 2>/dev/null)"}:#strip: supported targets: *}#strip: supported targets: })
+ bfdnames=(${=${(M)${(f)"$(_call_program bfdnames strip --help)"}:#strip: supported targets: *}#strip: supported targets: })
_describe -t bfdnames 'bfd name' bfdnames && ret=0
;;
esac
-return $ret
+return ret
diff --git a/Completion/Unix/Command/_su b/Completion/Unix/Command/_su
index 6d0f2cd9f..057a41371 100644
--- a/Completion/Unix/Command/_su
+++ b/Completion/Unix/Command/_su
@@ -1,9 +1,9 @@
#compdef su
local -A opt_args
-local -a args state context
+local -a args context state line expl
local shell=${words[(i)(-s|--shell=*)]} first='1:user name:_users'
-local usr=root line
+local usr=root
if _pick_variant gnu="Free Software Foundation" unix --version; then
args=(
@@ -20,10 +20,21 @@ if _pick_variant gnu="Free Software Foundation" unix --version; then
)
else
args=(
- '-c[pass command to shell]:command string:->command'
'-l[use a login shell]'
'-s[run the specified shell]:shell:->shell'
)
+ case $OSTYPE in
+ freebsd*)
+ args=(
+ '-c[use settings from specified login class]:class'
+ '-f[if the invoked shell is csh, prevent it from reading .cshrc]'
+ '-l[use a login shell]'
+ '-m[do not reset environment]'
+ '-s[set the MAC label]'
+ )
+ ;;
+ *) args+=( '-c[pass command to shell]:command string:->command' ) ;;
+ esac
fi
if [[ $#words -ge 2 && $words[2] != -* && CURRENT -ne 2 ]]; then
@@ -50,11 +61,11 @@ case $state in
return
;;
(shell)
- compadd ${(f)^"$(</etc/shells)"}(N)
+ _wanted -C $context shells expl shell compadd ${(f)^"$(</etc/shells)"}(N)
return
;;
(rest)
- if [[ -z $shell || $shell = */nologin ]]; then
+ if [[ -z $shell || $shell = */(nologin|false) ]]; then
_arguments "-s[run the specified shell, $usr has no shell]" ||
_message "-s option required, $usr has no shell"
compstate[insert]=
diff --git a/Completion/Unix/Command/_sudo b/Completion/Unix/Command/_sudo
index f8543f865..63ac37f62 100644
--- a/Completion/Unix/Command/_sudo
+++ b/Completion/Unix/Command/_sudo
@@ -1,6 +1,8 @@
#compdef sudo sudoedit
-local curcontext="$curcontext" environ e
+setopt localoptions extended_glob
+
+local environ e
local -a args
zstyle -a ":completion:${curcontext}:" environ environ
@@ -10,33 +12,44 @@ do local -x "$e"
done
args=(
- '-V[show version]'
- '-l[list allowed commands]'
- '-L[list options from Default section]'
- '-a[BSD auth type]:BSD auth type:'
- '-c[BSD login class]:BSD login class:'
- '-h[show help]'
- '-v[validate user timestamp]'
- '-k[invalidate user timestamp]'
- '-K[remove user timestamp]'
- '-r[Kerberos realm]:Kerberos realm:'
- '-p[password prompt]:password prompt:'
- '-u[user name]:user name:_users'
- '-S[read password from stdin]'
+ '(-A --askpass)'{-A,--askpass}'[use a helper program for password prompting]'
+ '(-C --close-from)'{-C+,--close-from=}'[close file descriptors]:lowest fd to close'
+ '(-g --group)'{-g+,--group=}'[run command as the specified group name or ID]:group:_groups'
+ '(-)'{-h,--help}'[display help message and exit]'
+ '(-h --host)'{-h+,--host=}'[run command on host]:host:_hosts'
+ '(-K --remove-timestamp)'{-K,--remove-timestamp}'[remove timestamp file completely]'
+ '(-k --reset-timestamp)'{-k,--reset-timestamp}'[invalidate timestamp file]'
+ \*{-l,--list}"[list user's privileges or check a specific command]"
+ '(-n --non-interactive)'{-n,--non-interactive}'[non-interactive mode, no prompts are used]'
+ '(-p --prompt)'{-p+,--prompt=}'[use the specified password prompt]:prompt'
+ '(-r --role)'{-r+,--role=}'[create SELinux security context with specified role]:role'
+ '(-S --stdin)'{-S,--stdin}'[read password from standard input]'
+ '(-t --type)'{-t+,--type=}'[create SELinux security context with specified type]:type'
+ '(-U --other-user)'{-U+,--other-user=}'[in list mode, display privileges for user]:user:_users'
+ '(-u --user)'{-u+,--user=}'[run command (or edit file) as specified user]:user:_users'
+ '(-)'{-V,--version}'[display version information and exit]'
+ '(-v --validate)'{-v,--validate}"[update user's timestamp without running a command]"
)
-if [[ $service = sudoedit ]]; then
- _arguments $args \
- '*:file: _files'
+# Does -e appears before the first word that doesn't begin with a hyphen?
+# The way (i) works in subscripts, the test will always be true if all the
+# words begin with a hyphen.
+#
+# TODO: use _arguments' $opt_args to detect the cases '-u jrandom -e' and '-Ae'
+if [[ $service = sudoedit ]] || (( $words[(i)-e] < $words[(i)^(*sudo|-[^-]*)] )) ; then
+ args=( -A "-*" $args '!(-V --version -h --help)-e' '*:file:_files' )
else
- _arguments $args \
- '(- :)-e[edit file]:*:file:_files' \
- '(- :)-s[run SHELL]' \
- '(- :)-i[simulate login]' \
- '(-i -s -e)-b[run command in background]' \
- '(-i -s -e)-E[preserve environment]' \
- '(-i -s -e)-H[set HOME environment variable]' \
- '(-i -s -e)-P[preserve group vector]' \
- '(-):command: _command_names -e' \
+ args+=(
+ '(-e --edit 1 *)'{-e,--edit}'[edit files instead of running a command]' \
+ '(-s --shell)'{-s,--shell}'[run shell as the target user; a command may also be specified]' \
+ '(-i --login)'{-i,--login}'[run login shell as the target user; a command may also be specified]' \
+ '(-b --background -i --login -s --shell -e --edit)'{-b,--background}'[run command in the background]' \
+ '(-E --preserve-env -i --login -s --shell -e --edit)'{-E,--preserve-env}'[preserve user environment when running command]' \
+ '(-H --set-home -i --login -s --shell -e --edit)'{-H,--set-home}"[set HOME variable to target user's home dir]" \
+ '(-P --preserve-groups -i -login -s --shell -e --edit)'{-P,--preserve-groups}"[preserve group vector instead of setting to target's]" \
+ '(-)1:command: _command_names -e'
'*::arguments: _normal'
+ )
fi
+
+_arguments -s -S $args
diff --git a/Completion/Unix/Command/_systemd b/Completion/Unix/Command/_systemd
index d2a7895e1..028ecddd9 100644
--- a/Completion/Unix/Command/_systemd
+++ b/Completion/Unix/Command/_systemd
@@ -132,9 +132,9 @@ _hosts_or_user_at_host()
)
if (( CURRENT == 1 )); then
- _describe -t commands 'systemctl command' _systemctl_cmds || compadd "$@"
+ _describe -t commands 'systemctl command' _systemctl_cmds
else
- local curcontext="$curcontext"
+ local curcontext="$curcontext" ret
cmd="${${_systemctl_cmds[(r)$words[1]:*]%%:*}}"
# Deal with any aliases
diff --git a/Completion/Unix/Command/_telnet b/Completion/Unix/Command/_telnet
index c7ab34f98..1674eedd8 100644
--- a/Completion/Unix/Command/_telnet
+++ b/Completion/Unix/Command/_telnet
@@ -12,8 +12,8 @@ if (( ! $+_telnet_args )); then
local help="$(_call_program options 'telnet -\?' < /dev/null 2>&1)"
local -A optionmap
optionmap=(
- '*\[-4\]*' '-4[Force IPv4 address resolution]'
- '*\[-6\]*' '-6[Force IPv6 address resolution]'
+ '*\[-4\]*' '-4[force IPv4 address resolution]'
+ '*\[-6\]*' '-6[force IPv6 address resolution]'
'*\[-8\]*' '-8[allow 8-Bit data]'
'*\[-E\]*' '-E[disable an escape character]'
'*\[-K\]*' '-K[no automatic login]'
@@ -52,16 +52,16 @@ _arguments -C -s \
case "$state" in
ssl)
_values -w 'SSL parameter' \
- 'debug[Send SSL debugging info to stderr]' \
- '(nossl)ssl[Negotiate SSL connection]' \
- '(ssl)nossl[Switch off SSL negotiation]' \
- 'certrequired[Require server certificate]' \
- 'secure[No fallback to unencrypted mode]' \
- 'verbose[Be verbose about certificates, etc.]' \
- 'verify[Set SSL verify flags]:int:' \
- 'cert[Specify certificate file]:certificate file:_path_files' \
- 'key[Specify key file]:key file:_path_files' \
- 'cipher[Set preferred cipher list]:ciphers:'
+ 'debug[send SSL debugging info to stderr]' \
+ '(nossl)ssl[negotiate SSL connection]' \
+ '(ssl)nossl[switch off SSL negotiation]' \
+ 'certrequired[require server certificate]' \
+ 'secure[no fallback to unencrypted mode]' \
+ 'verbose[be verbose about certificates, etc.]' \
+ 'verify[set SSL verify flags]:int' \
+ 'cert[specify certificate file]:certificate file:_path_files' \
+ 'key[specify key file]:key file:_path_files' \
+ 'cipher[set preferred cipher list]:cipher' && ret=0
;;
hosts)
diff --git a/Completion/Unix/Command/_tidy b/Completion/Unix/Command/_tidy
index fce719026..ec2d74238 100644
--- a/Completion/Unix/Command/_tidy
+++ b/Completion/Unix/Command/_tidy
@@ -123,6 +123,4 @@ _arguments \
'--css-prefix:CSS class name:' \
'--accessibility-check:priority level:(${access[@]})' \
'--newline:newline character:(LF CRLF CR)' \
- '*:file:_files' && return
-
-return 1
+ '*:file:_files'
diff --git a/Completion/Unix/Command/_tmux b/Completion/Unix/Command/_tmux
index 5a4a2d71f..f0cc4be37 100644
--- a/Completion/Unix/Command/_tmux
+++ b/Completion/Unix/Command/_tmux
@@ -1490,7 +1490,7 @@ function __tmux-windows() {
# And here is the actual _tmux(), that puts it all together:
function _tmux() {
local curcontext="${curcontext}"
- local mode state ret
+ local mode state ret=1
local -a args
local -x tmuxcommand
unset tmux_describe
@@ -1508,22 +1508,22 @@ function _tmux() {
'-v[request verbose logging]'
'*:: :->subcommand_or_options'
)
- _arguments -C -s -w ${args} && return
+ _arguments -C -s -w ${args} && ret=0
if [[ ${state} == "subcommand_or_options" ]]; then
if (( CURRENT == 1 )) ; then
zstyle -s ":completion:${curcontext}:subcommands" mode mode || mode='both'
if [[ ${mode} == 'commands' ]]; then
- _describe -t subcommands 'tmux commands' _tmux_commands
+ _describe -t subcommands 'tmux commands' _tmux_commands && ret=0
elif [[ ${mode} == 'aliases' ]]; then
- _describe -t subcommands 'tmux aliases' _tmux_aliases
+ _describe -t subcommands 'tmux aliases' _tmux_aliases && ret=0
else
- _describe -t subcommands 'tmux commands and aliases' _tmux_commands -- _tmux_aliases
+ _describe -t subcommands 'tmux commands and aliases' _tmux_commands -- _tmux_aliases && ret=0
fi
else
if (( ${+commands[tmux]} == 0 )); then
_message '`tmux'\'' not found in $path; sub-cmd completions disabled.'
- return 0
+ return
fi
tmuxcommand="${words[1]}"
if [[ -n ${_tmux_aliasmap[$tmuxcommand]} ]] ; then
@@ -1545,6 +1545,7 @@ function _tmux() {
_call_function ret _tmux-${tmuxcommand}
fi
fi
+ return ret
}
# description generation follows; only done on 1st _tmux call.
diff --git a/Completion/Unix/Command/_uname b/Completion/Unix/Command/_uname
index 9b4663b8a..414a82a87 100644
--- a/Completion/Unix/Command/_uname
+++ b/Completion/Unix/Command/_uname
@@ -1,53 +1,81 @@
#compdef uname
typeset -A _uname_args
+local -a args
+
+case $LANG in
+ de_*)
+ _uname_args=(
+ all "alle Grundinformationen ausgeben"
+ kernel-name "Namen des Kernels ausgeben"
+ nodename "Netzwerknamen der Maschine ausgeben"
+ kernel-release "Release-Nummer des Kernels ausgeben"
+ kernel-version "Version des Kernels ausgeben"
+ os-release "Release-Nummer des Betriebssystems ausgeben"
+ machine "Maschinentyp (Hardware) ausgeben"
+ processor "Typ des Prozessors ausgeben"
+ hardware-platform "Hardwareplattform ausgeben"
+ operating-system "Namen des Betriebssystems ausgeben"
+ help "Hilfe anzeigen und beenden"
+ version "Versionsinformation anzeigen und beenden"
+ )
+ ;;
+ (*)
+ _uname_args=(
+ all "print all basic information"
+ kernel-name "print kernel name"
+ nodename "print network node hostname"
+ kernel-release "print kernel release"
+ kernel-version "print kernel version"
+ os-release "print operating system release level"
+ machine "print machine hardware name"
+ processor "print processor type"
+ hardware-platform "print hardware platform"
+ operating-system "print name of the operating system"
+ help "display help information"
+ version "output version information and exit"
+ )
+ ;;
+esac
if _pick_variant gnu="Free Soft" unix --version; then
- case $LANG in
- (de_DE.UTF-8)
- _uname_args=(
- all "alle Informationen ausgeben"
- kernel-name "Namen des Kernels ausgeben"
- nodename "Netzwerknamen der Maschine ausgeben"
- kernel-release "Release-Nummer des Kernels ausgeben"
- kernel-version "Version des Kernels ausgeben"
- machine "Maschinentyp (Hardware) ausgeben"
- processor "Typ des Prozessors ausgeben (oder das Wort unknown)"
- hardware-platform "Hardwareplattform ausgeben (oder das Wort unknown)"
- operating-system "Namen des Betriebssystems ausgeben"
- help "diese Hilfe anzeigen und beenden"
- version "Versionsinformation anzeigen und beenden"
- )
+ _arguments -s \
+ '(-)'{--all,-a}'['$_uname_args[all]']' \
+ '(--kernel-name -s)'{--kernel-name,-s}'['$_uname_args[kernel-name]']' \
+ '(--nodename -n)'{--nodename,-n}'['$_uname_args[nodename]']' \
+ '(--kernel-release -r)'{--kernel-release,-r}'['$_uname_args[kernel-release]']' \
+ '(--kernel-version -v)'{--kernel-version,-v}'['$_uname_args[kernel-version]']' \
+ '(--machine -m)'{--machine,-m}'['$_uname_args[machine]']' \
+ '(--processor -p)'{--processor,-p}'['$_uname_args[processor]']' \
+ '(--hardware-platform -i)'{--hardware-platform,-i}'['$_uname_args[hardware-platform]']' \
+ '(--operating-system -o)'{--operating-system,-o}'['$_uname_args[operating-system]']' \
+ '(-)--help['$_uname_args[help]']' \
+ '(-)--version['$_uname_args[version]']'
+else
+ args=(
+ "(-m -n -r -s -v)-a[${_uname_args[all]}]"
+ '-m[print hardware class]'
+ "-n[${_uname_args[nodename]}]"
+ "-p[${_uname_args[processor]}]"
+ "-r[${_uname_args[os-release]}]"
+ "-s[${_uname_args[operating-system]}]"
+ '-v[print detailed operating system version]'
+ )
+ case $OSTYPE in
+ freebsd*|dragonfly*) args+=( '-i[print kernel ident]' ) ;|
+ freebsd<10->.*)
+ args+=(
+ '-K[print FreeBSD kernel version]'
+ '-U[print FreeBSD user environment version]'
+ )
;;
- (*)
- _uname_args=(
- all "print all information"
- kernel-name "print the kernel name"
- nodename "print the network node hostname"
- kernel-release "print the kernel release"
- kernel-version "print the kernel version"
- machine "print the machine hardware name"
- processor "print the processor type or \"unknown\""
- hardware-platform "print the hardware platform or \"unknown\""
- operating-system "print the operating system"
- help "display this help and exit"
- version "output version information and exit"
- )
+ solaris*)
+ args+=(
+ '-i[print platform name]'
+ '-S[set system name]:system name'
+ '-X[print expanded system information]'
+ )
;;
esac
-
- _arguments \
- '(--all -a)'{--all,-a}'['$_uname_args[all]']' \
- '(--kernel-name -s)'{--kernel-name,-s}'['$_uname_args[kernel-name]']' \
- '(--nodename -n)'{--nodename,-n}'['$_uname_args[nodename]']' \
- '(--kernel-release -r)'{--kernel-release,-r}'['$_uname_args[kernel-release]']' \
- '(--kernel-version -v)'{--kernel-version,-v}'['$_uname_args[kernel-version]']' \
- '(--machine -m)'{--machine,-m}'['$_uname_args[machine]']' \
- '(--processor -p)'{--processor,-p}'['$_uname_args[processor]']' \
- '(--hardware-platform -i)'{--hardware-platform,-i}'['$_uname_args[hardware-platform]']' \
- '(--operating-system -o)'{--operating-system,-o}'['$_uname_args[operating-system]']' \
- '--help['$_uname_args[help]']' \
- '--version['$_uname_args[version]']'
-else
-# TODO add options of a NON GNU implementation
+ _arguments -s $args
fi
diff --git a/Completion/Unix/Command/_uniq b/Completion/Unix/Command/_uniq
index dcd7a6f49..1cf12357b 100644
--- a/Completion/Unix/Command/_uniq
+++ b/Completion/Unix/Command/_uniq
@@ -1,4 +1,4 @@
-#compdef uniq
+#compdef uniq guniq
local args
@@ -20,7 +20,7 @@ args=(
if ! _pick_variant gnu=Free\ Soft unix --version; then
local optchars="cdufs"
- if [[ "$OSTYPE" == (darwin|freebsd)* ]]; then
+ if [[ "$OSTYPE" == (darwin|dragonfly|freebsd)* ]]; then
optchars="${optchars}i"
fi
args=( ${(M)args:#(|\*)(|\(*\))-[$optchars]*} )
diff --git a/Completion/Unix/Command/_user_admin b/Completion/Unix/Command/_user_admin
index 281171d17..31ccbf1c2 100644
--- a/Completion/Unix/Command/_user_admin
+++ b/Completion/Unix/Command/_user_admin
@@ -45,6 +45,7 @@ if [[ $service = user* ]]; then
"(-L -p)-U[unlock user's password]"
)
args+=(
+ '-a[append groups]'
'-l[specify new user name]:new username'
':username:_users'
)
diff --git a/Completion/Unix/Command/_vcsh b/Completion/Unix/Command/_vcsh
index 47dbd9e69..00aed7d28 100644
--- a/Completion/Unix/Command/_vcsh
+++ b/Completion/Unix/Command/_vcsh
@@ -1,60 +1,29 @@
#compdef vcsh
function __vcsh_repositories () {
- local expl
local -a repos
- repos=( ${(f)"$(command vcsh list)"} )
- _describe -t repos 'repositories' repos
-}
-
-function __vcsh_not_implemented_yet () {
- _message "Subcommand completion '${1#*-}': not implemented yet"
+ repos=( ${(f)"$(_call_program repositories vcsh list)"} )
+ _describe -t repositories 'repository' repos
}
function _vcsh-clone () {
- __vcsh_not_implemented_yet "$0" #TODO
-}
-
-function _vcsh-delete () {
- (( CURRENT == 2 )) && __vcsh_repositories
+ _default #TODO
}
-function _vcsh-enter () {
- (( CURRENT == 2 )) && __vcsh_repositories
-}
-
-function _vcsh-help () {
- _nothing
-}
-
-function _vcsh-init () {
- _nothing
-}
-
-function _vcsh-list () {
- _nothing
-}
-
-function _vcsh-list-tracked () {
- _nothing
-}
-
-function _vcsh-list-tracked-by () {
- (( CURRENT == 2 )) && __vcsh_repositories
-}
-
-function _vcsh-pull () {
- _nothing
-}
-
-function _vcsh-push () {
- _nothing
-}
+local func
+for func in help init list list-tracked pull push version; do
+ _vcsh-$func() { _nothing }
+done
+for func in delete enter list-tracked-by upgrade write-gitignore; do
+ _vcsh-$func() { (( CURRENT == 2 )) && __vcsh_repositories }
+done
function _vcsh-rename () {
- (( CURRENT == 2 )) && __vcsh_repositories
- (( CURRENT == 3 )) && _message "new repository name"
- (( CURRENT > 3 )) && _nothing
+ case $CURRENT in
+ 2) __vcsh_repositories ;;
+ 3) _message "new repository name" ;;
+ *) _nothing ;;
+ esac
}
function _vcsh-run () {
@@ -66,24 +35,8 @@ function _vcsh-run () {
fi
}
-function _vcsh-upgrade () {
- (( CURRENT == 2 )) && __vcsh_repositories
-}
-
-function _vcsh-version () {
- _nothing
-}
-
-function _vcsh-which () {
- _files
-}
-
-function _vcsh-write-gitignore () {
- (( CURRENT == 2 )) && __vcsh_repositories
-}
-
function _vcsh () {
- local curcontext="${curcontext}"
+ local curcontext="${curcontext}" ret=1
local state vcshcommand
local -a args subcommands
@@ -112,24 +65,25 @@ function _vcsh () {
'*:: :->subcommand_or_options_or_repo'
)
- _arguments -C ${args} && return
+ _arguments -C ${args} && ret=0
if [[ ${state} == "subcommand_or_options_or_repo" ]]; then
if (( CURRENT == 1 )); then
- _describe -t subcommands 'vcsh sub-commands' subcommands
- __vcsh_repositories
+ _describe -t subcommands 'vcsh sub-commands' subcommands && ret=0
+ __vcsh_repositories && ret=0
else
vcshcommand="${words[1]}"
if ! (( ${+functions[_vcsh-$vcshcommand]} )); then
# There is no handler function, so this is probably the name
# of a repository. Act accordingly.
- _dispatch git git
+ _dispatch git git && ret=0
else
curcontext="${curcontext%:*:*}:vcsh-${vcshcommand}:"
_call_function ret _vcsh-${vcshcommand}
fi
fi
fi
+ return ret
}
_vcsh "$@"
diff --git a/Completion/Unix/Command/_vim b/Completion/Unix/Command/_vim
index 42e5058ec..021054d47 100644
--- a/Completion/Unix/Command/_vim
+++ b/Completion/Unix/Command/_vim
@@ -1,4 +1,4 @@
-#compdef vim exim gvim gex gview rvim rview rgvim rgview evim eview vimdiff gvimdiff
+#compdef vim exim gvim gex gview nvim rvim rview rgvim rgview evim eview vimdiff gvimdiff
(( $+functions[_vim_files] )) ||
_vim_files () {
diff --git a/Completion/Unix/Command/_wc b/Completion/Unix/Command/_wc
new file mode 100644
index 000000000..49a03ba2c
--- /dev/null
+++ b/Completion/Unix/Command/_wc
@@ -0,0 +1,26 @@
+#compdef wc gwc
+
+local args
+
+args=(
+ '(-c --bytes)'{-c,--bytes}'[print byte counts]'
+ '(-C -m --chars)'{-m,--chars}'[print character counts]'
+ '(-w --words)'{-w,--words}'[print word counts]'
+ '(-l --lines)'{-l,--lines}'[print line counts]'
+)
+
+if _pick_variant gnu=GNU unix --version; then
+ args+=(
+ '(*)--files0-from=[read NUL-terminated file list from specified file]:file:_files'
+ '(-L --max-line-length)'{-L,--max-line-length}'[print longest line lengths]'
+ )
+else
+ args=( -A "-*" "${(@)args:#(|\(*\))(|\*)--*}" )
+ case $OSTYPE in
+ freebsd*|netbsd*) args+=( '-L[print longest line lengths]' ) ;;
+ openbsd*) args+=( '-h[human readable: use unit suffixes]' ) ;;
+ solaris*) args+=( ${${(M)args:#*-m\[*}//-m\[/-C\[} ) ;;
+ esac
+fi
+
+_arguments -s -S $args '*:file:_files'
diff --git a/Completion/Unix/Command/_xargs b/Completion/Unix/Command/_xargs
index f727ed8b7..d8c0a0ec2 100644
--- a/Completion/Unix/Command/_xargs
+++ b/Completion/Unix/Command/_xargs
@@ -1,15 +1,63 @@
-#compdef xargs
-
-_arguments \
- '(-t)-p[prompt user for each command]' \
- '(-p)-t[verbose - echo each command]' \
- '-x[exit if max size exceeded]' \
- -{e-,E}':end-of-file string:' \
- '(-x -I)-i-:replacement string for lines:' \
- '(-x -i)-I:replacement string for lines:' \
- '(-n -L -x)-l-:number of input lines:' \
- '(-n -l)-L:number of input lines:' \
- '(-l -L)-n-:maximum number of arguments:' \
- '-s-:maximum command line length:' \
+#compdef xargs gxargs
+
+local args variant
+
+args=(
+ '(-l -L --max-lines -n --max-args -s --max-chars)'{-n+,--max-args=}'[specify maximum number of arguments for each line]:number of arguments' \
+ '(-l -L --max-lines -n --max-args -s --max-chars)'{-s+,--max-chars=}'[specify maximum characters per command line]:maximum command line length'
+ '(-p --verbose -t --interactive)'{-p,--interactive}'[prompt user for each command]'
+ '(-p --verbose -t --interactive)'{-t,--verbose}'[verbose - echo each command]'
+ '(-x --exit)'{-x,--exit}'[exit if max size exceeded]'
+)
+
+_pick_variant -r variant gnu=GNU $OSTYPE --version
+
+case $variant in
+ gnu|darwin*|freebsd*|netbsd*|openbsd*)
+ args+=(
+ '(--max-procs -P)'{-P,--max-procs}'[parallel mode]:maximum processes' '!-r'
+ )
+ ;|
+ dragonfly*|darwin*|freebsd*|netbsd*|openbsd*)
+ args=( "${(@)args:#(|\(*\))(|\*)--*}"
+ '-0[expect NUL characters as input separators]'
+ '-J[specify marker for position of arguments]:marker'
+ '-R[specify maximum arguments that -I will replace in]:replacements'
+ )
+ ;|
+ freebsd*|netbsd*)
+ args+=(
+ '-S[space that -I can use for replacements]:size (bytes) [255]'
+ )
+ ;;
+ solaris*|gnu)
+ args+=(
+ '(-x -I)'{-i-,--replace}'[specify replacement string for command line]::replacement string'
+ '(-n -L -x)-l-[call program for every number of lines]:number of input lines'
+ '(-E -e --eof)'{-e-,--eof=}'[specify EOF marker]:end-of-file marker'
+ )
+ ;|
+ solaris*) args=( "${(@)args:#(|\(*\))(|\*)--*}" ) ;|
+ solaris2.<11->)
+ args+=( '-0[expect NUL characters as input separators]' )
+ ;;
+ gnu)
+ args+=(
+ '(-a --arg-file)'{-a+,--arg-file=}'[read input items from specified file]:file:_files'
+ '(-0 --null -d --delimiter)'{-0,--null}'[expect NUL characters as input separators]'
+ '(-d --delimiter -0 --null)'{-d+,--delimiter=}'[specify delimiter of input items]:delimiter'
+ '(-l -L --max-lines -n --max-args -s --max-chars)--max-lines=-[call program for every number of lines]::number of input lines'
+ '(-r --no-run-if-empty)'{-r,--no-run-if-empty}"[don't run command in absence of input]"
+ '(- *)--help[show help information]'
+ '(- *)--version[show version information]'
+ '--show-limits[show OS imposed limits to command-line length]'
+ )
+ ;;
+esac
+
+_arguments -s $args \
+ '-E[specify EOF marker]:end-of-file marker' \
+ '(-x -i)-I[specify replacement string for command line]:replacement string' \
+ '(-n -l)-L[call program for every number of lines]:number of input lines' \
'(-):command: _command_names -e' \
'*::args: _normal'
diff --git a/Completion/Unix/Command/_xxd b/Completion/Unix/Command/_xxd
new file mode 100644
index 000000000..1a822553c
--- /dev/null
+++ b/Completion/Unix/Command/_xxd
@@ -0,0 +1,45 @@
+#compdef xxd
+
+local arguments
+
+# Output options compatibility matrix
+#
+# 0 - options conflict
+# 1 - options coexist
+#
+# (The matrix is symmetric, so implied values are not shown.)
+#
+# bEipru
+# bx10000
+# E-x0001
+# i--x001
+# p---x11
+# r----x0
+# u-----x
+
+# xxd supports either double or single dashes on long options.
+[[ -prefix -- ]] && compset -P -
+
+arguments=(
+ # output options
+ '(-b -bits -i -include -p -postscript -plain -ps -r -reverse -u -uppercase)'{-b,-bits}'[output in binary digits, rather than hex]'
+ '( -E -EBCDIC -i -include -p -postscript -plain -ps -r -reverse )'{-E,-EBCDIC}'[print human-readable part in EBCDIC rather than ASCII]'
+ '(-b -bits -E -EBCDIC -i -include -p -postscript -plain -ps -r -reverse )'{-i,-include}'[output in C include file style]'
+ '(-b -bits -E -EBCDIC -i -include -p -postscript -plain -ps )'{-p,-postscript,-plain,-ps}'[read or write a plain hexdump (no line numbers or ASCII rendering)]'
+
+ '(-b -bits -E -EBCDIC -i -include -r -reverse -u -uppercase)'{-r,-reverse}'[reverse mode\: read a hex dump and output binary data]'
+ '(-b -bits -r -reverse -u -uppercase)'{-u,-uppercase}'[output upper-case hex digits]'
+
+ {-h,-help}'[display usage message]'
+ {-v,-version}'[show program version]'
+ '*'{-a,-autoskip}"[a single '*' replaces runs of NUL (toggleable)]"
+
+ {-c+,-cols}'[specify number of octets per line]: :_guard "[0-9a-fA-Fx]#" "number of octets per line"'
+ {-g+,-groupsize}'[specify the number of octets per group]: :_guard "[0-9]#" "number of octets per group"'
+ {-l+,-len}'[specify number of octets to output]: :_guard "[0-9]#" "number of octets to output"'
+ {-s,-skip,-seek}'[specify file offset to dump from]: :_guard "[0-9]#" "file offset to dump from (absolute or relative)"'
+
+ ':files:_files'
+)
+
+_arguments -S $arguments
diff --git a/Completion/Unix/Command/_zpool b/Completion/Unix/Command/_zpool
index 0f18eefb5..03ebd0642 100644
--- a/Completion/Unix/Command/_zpool
+++ b/Completion/Unix/Command/_zpool
@@ -12,7 +12,7 @@ _zpool() {
)
versions=(
- ${${${(M)"${(f)$(zpool upgrade -v)}":#[[:space:]]#<->*}##[[:space:]]}%%[[:space:]]*}
+ ${${${(M)"${(f)$(_call_program versions zpool upgrade -v)}":#[[:space:]]#<->*}##[[:space:]]}%%[[:space:]]*}
)
ro_props=(
@@ -87,15 +87,12 @@ _zpool() {
if [[ $service == "zpool" ]]; then
_arguments -C -A "-*" \
- '-\?[Help]' \
- '*::command:->subcmd' && return 0
+ '-\?[show help information]' \
+ '1:subcommand:compadd -a subcmds' \
+ '*:: :->subcmd' && return
- if (( CURRENT == 1 )); then
- _wanted commands expl "zpool subcommand" compadd -a subcmds
- return
- fi
service="$words[1]"
- curcontext="${curcontext%:*}=$service:"
+ curcontext="${curcontext%:*}-$service:"
fi
case $service in
diff --git a/Completion/Unix/Type/_cmdstring b/Completion/Unix/Type/_cmdstring
new file mode 100644
index 000000000..fb19fdb76
--- /dev/null
+++ b/Completion/Unix/Type/_cmdstring
@@ -0,0 +1,6 @@
+#autoload
+
+# This is for a quoted argument that will be interpreted as a command.
+
+compset -q
+_normal
diff --git a/Completion/Unix/Type/_diff_options b/Completion/Unix/Type/_diff_options
index 472838cda..d76c265ca 100644
--- a/Completion/Unix/Type/_diff_options
+++ b/Completion/Unix/Type/_diff_options
@@ -103,17 +103,20 @@ if _pick_variant -c $cmd gnu=GNU unix -v; then
else
case $OSTYPE in
solaris2.<9->)
- args=( '(-c -e -f -C)-u[output a unified diff]' )
+ args=(
+ '(-c -e -f -C -U)-u[output a unified diff]'
+ '(-c -e -f -C -u)-U[output a unified diff]:lines of context'
+ )
;&
solaris*)
args+=(
'-i[case insensitive]'
'-t[expand tabs to spaces]'
'-w[ignore all white space]'
- '(-c -e -f -n -u -h -D)-C+[output a context diff]:number of lines of copied context'
- '(-c -e -f -n -u -C -D)-h[do a fast, half-hearted job]'
- '(-c -e -f -u -h -C -D)-n[reversed ed script]'
- '(-c -e -f -n -u -h -C)-D[output merged file with preprocessor directives]:preprocessor symbol'
+ '(-c -e -f -n -u -U -h -D)-C+[output a context diff]:lines of context'
+ '(-c -e -f -n -u -U -C -D)-h[do a fast, half-hearted job]'
+ '(-c -e -f -u -U -h -C -D)-n[reversed ed script]'
+ '(-c -e -f -n -u -U -h -C)-D[output merged file with preprocessor directives]:preprocessor symbol'
'-l[output through pr]'
'-s[report on identical files]'
'-S+[set first file in comparison]:start with file:_files'
diff --git a/Completion/Unix/Type/_directories b/Completion/Unix/Type/_directories
index ab1b50b4f..2125645fe 100644
--- a/Completion/Unix/Type/_directories
+++ b/Completion/Unix/Type/_directories
@@ -1,4 +1,4 @@
-#compdef rmdir df dircmp -P -value-,*path,-default-
+#compdef rmdir zf_rmdir dircmp -P -value-,*path,-default-
local expl
diff --git a/Completion/Unix/Type/_file_systems b/Completion/Unix/Type/_file_systems
index 3415bb163..2d903d471 100644
--- a/Completion/Unix/Type/_file_systems
+++ b/Completion/Unix/Type/_file_systems
@@ -12,18 +12,19 @@ case $OSTYPE in
[[ -r /proc/filesystems ]] &&
fss+=( ${$(</proc/filesystems)#nodev} )
[[ -r /etc/filesystems ]] &&
- fss+=( ${$(</etc/filesystems)#\*} )
+ fss+=( ${${${(f)"$(</etc/filesystems)"}:#\#*}#\*} )
;;
osf*) fss=( advfs ufs nfs mfs cdfs ) ;;
solaris*) fss=( ufs nfs hsfs s5fs pcfs cachefs tmpfs ) ;;
dragonfly*)
- fss=( cd9660 devfs ext2fs fdesc kernfs linprocfs mfs msdos nfs
+ fss=( cd9660 devfs ext2fs fdesc kernfs linprocfs mfs msdos nfs
ntfs null nwfs portal procfs std udf ufs umap union )
;;
freebsd*)
+ fss=( ${${(f)"$(_call_program fstypes lsvfs)"}[3,-1]%% *} ) ||
fss=( cd9660 devfs ext2fs fdescfs kernfs linprocfs linsysfs mfs msdosfs nfs
- ntfs nullfs nwfs portalfs procfs smbfs std udf ufs unionfs
- reiserfs xfs)
+ ntfs nullfs nwfs portalfs procfs smbfs std tmpfs udf ufs unionfs
+ reiserfs xfs zfs )
;;
darwin*)
fss=( afp cd9660 cddafs devfs fdesc hfs lfs msdos nfs
@@ -36,11 +37,3 @@ case $OSTYPE in
esac
_wanted fstypes expl 'file system type' compadd "$@" -M 'L:|no=' -a "$@" - fss
-
-
-
-
-
-
-
-
diff --git a/Completion/Unix/Type/_files b/Completion/Unix/Type/_files
index 0f6fcd6ff..e628cb39e 100644
--- a/Completion/Unix/Type/_files
+++ b/Completion/Unix/Type/_files
@@ -121,9 +121,13 @@ for def in "$pats[@]"; do
if _path_files -g "$pat" "$opts[@]" "$expl[@]"; then
ret=0
elif [[ $PREFIX$SUFFIX != */* ]] && zstyle -a ":completion:${curcontext}:$tag" recursive-files rfiles; then
+ local subtree
for rfile in $rfiles; do
if [[ $PWD/ = ${~rfile} ]]; then
- for prepath in **/*(/); do
+ if [[ -z $subtree ]]; then
+ subtree=( **/*(/) )
+ fi
+ for prepath in $subtree; do
oprefix=$PREFIX
PREFIX=$prepath/$PREFIX
_path_files -g "$pat" "$opts[@]" "$expl[@]" && ret=0
diff --git a/Completion/Unix/Type/_find_net_interfaces b/Completion/Unix/Type/_find_net_interfaces
new file mode 100644
index 000000000..0c7033519
--- /dev/null
+++ b/Completion/Unix/Type/_find_net_interfaces
@@ -0,0 +1,42 @@
+#autoload
+
+# This can be called independently of completion. It returns
+# arrays net_intf_disp and net_intf_list which the caller should
+# make local.
+
+local sep list
+
+# Make sure needed tools are in the path.
+local PATH=$PATH
+PATH=/sbin:$PATH
+
+case $OSTYPE in
+ aix*)
+ net_intf_list=( ${(f)"$(lsdev -C -c if -F 'name:description')"} )
+ if zstyle -T ":completion:${curcontext}" verbose; then
+ zstyle -s ":completion:${curcontext}:" list-separator sep || sep=--
+ zformat -a list " $sep " "$net_intf_list[@]"
+ net_intf_disp=(-ld list)
+ fi
+ ;;
+ darwin*|freebsd*|dragonfly*) net_intf_list=( $(ifconfig -l) ) ;;
+ irix*) net_intf_list=( ${${${(f)"$(/usr/etc/netstat -i)"}%% *}[2,-1]} ) ;;
+ *linux*)
+ if (( $+commands[ip] )); then
+ net_intf_list=( ${${(m)${(f)"$(ip -o link)"}#*: }%%: *} )
+ fi
+ ;&
+
+ *)
+ if [[ ${#net_intf_list} -eq 0 ]]; then
+ # linux's deprecated ifconfig may truncate long interface names
+ net_intf_list=( $(ifconfig -a 2>/dev/null | sed -n 's/^\([^ :]*\).*/\1/p') )
+ if [[ -d /proc/sys/net/ipv4/conf ]]; then
+ # On linux we used to use the following as the default.
+ # However, we now use ip or ifconfig since it finds additional devices such
+ # as tunnels. So only do this if that didn't work.
+ net_intf_list=( /proc/sys/net/ipv4/conf/*~*(all|default)(N:t) )
+ fi
+ fi
+ ;;
+esac
diff --git a/Completion/Unix/Type/_net_interfaces b/Completion/Unix/Type/_net_interfaces
index 2cac3e3bb..5be66d7d1 100644
--- a/Completion/Unix/Type/_net_interfaces
+++ b/Completion/Unix/Type/_net_interfaces
@@ -1,42 +1,9 @@
#compdef ifup ifdown
-local expl list intf sep
-local -a disp
+local expl
+local -a net_intf_disp net_intf_list
-# Make sure needed tools are in the path.
-local PATH=$PATH
-PATH=/sbin:$PATH
-
-case $OSTYPE in
- aix*)
- intf=( ${(f)"$(lsdev -C -c if -F 'name:description')"} )
- if zstyle -T ":completion:${curcontext}" verbose; then
- zstyle -s ":completion:${curcontext}:" list-separator sep || sep=--
- zformat -a list " $sep " "$intf[@]"
- disp=(-ld list)
- fi
- ;;
- darwin*|freebsd*|dragonfly*) intf=( $(ifconfig -l) ) ;;
- irix*) intf=( ${${${(f)"$(/usr/etc/netstat -i)"}%% *}[2,-1]} ) ;;
- *linux*)
- if (( $+commands[ip] )); then
- intf=( ${${(m)${(f)"$(ip -o link)"}#*: }%%: *} )
- fi
- ;&
-
- *)
- if [[ ${#intf} -eq 0 ]]; then
- # linux's deprecated ifconfig may truncate long interface names
- intf=( $(ifconfig -a 2>/dev/null | sed -n 's/^\([^ :]*\).*/\1/p') )
- if [[ -d /proc/sys/net/ipv4/conf ]]; then
- # On linux we used to use the following as the default.
- # However, we now use ip or ifconfig since it finds additional devices such
- # as tunnels. So only do this if that didn't work.
- intf=( /proc/sys/net/ipv4/conf/*~*(all|default)(N:t) )
- fi
- fi
- ;;
-esac
+_find_net_interfaces
_wanted interfaces expl 'network interface' \
- compadd "$@" "$disp[@]" - "${(@)intf%%:*}"
+ compadd "$@" "$net_intf_disp[@]" - "${(@)net_intf_list%%:*}"
diff --git a/Completion/Unix/Type/_path_files b/Completion/Unix/Type/_path_files
index ed3f54de3..c64ebf58c 100644
--- a/Completion/Unix/Type/_path_files
+++ b/Completion/Unix/Type/_path_files
@@ -609,8 +609,15 @@ for prepath in "$prepaths[@]"; do
tmp3="$pre$suf"
tpre="$pre"
tsuf="$suf"
- [[ -n "${prepath}${realpath}${testpath}" ]] &&
+ if [[ -n "${prepath}${realpath}${testpath}" ]]
+ then
+ if [[ -o nocaseglob ]]
+ then
+ tmp1=( "${(@)tmp1#(#i)${prepath}${realpath}${testpath}}" )
+ else
tmp1=( "${(@)tmp1#${prepath}${realpath}${testpath}}" )
+ fi
+ fi
while true; do
diff --git a/Completion/Unix/Type/_pdf b/Completion/Unix/Type/_pdf
index f20f94e79..60cee84ee 100644
--- a/Completion/Unix/Type/_pdf
+++ b/Completion/Unix/Type/_pdf
@@ -1,4 +1,4 @@
-#compdef pdf2dsc pdf2ps pdfimages pdfinfo pdftopbm pdftops pdftotext pdfopt pdffonts kpdf apvlv evince epdfview
+#compdef pdf2dsc pdf2ps pdfimages pdfinfo pdftopbm pdftops pdftotext pdfopt pdffonts kpdf apvlv epdfview
local expl ext=''
diff --git a/Completion/Unix/Type/_perl_modules b/Completion/Unix/Type/_perl_modules
index 1b61043e7..d27a7f7af 100644
--- a/Completion/Unix/Type/_perl_modules
+++ b/Completion/Unix/Type/_perl_modules
@@ -71,7 +71,7 @@ _perl_modules () {
perl_modules=_unknown_perl_modules$with_pod
fi
- if ( [[ ${(P)+perl_modules} -eq 0 ]] || _cache_invalid $perl_modules ) &&
+ if ( [[ ${(P)+perl_modules} -eq 0 ]] || _cache_invalid ${perl_modules#_} ) &&
! _retrieve_cache ${perl_modules#_};
then
if zstyle -t ":completion:${curcontext}:modules" try-to-use-pminst &&
diff --git a/Completion/Unix/Type/_pids b/Completion/Unix/Type/_pids
index 3c6a76561..cf9000538 100644
--- a/Completion/Unix/Type/_pids
+++ b/Completion/Unix/Type/_pids
@@ -1,4 +1,4 @@
-#compdef pflags pcred pmap pldd psig pstack pfiles pwdx pstop prun pwait ptree
+#compdef pflags pcred pmap pldd psig pstack pfiles pwdx pstop prun pwait
# If given the `-m <pattern>' option, this tries to complete only pids
# of processes whose command line match the `<pattern>'.
diff --git a/Completion/Unix/Type/_python_modules b/Completion/Unix/Type/_python_modules
new file mode 100644
index 000000000..b30848d83
--- /dev/null
+++ b/Completion/Unix/Type/_python_modules
@@ -0,0 +1,44 @@
+#autoload
+
+_python_module_caching_policy () {
+ local -a newer
+ # rebuild if cache does not exist or is more than a week old
+ newer=( "$1"(Nmw-1) )
+ return $#newer
+}
+
+_python_modules () {
+ local update_policy python expl
+
+ case $words[1] in
+ (python*) python=$words[1] ;;
+ (pydoc*) python=${words[1]/#pydoc/python} ;;
+ (*) python="python" ;;
+ esac
+ local cache_id=${${python//[^[:alnum:]]/_}#_}_modules
+ local array_name=_${cache_id}
+
+ zstyle -s ":completion:${curcontext}:" cache-policy update_policy
+ [[ -z "$update_policy" ]] && \
+ zstyle ":completion:${curcontext}:" \
+ cache-policy _python_module_caching_policy
+
+ if ( [[ ${(P)+array_name} -eq 0 ]] || _cache_invalid $cache_id ) &&
+ ! _retrieve_cache $cache_id; then
+
+ local script='import sys, pydoc
+def f(p,m,d):
+ if m.find(".") < 0: sys.stdout.write(m+"\n")
+pydoc.ModuleScanner().run(f)'
+
+ typeset -agU $array_name
+ set -A $array_name \
+ $(_call_program modules $python -c ${(q)script} 2>/dev/null)
+
+ _store_cache $cache_id $array_name
+ fi
+
+ _wanted modules expl module compadd "$@" -a -- $array_name
+}
+
+_python_modules "$@"
diff --git a/Completion/Unix/Type/_users b/Completion/Unix/Type/_users
index 3c8c7027b..2ea3b1455 100644
--- a/Completion/Unix/Type/_users
+++ b/Completion/Unix/Type/_users
@@ -3,8 +3,8 @@
local expl users
if zstyle -a ":completion:${curcontext}:users" users users; then
- _wanted users expl user compadd "$@" -a - users
- return 0
+ _wanted users expl user compadd "$@" -a - users
+ return
fi
_wanted users expl user compadd "$@" -k - userdirs
diff --git a/Completion/X/Command/_rdesktop b/Completion/X/Command/_rdesktop
new file mode 100644
index 000000000..0bd08d932
--- /dev/null
+++ b/Completion/X/Command/_rdesktop
@@ -0,0 +1,71 @@
+#compdef rdesktop
+
+local curcontext="$curcontext" state line expl redir ret=1
+typeset -A opt_args
+
+_arguments -C -s \
+ '-u[username]:username:_users' \
+ '-d[domain]:domain' \
+ '-s[shell]:startup shell' \
+ '-c[working directory]:directory:_directories' \
+ '-p[password]:password' \
+ '-n[hostname]:host:_hosts' \
+ '-k[keyboard map]:keyboard map' \
+ '(-f)-g[geometry]:geometry (WxH)' \
+ '(-g)-f[fullscreen mode]' \
+ '-b[force server to use bitmaps for screen updates]' \
+ '-B[use X server backing store]' \
+ '-E[disable encryption]' \
+ "-m[don't send mouse motion events]" \
+ '-C[use private colormap]' \
+ '-D[hide window decorations]' \
+ '-K[do not override window manager key bindings]' \
+ '-S[single application mode]' \
+ '-T[set window title]:title' \
+ '-N[enable numlock synchronisation]' \
+ '-X[embed in another window]:window:_x_window' \
+ '-a[colour depth]:depth:(8 15 16 24)' \
+ '-z[enable compression]' \
+ '-x[bandwidth performance behaviour]:experience:((b\:broadband l\:lan m\:modem))' \
+ '-P[enable bitmap caching]' \
+ '*-r[device redirection]: :->redirection' \
+ '-0[attach to server console]' \
+ '(-5)-4[use RDP version 4]' \
+ '(-4)-5[use RDP version 5]' \
+ ':server:->hostsport' && ret=0
+
+case $state in
+ hostsport)
+ if compset -P '*:'; then
+ _ports && ret=0
+ else
+ compset -S ':*'
+ _hosts && ret=0
+ fi
+ ;;
+ redirection)
+ redir="${PREFIX%%:*}"
+ if compset -P '*='; then
+ curcontext="${curcontext%:*}:$redir"
+ compset -P '*='
+ case $redir in
+ comport|lptport) _wanted devices expl device _files -g '*(-%)' && ret=0 ;;
+ disk) _directories && ret=0 ;;
+ printer) _printers && ret=0 ;;
+ scard) _message -e aliases 'alias name' ;;
+ esac
+ else
+ compset -S '=*'
+ _values -S : 'redirection' \
+ 'comport:port' \
+ 'disk:sharename' \
+ 'lptport:lptport' \
+ 'printer:printername:_printers -S=' \
+ 'sound:sound:(local off remote)' \
+ 'lspci' \
+ 'scard:sound card name' && ret=0
+ fi
+ ;;
+esac
+
+return ret
diff --git a/Completion/X/Command/_urxvt b/Completion/X/Command/_urxvt
index b7ea06be5..661897c3a 100644
--- a/Completion/X/Command/_urxvt
+++ b/Completion/X/Command/_urxvt
@@ -1,6 +1,6 @@
-#compdef rxvt urxvt urxvtc
+#compdef rxvt urxvt urxvtc urxvt256c urxvt256cc urxvt256c-ml urxvt256c-mlc
-local curcontext="$curcontext" state line expl
+local curcontext="$curcontext" state line expl ret=1
local -a suf long_args
typeset -A opt_args
typeset -U extensions
diff --git a/Completion/X/Command/_x_utils b/Completion/X/Command/_x_utils
index 9448fd3df..05a899b68 100644
--- a/Completion/X/Command/_x_utils
+++ b/Completion/X/Command/_x_utils
@@ -1,12 +1,13 @@
#compdef xdpyinfo xwininfo xkill xfontsel xfd xev xhost xon xsetroot xwd xwud xrdb xprop xlsatoms
-local ret=1 oret expl
+local curcontext="$curcontext" state line expl ret=1
case "$service" in
xdpyinfo)
_x_arguments \
-queryExtensions \
- '-ext:extension: _x_extension -a'
+ '-ext:extension: _x_extension -a' \
+ -version
;;
xwininfo)
_x_arguments \
@@ -16,7 +17,7 @@ xwininfo)
'(-name -root)-id:id: _x_window'
;;
xprop)
- _x_arguments \
+ _x_arguments -C \
-{help,frame,notype,spy} \
'-grammar[show grammar for command line options]' \
'(-id -name)-root[use the root window as the target window]' \
@@ -28,16 +29,17 @@ xprop)
'*-remove[specify an atom to remove from the target window]:atoms:->atoms' \
'*-set[specify an atom and a value to set on the target window]:atoms:->atoms:value' \
'*-f:atoms:->atoms:format: ::dformat' \
- '*:atoms:->atoms' && ret=0
+ '*:atoms:->atoms'
;;
xlsatoms)
- _x_arguments \
+ _x_arguments -C \
'*-format[printf-style format to use]:format' \
'*-range[atom values to list]:[num]-[num]' \
'*-name[name of single atom to print]:atom:->atoms'
;;
xkill)
_x_arguments \
+ -version \
-frame \
'(-id)-all' \
'(-all)-id:window: _x_window' \
@@ -45,14 +47,16 @@ xkill)
;;
xfontsel)
_xt_arguments \
- -{print,noscaled} \
+ -{print,scaled} \
'-pattern:font pattern:_x_font' \
'-sample:sample text' \
- '-sample16:16-bit sample text'
+ '-sample16:16-bit sample text' \
+ '-sampleUCS:ISO10646 sample text'
;;
xfd)
_xt_arguments \
'-fn:font: _x_font' \
+ '-fa:font: _xft_fonts' \
-{box,center} \
'-start:first character number' \
'-bc:box border color:_x_color' \
@@ -66,7 +70,8 @@ xev)
'-id:id:_x_window' \
'-s[use save-under]' \
'-name:window name' \
- '-rv'
+ '-rv' \
+ '*-event:event mask:(keyboard mouse expose visibility structure substructure focus property colormap owner_grab_button randr)'
;;
xhost)
local type tmp match
@@ -120,8 +125,8 @@ xhost)
'types:name family:compadd -S: - inet dnet nis krb' \
'hosts:: _hosts' && ret=0
fi
- return ret
fi
+ return ret
;;
xon)
_arguments \
@@ -165,7 +170,7 @@ xwud)
;;
xrdb)
_x_arguments \
- -{help,quiet,symbols,retain} \
+ -{help,quiet,symbols,retain,version} \
'(-all -screen -screens)-global' \
'(-global -screen -screens)-all' \
'(-global -all -screens)-screen' \
@@ -185,12 +190,10 @@ xrdb)
'*-I-:include directory:_files -/' \
'*:defaults file:_files'
;;
-esac
+esac && ret=0
-oret=$?
if [[ $state == atoms ]]; then
_wanted atoms expl atoms compadd ${${(f)"$(_call_program atoms xlsatoms 2> /dev/null)"}#*$'\t'} && ret=0
-else
- ret=$oret
fi
+
return ret
diff --git a/Completion/X/Command/_xautolock b/Completion/X/Command/_xautolock
new file mode 100644
index 000000000..4d01a1dd2
--- /dev/null
+++ b/Completion/X/Command/_xautolock
@@ -0,0 +1,25 @@
+#compdef xautolock
+_arguments \
+ '(-enable -toggle)-disable' \
+ '(-disable -toggle)-enable' \
+ '(-locknow)-unlocknow' \
+ '(-unlocknow)-locknow' \
+ '(-restart)-exit' \
+ '(-exit)-restart' \
+ '-killer:program: _command_names -e' \
+ '-locker:program: _command_names -e' \
+ '-notifier:program: _command_names -e' \
+ '-nowlocker:program: _command_names -e' \
+ -bell:percent: \
+ -cornerdelay:seconds: \
+ -cornerredelay:seconds: \
+ -corners:corners: \
+ -cornersize:pixels: \
+ -killtime:minutes: \
+ -noclose{,out,err} \
+ -notify:seconds: \
+ -time:minutes: \
+ -secure \
+ -resetsaver \
+ -detectsleep \
+ -{help,version}
diff --git a/Completion/Zsh/Command/_bindkey b/Completion/Zsh/Command/_bindkey
index 045cba960..4c4aeda9d 100644
--- a/Completion/Zsh/Command/_bindkey
+++ b/Completion/Zsh/Command/_bindkey
@@ -26,6 +26,7 @@ _arguments -C -s -S \
'(-l -L -d -D -A -N -m -s *)-r[unbind specified in-strings]:*:in-string' \
'(-l -L -d -D -A -N -m -p -r *)-s[bind each in-string to each out-string]:*:key string' \
'(-e -v -a -M -l -L -d -D -A -N -m -p)-R[interpret in-strings as ranges]' \
+ '(-l -L -d -A -N -m -p -r -s):in-string' \
'(-l -L -d -A -N -m -p -r -s)*::widgets:->widget' && ret=0
case $state in
diff --git a/Completion/Zsh/Command/_command b/Completion/Zsh/Command/_command
index 7cfb52c2f..4e2858676 100644
--- a/Completion/Zsh/Command/_command
+++ b/Completion/Zsh/Command/_command
@@ -1,14 +1,11 @@
#compdef command
-local ret
-
# indicate if this is a precommand modifier
[[ $service = command ]] && precommands+=(command)
-if [[ CURRENT -ge 3 ]]; then
- compset -n 2
- _normal && ret=0
-else
- _path_commands "$@" && ret=0
-fi
-return ret
+_arguments \
+ '-v[indicate result of command search]:*:command:_path_commands' \
+ '-V[show result of command search in verbose form]:*:command:_path_commands' \
+ '(-)-p[use default PATH to find command]' \
+ ':command:_path_commands' \
+ '*::arguments: _normal'
diff --git a/Completion/Zsh/Command/_emulate b/Completion/Zsh/Command/_emulate
index e562d6834..d6fb0c3d9 100644
--- a/Completion/Zsh/Command/_emulate
+++ b/Completion/Zsh/Command/_emulate
@@ -1,6 +1,8 @@
#compdef emulate
-_arguments -C -s -A "-*" \
+_arguments -C -s \
'-L[set local_options and local_traps as well]' \
'-R[reset all options instead of only those needed for script portability]' \
- '::shell to emulate:(zsh sh ksh csh)'
+ '1:shell to emulate:(zsh sh ksh csh)' \
+ '2:specify optional command:(-c)' \
+ '3:command:_cmdstring'
diff --git a/Completion/Zsh/Command/_fc b/Completion/Zsh/Command/_fc
index 2af5980c2..c2987211e 100644
--- a/Completion/Zsh/Command/_fc
+++ b/Completion/Zsh/Command/_fc
@@ -1,21 +1,47 @@
#compdef fc history r
+local curcontext="$curcontext" state state_descr line ret=1
+local list events num cmd
+typeset -A opt_args
local fc_common fc_hist fc_r
+# hide any replacements from _arguments
+local cur=${(M)#words[1,CURRENT-1]:#*=*}
+words=( "${(@)words[1,CURRENT-1]:#*=*}" "${(@)words[CURRENT,-1]}" )
+(( CURRENT -= cur ))
+
fc_common=(
+ -s -S
'(-A -R -W -I -p -P)-r[reverse order of the commands]'
'(-A -R -W -I -e -p -P)-n[suppress line numbers]'
- '(-A -R -W -I -p -P)*::commands:_command_names -e' )
+)
+
+if [[ -n ${words[(r)-[pa](|[ap])]} ]]; then
+ fc_common+=(
+ ':history file:_files'
+ ':history size:'
+ ':saved history size:'
+ )
+ [[ -n ${words[(r)-(|a)p(|a)]} ]] || fc_common+='!-a:option:(-p)'
+elif [[ -n ${words[(r)-*[ARWI]*]} ]]; then
+ fc_common+=( ':history file:_files' )
+else
+ fc_common=( -C "$fc_common[@]"
+ '(-)1:first event:->events' '2:last event:->events'
+ )
+fi
fc_hist=(
- '(-A -R -W -I -p -p)-m[treat first argument as a pattern]'
- '(-A -R -W -I -e -f -E -i -t -p -P)-d[print time-stamps]'
- '(-A -R -W -I -e -d -E -i -t -p -P)-f[mm/dd/yyyy format time-stamps]'
- '(-A -R -W -I -e -d -f -i -t -p -P)-E[dd.mm.yyyy format time-stamps]'
- '(-A -R -W -I -e -d -f -E -t -p -P)-i[yyyy-mm-dd format time-stamps]'
- '(-A -R -W -I -e -d -f -E -i -p -P)-t[print time-stamps in specified format]:date format'
- '(-A -R -W -I -e -p -P)-D[print elapsed times]'
- '(- *)-p[push current history to stack]:history file:_files:history size: :saved history size'
+ '(-A -R -W -I -a -p -P 2)-m[treat argument as a pattern]'
+ '(-A -R -W -I -e -f -E -i -t -a -p -P)-d[print time-stamps]'
+ '(-A -R -W -I -e -d -E -i -t -a -p -P)-f[mm/dd/yyyy format time-stamps]'
+ '(-A -R -W -I -e -d -f -i -t -a -p -P)-E[dd.mm.yyyy format time-stamps]'
+ '(-A -R -W -I -e -d -f -E -t -a -p -P)-i[yyyy-mm-dd format time-stamps]'
+ '(-A -R -W -I -e -d -f -E -i -a -p -P)-t[print time-stamps in specified format]:date format'
+ '(-A -R -W -I -e -a -p -P)-D[print elapsed times]'
+
+ '(-A -R -W -I -e -d -f -i -l -m -n -r -D -E -t -P)-a[with -p, automatically pop history on function return]'
+ '(-A -R -W -I -e -d -f -i -l -m -n -r -D -E -t -P)-p[push current history to stack]'
'(- *)-P[pop history from stack]'
)
@@ -23,18 +49,42 @@ fc_r='(-A -R -W -I -e)-l[list resulting commands on stdout]'
case $service in
history)
- _arguments -s -S "$fc_common[@]" "$fc_hist[@]" && return 0
+ _arguments "$fc_common[@]" "$fc_hist[@]" && ret=0
;;
r)
- _arguments -s -S "$fc_common[@]" "$fc_r" && return 0
+ _arguments "$fc_common[@]" "$fc_r" && ret=0
;;
*)
- _arguments -s -S \
- '(-A -R -W -I -l -n -d -f -E -i -D -p -P)-e[specify editor to invoke]:editor to invoke:_command_names -e' \
- '(-l -m -e -r -n -d -f -E -i -D -A -W -p -P *)-R[read history from file]:history file:_files' \
- '(-l -m -e -r -n -d -f -E -i -D -R -W -p -P *)-A[append history to file]:history file:_files' \
- '(-l -m -e -r -n -d -f -E -i -D -R -A -p -P *)-W[write history to file]:history file:_files' \
- '(-l -m -e -r -n -d -f -E -i -D -A -W -p -P *)-I[read/write new events only]:history file:_files' \
- "$fc_common[@]" "$fc_hist[@]" "$fc_r" && return 0
+ _arguments "$fc_common[@]" "$fc_hist[@]" "$fc_r" \
+ '(-A -R -W -I -a -l -n -d -f -E -i -r -t -D -p -P)-e+[specify editor to invoke]:editor to invoke:_command_names -e' \
+ '(-a -l -m -e -r -n -d -f -t -E -i -R -D -A -W -p -P *)-'{\
+'R[read history from file]',\
+'A[append history to file]',\
+'W[write history to file]',\
+'I[read/write new events only]'} && ret=0
;;
esac
+
+if [[ -n $state ]]; then
+ if [[ -z ${line:#*=*} ]] && compset -P '*='; then
+ _message -e replacements 'replacement'
+ elif [[ -prefix [0-9] ]]; then
+ events=( ${(ps.\0.)"$(printf '%s:%s\0' ${(kv)history})"} )
+ zformat -a list " -- " "$events[@]"
+ _wanted -2V events expl "$state_descr" compadd -M "B:0=" -ld list - \
+ "${events[@]%%:*}"
+ elif [[ -prefix - ]]; then
+ for num cmd in ${(kv)history}; do
+ (( num=num - HISTNO ))
+ events+=( $num:$cmd )
+ done
+ zformat -a list " -- " "$events[@]"
+ _wanted -2V events expl "$state_descr" compadd -ld list - \
+ "${events[@]%%:*}"
+ else
+ _wanted events expl "$state_descr" compadd -S '' - \
+ ${${history%%[=[:IFS:]]*}:#[0-9-]*} || _guard "[0-9]#" event
+ fi
+fi && ret=0
+
+return ret
diff --git a/Completion/Zsh/Command/_tcpsys b/Completion/Zsh/Command/_tcpsys
index dcc6f6cc8..1240ffbf8 100644
--- a/Completion/Zsh/Command/_tcpsys
+++ b/Completion/Zsh/Command/_tcpsys
@@ -1,16 +1,16 @@
#compdef tcp_open
-local context line expl nm=$compstate[nmatches]
-local -a state argargs sesslist
+local curcontext="$curcontext" state line expl
local -A opt_args
+local -a argargs sesslist
case $service in
(tcp_open)
argargs=(
'(-a -f -l)-s[open session(s)]'
'(-a -f -s)-l[open list of sessions]'
- '(-f -s -l)-a[open session for accept on fd]:fd:->fd'
- '(-a -s -l)-f[open session for accept on fd]:fd:->fd'
+ '(-f -s -l)-a[open session for accept on fd]:fd'
+ '(-a -s -l)-f[open session for accept on fd]:fd'
'-q[quiet mode]'
'-z[no zle handler]'
)
@@ -19,7 +19,7 @@ case $service in
elif [[ -n $words[(R)-(l|s)*] ]]; then
argargs+=('*:session:->session')
else
- argargs+=(':host:->host' ':port:->port' '*:session:->session')
+ argargs+=(':host:_hosts' ':port:_ports' '*:session:->session')
fi
_arguments -C $argargs
;;
@@ -27,14 +27,6 @@ esac
while (( $#state )); do
case "$state[1]" in
- (host)
- _hosts
- ;;
-
- (port)
- _ports
- ;;
-
(sessionlist)
compset -P '*,'
;&
diff --git a/Completion/Zsh/Command/_typeset b/Completion/Zsh/Command/_typeset
index 367dbfc23..4e29c23e7 100644
--- a/Completion/Zsh/Command/_typeset
+++ b/Completion/Zsh/Command/_typeset
@@ -46,7 +46,7 @@ use="AEFHLRTUZafghiklmprtuxz"
case ${service} in
autoload)
- use="UXktwz"
+ use="UTXktwz"
func=f
;;
float) use="EFHghlprtux";;
diff --git a/Completion/Zsh/Command/_unhash b/Completion/Zsh/Command/_unhash
index c05c27ea3..ff0c03f49 100644
--- a/Completion/Zsh/Command/_unhash
+++ b/Completion/Zsh/Command/_unhash
@@ -1,14 +1,9 @@
#compdef unhash
-local expl state line curcontext="$curcontext"
-
-_arguments -C -s -S \
- '(-a -f -s *)-d[remove named directories]:*:named directory:->nameddir' \
+_arguments -s -S \
+ '(-a -f -s *)-d[remove named directories]:*:named directory:compadd -k nameddirs' \
'(-d -f -s *)-a[remove aliases]:*:alias:_aliases' \
'(-a -d -f *)-s[remove suffix aliases]:*:suffix alias:_aliases -s s' \
'(-d -a -s *)-f[remove functions]:*:shell function:_functions' \
'-m[treat arguments as patterns]' \
- '(-a -d -f -m)*:command: _command_names -e' && return 0
-
-[[ "$state" = nameddir ]] &&
- _wanted named-directories expl 'named directory' compadd -k nameddirs
+ '(-a -d -f -m)*:command: _command_names -e'
diff --git a/Completion/Zsh/Command/_which b/Completion/Zsh/Command/_which
index 07ede39fd..c43704ae8 100644
--- a/Completion/Zsh/Command/_which
+++ b/Completion/Zsh/Command/_which
@@ -6,7 +6,8 @@ cargs=( \
'(-v -c)-w[print command type]' \
'-p[always do a path search]' \
'-m[treat the arguments as patterns]' \
- '-s[print symlink free path as well]' \
+ '(-S)-s[print symlink free path as well]' \
+ '(-s)-S[show steps in the resolution of symlinks]' \
'*:commands:->command' )
farg='-f[output contents of functions]'
aarg='-a[print all occurrences in path]'
diff --git a/Completion/Zsh/Command/_zattr b/Completion/Zsh/Command/_zattr
index 1924bb28d..e48047f6c 100644
--- a/Completion/Zsh/Command/_zattr
+++ b/Completion/Zsh/Command/_zattr
@@ -1,7 +1,6 @@
#compdef zgetattr zsetattr zdelattr zlistattr
-local state line expl ret=1 REPLY
-local -a args privs
+local context state line expl ret=1 REPLY
case $service in
zgetattr)
@@ -29,6 +28,8 @@ _arguments \
esac && ret=0
if [[ $state = attrs ]]; then
- zlistattr ${~${(Q)line[1]}} REPLY 2> /dev/null
- _wanted attrs expl 'attribute' compadd $REPLY
+ zlistattr ${(Q)${~line[1]}} REPLY 2> /dev/null
+ _wanted -C "$context[1]" attrs expl 'attribute' compadd -a REPLY && ret=0
fi
+
+return ret
diff --git a/Completion/Zsh/Command/_zle b/Completion/Zsh/Command/_zle
index 2bfc708e5..3ed373348 100644
--- a/Completion/Zsh/Command/_zle
+++ b/Completion/Zsh/Command/_zle
@@ -13,20 +13,24 @@ compwids=(accept-and-menu-complete
menu-expand-or-complete
reverse-menu-complete)
-opts=(-A -C -D -L -M -N -R -U -a -c -l \* :)
+opts=(-A -C -D -F -L -M -N -R -T -U -a -c -l -r \* :)
_arguments -s -S \
"($opts)-A[define widget alias]:old widget:->widget :new widget:->widget" \
"($opts)-C[define completion widget]:new widget name:->comp-widget :completion widget:->builtin-comp-widget :widget shell function:->function" \
"($opts)-D[delete widget]:*:widget:->widget" \
- \(${(j. .)opts:#-l}')-L[with -l, list as commands]' \
+ \(${(j. .)opts:#-[lFT]}')-L[with -l, list as commands]' \
\(${(j. .)opts:#-[La]}')-l+[list user-defined widgets]:*:-:->listing' \
\(${(j. .)opts:#-l}')-a[with -l, list all widgets]' \
+ "(: * ${(j. .)opts:#-[Lw]})-F[install file descriptor handler]:file descriptor:_file_descriptors::handler:_functions" \
+ "!($opts)-K:keymap:compadd -a keymaps" \
"($opts)-M[display message]:message: " \
"($opts)-N[define new widget]:widget name:->widget-or-function ::widget shell function:->function" \
\(${(j. .)opts:#-c}')-R+[redisplay]:*:-:->redisplay' \
\(${(j. .)opts:#-R}')-c[with -R, clear listing]' \
"($opts)-U[unget to input stack]:string: " \
+ '(: *)-T[manipulate transformations]:transformation:(tc):function:_functions' \
+ \(${(j. .)opts:#-T}')-r[remove transformations]' \
'(-):widget:->widget' \
'(-)*::widget args:->args' && ret=0
diff --git a/Completion/Zsh/Command/_zmodload b/Completion/Zsh/Command/_zmodload
index ffcab28dd..e144b981e 100644
--- a/Completion/Zsh/Command/_zmodload
+++ b/Completion/Zsh/Command/_zmodload
@@ -4,35 +4,38 @@ local suf comp state line expl curcontext="$curcontext" ret=1 NORMARG
typeset -A opt_args
suf=()
-_arguments -n -C -A "-*" -s \
- '(-i -u -d -a -b -c -I -p -f -e)-A[create module aliases]' \
- '-u[unload module]' \
- '(-e)-a[autoload module]' \
- '(-c -I -p -f)-b[autoload module for builtins]' \
- '(-b -I -p -f)-c[autoload module for condition codes]' \
- '(-i)-d[list or specify module dependencies]' \
- '(-i -u -d -a -b -c -p -f -L -A)-e[test if modules are loaded]' \
- '(-b -c -I -p)-f[autoload module for math functions]' \
- '(-u -b -c -p -f -A)-F[handle features]' \
+_arguments -n -C -S -s \
+ '(-R -P -i -u -d -a -b -c -I -p -f -e -F -m)-A[create module aliases]' \
+ '(-)-R[remove module aliases]' \
+ '(-A -R -F -L -m -P -l -e)-u[unload module]' \
+ '(-d -e -l)-a[autoload module]' \
+ '(-c -d -I -p -f -F -P -l -m -A -R)-b[autoload module for builtins]' \
+ '(-b -d -I -p -f -F -P -l -m -A -R)-c[autoload module for condition codes]' \
+ '(-A -R -F -I -P -a -b -c -e -f -i -l -m -p)-d[list or specify module dependencies]' \
+ '(-i -u -d -a -b -c -p -f -L -R)-e[test if modules are loaded]' \
+ '(-b -c -d -I -p -F -P -l -m -A -R)-f[autoload module for math functions]' \
+ '(-u -b -c -d -p -f -A -R -I)-F[handle features]' \
+ '(-u -b -c -d -p -f -A -R -I)-m[treat feature arguments as patterns]' \
'(-d -e)-i[suppress error if command would do nothing]' \
- '(-b -c -p -f)-I[define infix condition names]' \
- '(-u -b -c -p -f -A)-l[list features]' \
+ '(-b -c -d -p -f -F -P -m)-I[define infix condition names]' \
+ '(-u -b -c -d -p -f -A -R)-l[list features]' \
'(-e -u)-L[output in the form of calls to zmodload]' \
- '(-b -c -I -f)-p[autoload module for parameters]' \
- '(-u -b -c -p -f -A)-P[array param for features]:array name:_parameters' \
- '*:params:->params' && ret=0
+ '(-b -c -d -I -f -F -P -l -m -A -R)-p[autoload module for parameters]' \
+ '(-u -b -c -d -p -f -A -R)-P[array param for features]:array name:_parameters' \
+ '(-)*:params:->params' && ret=0
[[ $state = params ]] || return ret
-(( $+opt_args[-A] )) && compset -P '*=' || suf=( -S '=' )
-
+if (( $+opt_args[-A] )); then
+ compset -S '=*' || compset -P '*=' || suf=( -S '=' )
+fi
if (( $+opt_args[-F] && CURRENT > NORMARG )); then
local module=$words[NORMARG]
local -a features
if [[ $modules[$module] != loaded ]]; then
- _message "features for unloaded module"
+ _message -e features "feature for unloaded module"
else
zmodload -lFP features $module
if compset -P -; then
@@ -41,6 +44,9 @@ if (( $+opt_args[-F] && CURRENT > NORMARG )); then
elif compset -P +; then
# only disabled features needed
features=(${${features:#+*}##?})
+ else
+ # complete opposite of current feature state, + is default
+ features=(${${features#-}/(#s)+/-})
fi
_wanted features expl feature compadd -a features
fi
diff --git a/Completion/Zsh/Command/_zstyle b/Completion/Zsh/Command/_zstyle
index eb27117b2..9a6d61891 100644
--- a/Completion/Zsh/Command/_zstyle
+++ b/Completion/Zsh/Command/_zstyle
@@ -20,6 +20,9 @@ _completers() {
compadd "$@" "$disp[@]" - "$us${^list[@]}"
}
+_vcs_info_hooks() {
+ compadd - ${functions[(I)+vi-*]#+vi-}
+}
# Assoc array of styles; the values give the possible top-level
# contexts:
# c completion
@@ -122,6 +125,7 @@ styles=(
select-prompt c:
select-scroll c:
separate-sections c:bool
+ show-ambiguity c:
show-completer c:bool
single-ignored c:single-ignored
sort c:bool
@@ -176,7 +180,10 @@ styles=(
actionformats v:vcs-format
branchformat v:branch-format
nvcsformats v:
+ hgrevformat v:hgrev-format
stgitformat v:stg-format
+ patch-format v:patch-format
+ nopatch-format v:patch-format
max-exports v:
enable v:vcs
disable v:vcs
@@ -190,7 +197,16 @@ styles=(
use-server v:bool
use-simple v:bool
get-revision v:bool
+ get-mq v:bool
+ get-bookmarks v:bool
+ get-unapplied v:bool
+ debug v:bool
+ hooks v:_vcs_info_hooks
use-prompt-escapes v:bool
+ use-quilt v:bool
+ quilt-standalone v:bool
+ quilt-patch-dir v:_directories
+ quiltcommand v:_command_names
chpwd z:bool
progress z:progress
@@ -307,7 +323,7 @@ while (( $#state )); do
(cmdorcont)
_alternative -O suf \
- 'commands:command:_command ' \
+ 'commands:command:_path_commands' \
'contexts:context:(-array-value- -brace-parameter- -command- -condition- -math- -parameter- -redirect- -subscript- -value-)'
;;
@@ -549,7 +565,18 @@ while (( $#state )); do
compset -P '*%'
_values -s '' 'format replacement' \
'b[the current branch]' \
- 'r[current revision number]' \
+ 'r[current revision number]'
+ else
+ _message -e formats 'vcs format'
+ fi
+ ;;
+
+ (hgrev-format)
+ if [[ $PREFIX = *% ]]; then
+ compset -P '*%'
+ _values -s '' 'format replacement' \
+ 'h[current revision hash (global)]' \
+ 'r[current revision number (local)]'
else
_message -e formats 'vcs format'
fi
@@ -566,6 +593,22 @@ while (( $#state )); do
fi
;;
+ (patch-format)
+ if [[ $PREFIX = *% ]]; then
+ compset -P '*%'
+ _values -s '' 'format replacement' \
+ 'p[name of top-most patch (applied-string)]' \
+ 'u[number of unapplied patches (unapplied-string)]' \
+ 'n[number of applied patches]' \
+ 'c[number of unapplied patches.]' \
+ 'a[number of all patches]' \
+ 'g[names of active mq guards (hg backend)]' \
+ 'G[number of active mq guards (hg backend)]'
+ else
+ _message -e formats 'vcs format'
+ fi
+ ;;
+
(_*)
${=state[1]} $suf
;;
diff --git a/Completion/Zsh/Context/_brace_parameter b/Completion/Zsh/Context/_brace_parameter
index 2aeb12bf4..fcca4bf84 100644
--- a/Completion/Zsh/Context/_brace_parameter
+++ b/Completion/Zsh/Context/_brace_parameter
@@ -104,9 +104,9 @@ if [[ $PREFIX = *'${('[^\)]# ]]; then
done
if [[ -z $found_percent ]]; then
- flags=("%:Expand prompt sequences")
+ flags=("%:expand prompt sequences")
else
- flags=("%:Expand prompts respecting options")
+ flags=("%:expand prompts respecting options")
fi
case $q_last in
(0)
@@ -134,58 +134,74 @@ if [[ $PREFIX = *'${('[^\)]# ]]; then
flags+=("Q:remove one level of quoting")
fi
if [[ -z $found_m ]]; then
- flags+=("m:Count multibyte width in padding calculation")
+ flags+=("m:count multibyte width in padding calculation")
else
- flags+=("m:Count number of character code points in padding calculation")
+ flags+=("m:count number of character code points in padding calculation")
fi
flags+=(
- "#:Evaluate as numeric expression"
- "@:Double-quoted splitting of scalars"
- "A:Create array parameter"
- "a:Sort in array index order (with O to reverse)"
- "c:Count characters in an array (with \${(c)#...})"
- "C:Capitalize words"
- "D:Perform directory name abbreviation"
- "e:Perform single-word shell expansions"
- "f:Split the result on newlines"
- "F:Join arrays with newlines"
- "g:Process echo array sequences (needs options)"
- "i:Sort case-insensitively"
- "k:Subsitute keys of associative arrays"
- "L:Lower case all letters"
- "n:Sort decimal integers numerically"
- "o:Sort in ascending order (lexically if no other sort option)"
- "O:Sort in descending order (lexically if no other sort option)"
- "P:Use parameter value as name of parameter for redirected lookup"
- "t:Substitute type of parameter"
- "u:Substitute first occurrence of each unique word"
- "U:Upper case all letters"
- "v:Substitute values of associative arrays (with (k))"
- "V:Visibility enhancements for special characters"
- "w:Count words in array or string (with \${(w)#...})"
- "W:Count words including empty words (with \${(W)#...})"
- "X:Report parsing errors and eXit substitution"
- "z:Split words as if zsh command line"
- "0:Split words on null bytes"
- "p:Handle print escapes in parameter flag arguments"
- "~:Treat strings in parameter flag arguments as patterns"
- "j:Join arrays with specified string"
- "l:Left-pad resulting words"
- "r:Right-pad resulting words"
- "s:Split words on specified string"
- "Z:Split words as if zsh command line (with options)"
- # "_:Extended flags, for future expansion"
- "S:Search substrings in #, %, / expressions"
- "I:Search <argument>th match in #, %, / expressions"
- "B:Include index of beginning of match in #, %, / expressions"
- "E:Include index of end of match in #, %, / expressions"
- "M:Include matched portion in #, %, / expressions"
- "N:Include length of match in #, %, expressions"
- "R:Include rest (unmatched portion) in #, %, / expressions"
+ "#:evaluate as numeric expression"
+ "@:double-quoted splitting of scalars"
+ "A:create array parameter"
+ "a:sort in array index order (with O to reverse)"
+ "c:count characters in an array (with \${(c)#...})"
+ "C:capitalize words"
+ "D:perform directory name abbreviation"
+ "e:perform single-word shell expansions"
+ "f:split the result on newlines"
+ "F:join arrays with newlines"
+ "g:process echo array sequences (needs options)"
+ "i:sort case-insensitively"
+ "k:subsitute keys of associative arrays"
+ "L:lower case all letters"
+ "n:sort decimal integers numerically"
+ "o:sort in ascending order (lexically if no other sort option)"
+ "O:sort in descending order (lexically if no other sort option)"
+ "P:use parameter value as name of parameter for redirected lookup"
+ "t:substitute type of parameter"
+ "u:substitute first occurrence of each unique word"
+ "U:upper case all letters"
+ "v:substitute values of associative arrays (with (k))"
+ "V:visibility enhancements for special characters"
+ "w:count words in array or string (with \${(w)#...})"
+ "W:count words including empty words (with \${(W)#...})"
+ "X:report parsing errors and eXit substitution"
+ "z:split words as if zsh command line"
+ "0:split words on null bytes"
+ "p:handle print escapes or variables in parameter flag arguments"
+ "~:treat strings in parameter flag arguments as patterns"
+ "j:join arrays with specified string"
+ "l:left-pad resulting words"
+ "r:right-pad resulting words"
+ "s:split words on specified string"
+ "Z:split words as if zsh command line (with options)"
+ # "_:extended flags, for future expansion"
+ "S:search substrings in #, %, / expressions"
+ "I:search <argument>th match in #, %, / expressions"
+ "B:include index of beginning of match in #, %, / expressions"
+ "E:include index of end of match in #, %, / expressions"
+ "M:include matched portion in #, %, / expressions"
+ "N:include length of match in #, % expressions"
+ "R:include rest (unmatched portion) in #, %, / expressions"
)
_describe -t flags "parameter flag" flags -Q -S ''
return
+elif compset -P '*:([\|\*\^]|\^\^)'; then
+ _arrays
+ return
elif compset -P '*:'; then
+ flags=(
+ '-:substitute alternate value if parameter is null'
+ '+:susbtitute alternate value if parameter is non-null'
+ '=:substitute and assign alternate value if parameter is null'
+ '\:=:unconditionally assign value to parameter'
+ '?:print error if parameter is set and non-null'
+ '#:filter value matching pattern'
+ '|:set difference'
+ '*:set intersection'
+ '^:zip arrays'
+ '^^:zip arrays reusing values from shorter array'
+ )
+ _describe -t flags "operator" flags -Q -S ''
_history_modifiers p
return
fi
diff --git a/Completion/Zsh/Context/_subscript b/Completion/Zsh/Context/_subscript
index cf1ec49a4..0ccc0c4ef 100644
--- a/Completion/Zsh/Context/_subscript
+++ b/Completion/Zsh/Context/_subscript
@@ -23,7 +23,7 @@ if [[ $BUFFER[1,pos-1] = (|*[[:space:]:=]##)\~\[ ]]; then
elif [[ "$PREFIX" = :* ]]; then
_wanted characters expl 'character class' \
compadd -p: -S ':]' alnum alpha ascii blank cntrl digit graph \
- lower print punct space upper xdigit
+ lower print punct space upper xdigit IFS IDENT IFSSPACE WORD
elif compset -P '\('; then
local match
compset -S '\)*'
diff --git a/Completion/Zsh/Function/_add-zsh-hook b/Completion/Zsh/Function/_add-zsh-hook
new file mode 100644
index 000000000..c70a4976f
--- /dev/null
+++ b/Completion/Zsh/Function/_add-zsh-hook
@@ -0,0 +1,24 @@
+#compdef add-zsh-hook
+
+local context state state_descr line
+typeset -A opt_args
+
+_add-zsh-hook_hooks() {
+ if (( $+opt_args[-d] )); then
+ _wanted functions expl "installed hooks" compadd -a - "$line[1]_functions" && return 0
+ else
+ _functions && return 0
+ fi
+ return 1
+}
+
+_add-zsh-hook() {
+ _arguments -s -w -S : \
+ '(-D)-d[remove HOOK from the array]' \
+ '(-d)-D[interpret HOOK as pattern to remove from the array]' \
+ {-U,-z,-k}"[passed to 'autoload']" \
+ ':hook class:(chpwd precmd preexec periodic zshaddhistory zshexit zsh_directory_name)' \
+ ':hook function:_add-zsh-hook_hooks'
+}
+
+_add-zsh-hook "$@"
diff --git a/Completion/Zsh/Function/_zcalc b/Completion/Zsh/Function/_zcalc
new file mode 100644
index 000000000..093a7a91d
--- /dev/null
+++ b/Completion/Zsh/Function/_zcalc
@@ -0,0 +1,7 @@
+#compdef zcalc
+
+_arguments -s -w -S : \
+ '-#[specify default base]:base: ' \
+ '-f[force floating point for all expressions]' \
+ '-e[treat command line as expressions to be output immediately]' \
+ '*:expression: '
diff --git a/Completion/Zsh/Type/_globflags b/Completion/Zsh/Type/_globflags
index ca665466b..5833dc8f1 100644
--- a/Completion/Zsh/Type/_globflags
+++ b/Completion/Zsh/Type/_globflags
@@ -4,11 +4,17 @@ local ret=1
local -a flags
if compset -P a; then
- _message -e numbers 'errors'
+ _message -e number 'errors'
return
elif compset -P q; then
_globquals
return
+elif compset -P 'c[0-9]##,'; then
+ _message -e number 'max repetitions'
+ return
+elif compset -P c; then
+ _message -e number 'repetitions (min or exact)'
+ return
fi
flags=(
@@ -17,6 +23,8 @@ flags=(
'I:case sensitive matching'
's:match start of string'
'e:match end of string'
+ 'U:consider all characters to be one byte'
+ 'u:support multibyte characters in pattern'
)
[[ $compstate[context] = condition ]] && flags+=(
'b:activate backreferences'
@@ -29,6 +37,7 @@ _describe -t globflags "glob flag" flags -Q -S ')' && ret=0
flags=(
'a:approximate matching'
'q:introduce glob qualifier'
+ 'c:match repetitions of preceding pattern'
)
_describe -t globflags "glob flag" flags -Q -S '' && ret=0
diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals
index 37db161d0..042b27400 100644
--- a/Completion/Zsh/Type/_globquals
+++ b/Completion/Zsh/Type/_globquals
@@ -213,7 +213,7 @@ case $state in
".:plain files"
"@:symbolic links"
"=:sockets"
- "p:name pipes (FIFOS)"
+ "p:named pipes (FIFOs)"
"*:executable plain files"
"%:device files"
"r:owner-readable"
diff --git a/Completion/Zsh/Type/_history_modifiers b/Completion/Zsh/Type/_history_modifiers
index f8dcd45ae..658f9f346 100644
--- a/Completion/Zsh/Type/_history_modifiers
+++ b/Completion/Zsh/Type/_history_modifiers
@@ -66,6 +66,7 @@ while true; do
list+=(
"a:absolute path"
"A:absolute path resolving symbolic links"
+ "c:PATH search for command"
"g:globally apply s or &"
"h:head - strip trailing path element"
"t:tail - strip directories"
diff --git a/Completion/compaudit b/Completion/compaudit
index 00125e4db..fb0463ca5 100644
--- a/Completion/compaudit
+++ b/Completion/compaudit
@@ -71,6 +71,7 @@ if [[ -n $_compdir ]]; then
_i_addfiles=(${_compdir}/*(/^M))
fi
for _i_line in {1..$#_i_addfiles}; do
+ (( $_i_line )) || break
_i_file=${_i_addfiles[$_i_line]}
[[ -d $_i_file && -z ${fpath[(r)$_i_file]} ]] ||
_i_addfiles[$_i_line]=
diff --git a/Completion/compinit b/Completion/compinit
index f9d2c574c..9470c92f6 100644
--- a/Completion/compinit
+++ b/Completion/compinit
@@ -105,17 +105,17 @@ done
# The associative arrays containing the definitions for the commands and
# services.
-typeset -gA _comps _services _patcomps _postpatcomps
+typeset -gHA _comps _services _patcomps _postpatcomps
# `_compautos' contains the names and options for autoloaded functions
# that get options.
-typeset -gA _compautos
+typeset -gHA _compautos
# The associative array use to report information about the last
# completion to the outside.
-typeset -gA _lastcomp
+typeset -gHA _lastcomp
# Remember dumpfile.
if [[ -n $_i_dumpfile ]]; then
@@ -127,12 +127,13 @@ fi
# The standard options set in completion functions.
-typeset -ga _comp_options
+typeset -gHa _comp_options
_comp_options=(
bareglobqual
extendedglob
glob
multibyte
+ multifuncdef
nullglob
rcexpandparam
unset
@@ -161,7 +162,7 @@ _comp_options=(
# have a valid stdin descriptor (zle closes it before calling widgets)
# and don't get confused by user's ZERR trap handlers.
-typeset -g _comp_setup='local -A _comp_caller_options;
+typeset -gH _comp_setup='local -A _comp_caller_options;
_comp_caller_options=(${(kv)options[@]});
setopt localoptions localtraps localpatterns ${_comp_options[@]};
local IFS=$'\'\ \\t\\r\\n\\0\''
diff --git a/Completion/compinstall b/Completion/compinstall
index c04543c57..afa517edb 100644
--- a/Completion/compinstall
+++ b/Completion/compinstall
@@ -3,6 +3,8 @@
emulate -L zsh
setopt extendedglob
+zmodload -F zsh/files b:zf_ln || return 1
+
local key
local compcontext=-default-
@@ -1958,11 +1960,14 @@ if [[ -z $ifile || -d $ifile ]] ||
fi
local tmpout=${TMPPREFIX:-/tmp/zsh}compinstall$$
+zf_ln -fn =(<<<'') $tmpout && # safe tempfile creation
+zf_ln -fn =(<<<'') ${tmpout}x || return 1
+
#
# Assemble the complete set of lines to
# insert.
#
-__ci_output >$tmpout
+__ci_output >>$tmpout
if [[ -n $ifile ]]; then
if [[ $ifile != *(zshrc|zlogin|zshenv) ]]; then
@@ -1984,15 +1989,15 @@ future use."
fi
if { { grep "$endline" $ifile >/dev/null 2>&1 &&
sed -e "/^[ ]*$endline/r $tmpout
-/^[ ]*$startline/,/^[ ]*$endline/d" $ifile >${tmpout}2 } ||
- { cp $ifile ${tmpout}2 && cat $tmpout >>${tmpout}2 } } &&
- cp ${tmpout}2 $ifile && rm -f ${tmpout}2; then
+/^[ ]*$startline/,/^[ ]*$endline/d" $ifile >>${tmpout}x } ||
+ { cp $ifile ${tmpout}x && cat $tmpout >>${tmpout}x } } &&
+ cp ${tmpout}x $ifile && rm -f ${tmpout}x; then
print "\nSuccessfully added compinstall lines to $ifile."
rm -f $tmpout
else
print "\nFailure adding lines to $ifile. Lines left in \`$tmpout'"
fi
- rm -f ${tmpout}2
+ rm -f ${tmpout}x
elif read -q key'?Print them to stdout instead ([y]es, [n]o)? '; then
cat $tmpout
rm -f $tmpout
diff --git a/Completion/openSUSE/Command/_SUSEconfig b/Completion/openSUSE/Command/_SUSEconfig
index d50828529..737a80b17 100644
--- a/Completion/openSUSE/Command/_SUSEconfig
+++ b/Completion/openSUSE/Command/_SUSEconfig
@@ -1,15 +1,7 @@
#compdef SuSEconfig
-local curcontext="$curcontext" state line
-typeset -A opt_args
-
-if [[ -z "$_SuSEconfig_modules" ]]; then
- for i in /sbin/conf.d/SuSEconfig.*; do
- case $i in *.rpm*|*.swap|*.bak|*.orig|*~|\#*) continue;; esac
- _SuSEconfig_modules=($_SuSEconfig_modules ${i##*/SuSEconfig.})
- done
-fi
-
+local modules
+modules=( /sbin/conf.d/SuSEconfig.*~(*.rpm*|*.swap|*.bak|*.orig|*~|\#*)(N:e) )
_arguments \
'--help' \
@@ -17,12 +9,6 @@ _arguments \
'--force' \
'--verbose' \
'--nonewpackage' \
- '--module:module:->module' && return 0
-
-case $state in
- module) compadd $_SuSEconfig_modules ;;
-esac
-
-# Usage: SuSEconfig [--quick|--nonewpackage|--force|--verbose] [--module name]
-
-
+ '-norestarts' \
+ '-nomodule' \
+ '--module:module:compadd -a modules'
diff --git a/Completion/Linux/Command/_yast b/Completion/openSUSE/Command/_yast
index f008b404f..98585f068 100644
--- a/Completion/Linux/Command/_yast
+++ b/Completion/openSUSE/Command/_yast
@@ -3,9 +3,12 @@
_arguments \
'(- 1)'{-h,--help}'[display help information]' \
'(- 1)'{-l,--list}'[list all available modules]' \
- '(-g --geometry)'{-g,--geometry}'[specify default window size]:_x_geometry' \
- '(-s --style)'{-s,--style}'[specify widget style]:style:(qt)' \
+ '(-g --geometry --ncurses)'{-g,--geometry}'[specify default window size]:_x_geometry' \
+ '--qt[use the QT graphical frontend]' \
+ '--gtk[use the GTK graphical frontend]' \
+ '--ncurses[use the curses text-mode frontend]' \
'--noborder[no window manager border for main window]' \
'--fullscreen[use full screen]' \
'(-)'{-i,--install}'[install package]:*:package file:_files -g "*.rpm(-.)"' \
+ '(-)--remove[remove package]:*:package' \
'1:module:( ${${(f)"$($words[1] -l 2>/dev/null)"}[2,-1]##* } )'
diff --git a/Completion/openSUSE/Command/_yast2 b/Completion/openSUSE/Command/_yast2
deleted file mode 100644
index b9c7f2489..000000000
--- a/Completion/openSUSE/Command/_yast2
+++ /dev/null
@@ -1,30 +0,0 @@
-#compdef yast2 yast
-
-local curcontext="$curcontext" state line
-typeset -A opt_args
-
-if [[ -z "$_yast2_modules" ]]; then
- for i in $(/sbin/yast2 --list | grep -v "Available.*modules"); do
- _yast2_modules=($_yast2_modules $i)
- done
-fi
-
-_arguments -s \
- '(--list)-l[list all available modules]' '(-l)--list' \
- '(--help)-h[help]' '(-h)--help'\
- \
- {'(--geometry)-g[default window size (qt only)]','(-g)--geometry'}':geometry:(800x600+0+0)' \
- '(--style)-s[widget style (qt only)]' '(-s)--style' \
- \
- {'(--install)-i[install rpm package]','(-i)--install'}':filename:_files' \
- \
- '--noborder[no window manager border for main window]' '--noborder' \
- '--fullscreen[use full screen]' '--fullscreen' \
- \
- ':module:->module' && return 0
-
-case $state in
- module) compadd $_yast2_modules; _files -g "*.ycp";;
-esac
-
-
diff --git a/Config/version.mk b/Config/version.mk
index 03289c155..d04d57d87 100644
--- a/Config/version.mk
+++ b/Config/version.mk
@@ -27,5 +27,5 @@
# This must also serve as a shell script, so do not add spaces around the
# `=' signs.
-VERSION=5.0.7
-VERSION_DATE='October 7, 2014'
+VERSION=5.0.7-dev-2
+VERSION_DATE='May 5, 2015'
diff --git a/Doc/META-FAQ.yo b/Doc/META-FAQ.yo
index bfdb76b77..992844ec1 100644
--- a/Doc/META-FAQ.yo
+++ b/Doc/META-FAQ.yo
@@ -19,6 +19,7 @@ ARG1
def(em)(1)(ARG1)
def(bf)(1)(ARG1)
def(tt)(1)(ARG1)
+def(uref)(1)(ARG1)
def(var)(1)(ARG1)
def(nofill)(1)(ARG1)
diff --git a/Doc/Makefile.in b/Doc/Makefile.in
index 41af4a33e..a420781ee 100644
--- a/Doc/Makefile.in
+++ b/Doc/Makefile.in
@@ -60,7 +60,7 @@ MODDOCSRC = \
Zsh/mod_attr.yo Zsh/mod_cap.yo Zsh/mod_clone.yo \
Zsh/mod_compctl.yo Zsh/mod_complete.yo Zsh/mod_complist.yo \
Zsh/mod_computil.yo Zsh/mod_curses.yo \
-Zsh/mod_datetime.yo Zsh/mod_deltochar.yo \
+Zsh/mod_datetime.yo Zsh/mod_db_gdbm.yo Zsh/mod_deltochar.yo \
Zsh/mod_example.yo Zsh/mod_files.yo Zsh/mod_langinfo.yo \
Zsh/mod_mapfile.yo Zsh/mod_mathfunc.yo Zsh/mod_newuser.yo \
Zsh/mod_parameter.yo Zsh/mod_pcre.yo Zsh/mod_regex.yo \
diff --git a/Doc/Zsh/arith.yo b/Doc/Zsh/arith.yo
index 96dc2dc68..5c334ce9c 100644
--- a/Doc/Zsh/arith.yo
+++ b/Doc/Zsh/arith.yo
@@ -39,7 +39,8 @@ zero status.
cindex(arithmetic base)
cindex(bases, in arithmetic)
Integers can be in bases other than 10.
-A leading `tt(0x)' or `tt(0X)' denotes hexadecimal.
+A leading `tt(0x)' or `tt(0X)' denotes hexadecimal and a leading
+`tt(0b)' or `tt(0B) binary.
Integers may also be of the form `var(base)tt(#)var(n)',
where var(base) is a decimal number between two and thirty-six
representing the arithmetic base and var(n)
@@ -232,6 +233,15 @@ necessary. In addition, if any operator which requires an integer
equivalents with assignment) is given a floating point argument, it will be
silently rounded down to the next integer.
+Users should beware that, in common with many other programming
+languages but not software designed for calculation, the evaluation of
+an expression in zsh is taken a term at a time and promotion of integers
+to floating point does not occur in terms only containing integers. A
+typical result of this is that a division such as tt(6/8) is truncated,
+in this being rounded down to 0. The tt(FORCE_FLOAT) shell option can
+be used in scripts or functions where floating point evaluation is
+required throughout.
+
Scalar variables can hold integer or floating point values at different
times; there is no memory of the numeric type in this case.
diff --git a/Doc/Zsh/builtins.yo b/Doc/Zsh/builtins.yo
index 46f40cc3a..c4acf7672 100644
--- a/Doc/Zsh/builtins.yo
+++ b/Doc/Zsh/builtins.yo
@@ -54,13 +54,13 @@ in a group before any non-option arguments; once the first non-option
argument has been found, option processing is terminated.
All builtin commands other than precommand modifiers, even those that
-have no options, can be given the argument `tt(--)' to terminate option
+have no options, can be given the argument `tt(-)tt(-)' to terminate option
processing. This indicates that the following words are non-option
arguments, but is otherwise ignored. This is useful in cases where
arguments to the command may begin with `tt(-)'. For historical
reasons, most builtin commands also recognize a single `tt(-)' in a
separate word for this purpose; note that this is less standard and
-use of `tt(--) is recommended.
+use of `tt(-)tt(-)' is recommended.
startitem()
prefix(-)
@@ -142,7 +142,7 @@ ifnzman(noderef(Aliasing)).
findex(autoload)
cindex(functions, autoloading)
cindex(autoloading functions)
-item(tt(autoload) [ {tt(PLUS())|tt(-)}tt(UXkmtz) ] [ tt(-w) ] [ var(name) ... ])(
+item(tt(autoload) [ {tt(PLUS())|tt(-)}tt(TUXkmtz) ] [ tt(-w) ] [ var(name) ... ])(
Equivalent to tt(functions -u), with the exception of tt(-X)/tt(+X) and
tt(-w).
@@ -198,7 +198,7 @@ cindex(exiting loops)
cindex(loops, exiting)
item(tt(break) [ var(n) ])(
Exit from an enclosing tt(for), tt(while),
-tt(until), tt(select) or tt(repeat) loop. If var(n)
+tt(until), tt(select) or tt(repeat) loop. If an arithmetic expression var(n)
is specified, then break var(n) levels instead of just one.
)
findex(builtin)
@@ -291,7 +291,7 @@ cindex(continuing loops)
item(tt(continue) [ var(n) ])(
Resume the next iteration of the enclosing
tt(for), tt(while), tt(until), tt(select) or
-tt(repeat) loop. If var(n) is specified, break out of
+tt(repeat) loop. If an arithmetic expression var(n) is specified, break out of
var(n)-1 loops and resume at the var(n)th enclosing loop.
)
alias(declare)(typeset)
@@ -615,16 +615,21 @@ the same as if the commands had been executed directly by the shell;
if there are no var(args) or they contain no commands (i.e. are
an empty string or whitespace) the return status is zero.
)
-item(tt(exec) [ tt(-cl) ] [ tt(-a) var(argv0) ] var(simple command))(
-Replace the current shell with an external command rather than forking.
+item(tt(exec) [ tt(-cl) ] [ tt(-a) var(argv0) ] [ var(command) [ var(arg) ... ]])(
+Replace the current shell with an external var(command) rather than forking.
With tt(-c) clear the environment; with tt(-l) prepend tt(-) to the
tt(argv[0]) string of the command executed (to simulate a login shell);
with tt(-a) var(argv0) set the tt(argv[0]) string of the command
executed. See noderef(Precommand Modifiers).
+
+cindex(redirection, current shell's I/O)
+If var(command) is omitted but any redirections are specified,
+then the redirections will take effect in the current shell.
)
findex(exit)
item(tt(exit) [ var(n) ])(
-Exit the shell with the exit status specified by var(n); if none
+Exit the shell with the exit status specified by an arithmetic
+expression var(n); if none
is specified, use the exit status from the last command executed.
pindex(IGNORE_EOF, use of)
An EOF condition will also cause the shell to exit, unless
@@ -657,6 +662,12 @@ xitem(tt( )[ var(old)tt(=)var(new) ... ] [ var(first) [ var(last) ] ])
xitem(tt(fc) tt(-p) [ tt(-a) ] [ var(filename) [ var(histsize) [ var(savehistsize) ] ] ])
xitem(tt(fc) tt(-P))
item(tt(fc) tt(-ARWI) [ var(filename) ])(
+The tt(fc) command controls the interactive history mechanism. Note
+that reading and writing of history options is only performed if the
+shell is interactive. Usually this is detected automatically, but
+it can be forced by setting the tt(interactive) option when starting the
+shell.
+
Select a range of commands from var(first) to var(last) from the
history list.
The arguments var(first) and var(last) may be specified as a
@@ -1088,10 +1099,13 @@ item( [ tt(-R) [ tt(-en) ]] [ var(arg) ... ])(
With the `tt(-f)' option the arguments are printed as described by tt(printf).
With no flags or with the flag `tt(-)', the arguments are printed on
the standard output as described by tt(echo), with the following differences:
-the escape sequence `tt(\M-)var(x)' metafies the character
+the escape sequence `tt(\M-)var(x)' (or `tt(\M)var(x)') metafies the character
var(x) (sets the highest bit),
-`tt(\C-)var(x)' produces a control character (`tt(\C-@)' and `tt(\C-?)' give the
-characters NUL and delete), and `tt(\E)' is a synonym for `tt(\e)'.
+`tt(\C-)var(x)' (or `tt(\C)var(x)') produces a control character
+(`tt(\C-@)' and `tt(\C-?)' give the characters NULL and delete),
+a character code in octal is represented by `tt(\)var(NNN)'
+(instead of `tt(\0)var(NNN)'),
+and `tt(\E)' is a synonym for `tt(\e)'.
Finally, if not in an escape
sequence, `tt(\)' escapes the following character and is not printed.
@@ -1294,10 +1308,10 @@ item(tt(-q))(
Read only one character from the terminal and set var(name) to
`tt(y)' if this character was `tt(y)' or `tt(Y)' and to `tt(n)' otherwise.
With this flag set the return status is zero only if the character was
-`tt(y)' or `tt(Y)'. This option may be used with a timeout; if
-the read times out, or encounters end of file, status 2 is returned.
-Input is read from the terminal unless one of tt(-u)
-or tt(-p) is present. This option may also be used within zle widgets.
+`tt(y)' or `tt(Y)'. This option may be used with a timeout (see tt(-t)); if
+the read times out, or encounters end of file, status 2 is returned. Input is
+read from the terminal unless one of tt(-u) or tt(-p) is present. This option
+may also be used within zle widgets.
)
item(tt(-k) [ var(num) ])(
Read only one (or var(num)) characters. All are assigned to the first
@@ -1400,7 +1414,8 @@ findex(return)
cindex(functions, returning from)
item(tt(return) [ var(n) ])(
Causes a shell function or `tt(.)' script to return to
-the invoking script with the return status specified by var(n). If var(n)
+the invoking script with the return status specified by
+an arithmetic expression var(n). If var(n)
is omitted, the return status is that of the last command
executed.
@@ -1661,7 +1676,7 @@ See also the shell variable tt(STTY) for a means of initialising
the tty before running external commands.
)
findex(type)
-item(tt(type) [ tt(-wfpams) ] var(name) ...)(
+item(tt(type) [ tt(-wfpamsS) ] var(name) ...)(
Equivalent to tt(whence -v).
)
findex(typeset)
@@ -1702,66 +1717,98 @@ newly-created parameters, or when any attribute flags listed below are
given along with the var(name). Using `tt(PLUS())' instead of minus to
introduce an attribute turns it off.
-If the tt(-p) option is given, parameters and values are printed in the
-form of a typeset command and an assignment (which will be printed
-separately for arrays and associative arrays), regardless of other flags
-and options. Note that the tt(-h) flag on parameters is respected; no
-value will be shown for these parameters.
-
-If the tt(-T) option is given, two or three arguments must be present (an
-exception is that zero arguments are allowed to show the list of parameters
-created in this fashion). The first two are the name of a scalar and an
-array parameter (in that order) that will be tied together in the manner of
-tt($PATH) and tt($path). The optional third argument is a single-character
-separator which will be used to join the elements of the array to form the
-scalar; if absent, a colon is used, as with tt($PATH). Only the first
-character of the separator is significant; any remaining characters are
-ignored. Only the scalar parameter may be assigned an initial value. Both
-the scalar and the array may otherwise be manipulated as normal. If one is
-unset, the other will automatically be unset too. There is no way of
-untying the variables without unsetting them, or converting the type of one
-of them with another tt(typeset) command; tt(+T) does not work, assigning
-an array to var(SCALAR) is an error, and assigning a scalar to var(array)
-sets it to be a single-element array. Note that both `tt(typeset -xT ...)'
-and `tt(export -T ...)' work, but only the scalar will be marked for
-export. Setting the value using the scalar version causes a split on all
-separators (which cannot be quoted). It is possible to use the
-same two tied variables with a different separator character in which
-case the variables remain joined as before but the separator is changed.
-This flag has a different meaning when used with tt(-f); see below.
-
-The tt(-g) (global) flag is treated specially: it means that any
-resulting parameter will not be restricted to local scope. Note that this
-does not necessarily mean that the parameter will be global, as the flag
-will apply to any existing parameter (even if unset) from an enclosing
-function. This flag does not affect the parameter after creation, hence it
-has no effect when listing existing parameters, nor does the flag tt(+g)
-have any effect except in combination with tt(-m) (see below).
-
If no var(name) is present, the names and values of all parameters are
printed. In this case the attribute flags restrict the display to only
those parameters that have the specified attributes, and using `tt(PLUS())'
rather than `tt(-)' to introduce the flag suppresses printing of the values
-of parameters when there is no parameter name. Also, if the last option
-is the word `tt(PLUS())', then names are printed but values are not.
+of parameters when there is no parameter name.
+
+If no attribute flags are given, and either no var(name) arguments are
+present or the flag tt(+m) is used, then each parameter name printed is
+preceded by a list of the attributes of that parameter (tt(array),
+tt(association), tt(exported), tt(float), tt(integer), tt(readonly),
+or tt(undefined) for autoloaded parameters not yet loaded). If tt(+m) is
+used with attribute flags, and all those flags are introduced with
+tt(PLUS()), the matching parameter names are printed but their values
+are not.
+
+The following control flags change the behavior of tt(typeset):
+startitem()
+item(tt(PLUS()))(
+If `tt(PLUS())' appears by itself in a separate word as the last option,
+then the names of all parameters (functions with tt(-f)) are printed, but
+the values (function bodies) are not. No var(name) arguments may appear,
+and it is an error for any other options to follow `tt(PLUS())'. The
+effect of `tt(PLUS())' is as if all attribute flags which precede it were
+given with a `tt(PLUS())' prefix. For example, `tt(typeset -U PLUS())' is
+equivalent to `tt(typeset +U)' and displays the names of all arrays having
+the uniqueness attribute, whereas `tt(typeset -f -U PLUS())' displays the
+names of all autoloadable functions. If tt(PLUS()) is the only option,
+then type information (array, readonly, etc.) is also printed for each
+parameter, in the same manner as `tt(typeset +m "*")'.
+)
+item(tt(-g))(
+The tt(-g) (global) means that any resulting parameter will not be
+restricted to local scope. Note that this does not necessarily mean that
+the parameter will be global, as the flag will apply to any existing
+parameter (even if unset) from an enclosing function. This flag does not
+affect the parameter after creation, hence it has no effect when listing
+existing parameters, nor does the flag tt(+g) have any effect except in
+combination with tt(-m) (see below).
+)
+item(tt(-m))(
If the tt(-m) flag is given the var(name) arguments are taken as patterns
-(which should be quoted). With no attribute flags, all parameters (or
-functions with the tt(-f) flag) with matching names are printed (the shell
-option tt(TYPESET_SILENT) is not used in this case). Note that tt(-m) is
-ignored if no patterns are given. If the tt(+g) flag is combined with
-tt(-m), a new local parameter is created for every matching parameter that
-is not already local. Otherwise tt(-m) applies all other flags or
-assignments to the existing parameters. Except when assignments are made
-with var(name)tt(=)var(value), using tt(+m) forces the matching parameters
-to be printed, even inside a function.
-
-If no attribute flags are given and either no tt(-m) flag is present or
-the tt(+m) form was used, each parameter name printed is preceded by a
-list of the attributes of that parameter (tt(array), tt(association),
-tt(exported), tt(integer), tt(readonly)). If tt(+m) is used with attribute
-flags, and all those flags are introduced with tt(PLUS()), the matching
-parameter names are printed but their values are not.
+(use quoting to prevent these from being interpreted as file patterns).
+With no attribute flags, all parameters (or functions with the tt(-f)
+flag) with matching names are printed (the shell option tt(TYPESET_SILENT)
+is not used in this case).
+
+If the tt(+g) flag is combined with tt(-m), a new local parameter is
+created for every matching parameter that is not already local. Otherwise
+tt(-m) applies all other flags or assignments to the existing parameters.
+
+Except when assignments are made with var(name)tt(=)var(value), using
+tt(+m) forces the matching parameters and their attributes to be printed,
+even inside a function. Note that tt(-m) is ignored if no patterns are
+given, so `tt(typeset -m)' displays attributes but `tt(typeset -a +m)'
+does not.
+)
+item(tt(-p))(
+If the tt(-p) option is given, parameters and values are printed in the
+form of a typeset command and an assignment (which will be printed
+separately for arrays and associative arrays), regardless of other flags
+and options. Note that the tt(-H) flag on parameters is respected; no
+value will be shown for these parameters.
+)
+item(tt(-T) [ var(scalar)[tt(=)var(value)] var(array) [ var(sep) ] ])(
+This flag has a different meaning when used with tt(-f); see below.
+Otherwise the tt(-T) option requires zero, two, or three arguments to be
+present. With no arguments, the list of parameters created in this
+fashion is shown. With two or three arguments, the first two are the name
+of a scalar and of an array parameter (in that order) that will be tied
+together in the manner of tt($PATH) and tt($path). The optional third
+argument is a single-character separator which will be used to join the
+elements of the array to form the scalar; if absent, a colon is used, as
+with tt($PATH). Only the first character of the separator is significant;
+any remaining characters are ignored.
+
+Only the scalar parameter may be assigned an initial value. Both the
+scalar and the array may otherwise be manipulated as normal. If one is
+unset, the other will automatically be unset too. There is no way of
+untying the variables without unsetting them, nor of converting the type
+of one of them with another tt(typeset) command; tt(+T) does not work,
+assigning an array to var(scalar) is an error, and assigning a scalar to
+var(array) sets it to be a single-element array.
+
+Note that both `tt(typeset -xT ...)' and `tt(export -T ...)' work, but
+only the scalar will be marked for export. Setting the value using the
+scalar version causes a split on all separators (which cannot be quoted).
+It is possible to apply tt(-T) to two previously tied variables but with a
+different separator character, in which case the variables remain joined
+as before but the separator is changed.
+)
+enditem()
Attribute flags that transform the final value (tt(-L), tt(-R), tt(-Z),
tt(-l), tt(u)) are only applied to the expanded value at the point
@@ -1892,6 +1939,13 @@ item(tt(-r))(
The given var(name)s are marked readonly. Note that if var(name) is a
special parameter, the readonly attribute can be turned on, but cannot then
be turned off.
+
+If the tt(POSIX_BUILTINS) option is set, the readonly attribute is
+more restrictive: unset variables can be marked readonly and cannot then
+be set; furthermore, the readonly attribute cannot be removed from any
+variable. Note that in zsh (unlike other shells) it is still possible
+to create a local variable of the same name as this is considered a
+different variable (though this variable, too, can be marked readonly).
)
item(tt(-t))(
Tags the named parameters. Tags have no special meaning to the shell.
@@ -2059,12 +2113,33 @@ then all currently active child processes are waited for.
Each var(job) can be either a job specification or the process ID
of a job in the job table.
The exit status from this command is that of the job waited for.
+
+It is possible to wait for recent processes (specified by process ID,
+not by job) that were running in the background even if the process has
+exited. Typically the process ID will be recorded by capturing the
+value of the variable tt($!) immediately after the process has been
+started. There is a limit on the number of process IDs remembered by
+the shell; this is given by the value of the system configuration
+parameter tt(CHILD_MAX). When this limit is reached, older process IDs
+are discarded, least recently started processes first.
+
+Note there is no protection against the process ID wrapping, i.e. if the
+wait is not executed soon enough there is a chance the process waited
+for is the wrong one. A conflict implies both process IDs have been
+generated by the shell, as other processes are not recorded, and that
+the user is potentially interested in both, so this problem is intrinsic
+to process IDs.
)
findex(whence)
-item(tt(whence) [ tt(-vcwfpams) ] var(name) ...)(
+item(tt(whence) [ tt(-vcwfpamsS) ] var(name) ...)(
For each name, indicate how it would be interpreted if used as a
command name.
+tt(whence) is most useful when var(name) is only the last path component
+of a command, i.e. does not include a `tt(/)'; in particular, pattern
+matching only succeeds if just the non-directory component of the command is
+passed.
+
startitem()
item(tt(-v))(
Produce a more verbose report.
@@ -2097,21 +2172,26 @@ throughout the command path.
Normally only the first occurrence is printed.
)
item(tt(-m))(
-The arguments are taken as patterns (should be
+The arguments are taken as patterns (pattern characters should be
quoted), and the information is displayed for each command matching one
of these patterns.
)
item(tt(-s))(
If a pathname contains symlinks, print the symlink-free pathname as well.
)
+item(tt(-S))(
+As tt(-s), but if the pathname had to be resolved by following
+multiple symlinks, the intermediate steps are printed, too. The
+symlink resolved at each step might be anywhere in the path.
+)
enditem()
)
findex(where)
-item(tt(where) [ tt(-wpms) ] var(name) ...)(
+item(tt(where) [ tt(-wpmsS) ] var(name) ...)(
Equivalent to tt(whence -ca).
)
findex(which)
-item(tt(which) [ tt(-wpams) ] var(name) ...)(
+item(tt(which) [ tt(-wpamsS) ] var(name) ...)(
Equivalent to tt(whence -c).
)
findex(zcompile)
diff --git a/Doc/Zsh/calsys.yo b/Doc/Zsh/calsys.yo
index 0d7abbf86..6b5fe27fb 100644
--- a/Doc/Zsh/calsys.yo
+++ b/Doc/Zsh/calsys.yo
@@ -10,9 +10,9 @@ or future events, details of which are stored in a text file (typically
tt(calendar) in the user's home directory). The version provided here
includes a mechanism for alerting the user when an event is due.
-In addition a function tt(age) is provided that can be used in a glob
-qualifier; it allows files to be selected based on their modification
-times.
+In addition functions tt(age), tt(before) and tt(after) are provided
+that can be used in a glob qualifier; they allow files to be selected
+based on their modification times.
The format of the tt(calendar) file and the dates used there in and in
the tt(age) function are described first, then the functions that can
@@ -122,10 +122,10 @@ enditemize()
Here, square brackets indicate optional elements, possibly with
alternatives. Fractions of a second are recognised but ignored. For
absolute times (the normal format require by the tt(calendar) file and the
-tt(age) function) a date is mandatory but a time of day is not; the time
-returned is at the start of the date. One variation is allowed: if
-tt(a.m.) or tt(p.m.) or one of their variants is present, an hour without a
-minute is allowed, e.g. tt(3 p.m.).
+tt(age), tt(before) and tt(after) functions) a date is mandatory but a
+time of day is not; the time returned is at the start of the date. One
+variation is allowed: if tt(a.m.) or tt(p.m.) or one of their variants
+is present, an hour without a minute is allowed, e.g. tt(3 p.m.).
Time zones are not handled, though if one is matched following a time
specification it will be removed to allow a surrounding date to be
@@ -605,8 +605,10 @@ left in a file with the suffix tt(.old).
enditem()
subsect(Glob qualifiers)
-findex(age)
+startitem()
+item(tt(age))(
+findex(age)
The function tt(age) can be autoloaded and use separately from
the calendar system, although it uses the function tt(calendar_scandate)
for date formatting. It requires the tt(zsh/stat) builtin, but uses
@@ -675,6 +677,23 @@ example(print *+LPAR()e-age :file1 :file2-+RPAR())
matches all files modified no earlier than tt(file1) and
no later than tt(file2); precision here is to the nearest second.
+)
+xitem(tt(after))
+item(tt(before))(
+findex(after)
+findex(before)
+The functions tt(after) and tt(before) are simpler versions of tt(age)
+that take just one argument. The argument is parsed similarly to an
+argument of tt(age); if it is not given the variable tt(AGEREF) is
+consulted. As the names of the functions suggest, a file matches if its
+modification time is after or before the time and date specified. If
+a time only is given the date is today.
+
+The two following examples are therefore equivalent:
+example(print *+LPAR()e-after 12:00-RPAR()
+print *+LPAR()e-after today:12:00-RPAR())
+)
+enditem()
texinode(Calendar Styles)(Calendar Utility Functions)(Calendar System User Functions)(Calendar Function System)
sect(Styles)
diff --git a/Doc/Zsh/compsys.yo b/Doc/Zsh/compsys.yo
index 920b5903d..b699502ca 100644
--- a/Doc/Zsh/compsys.yo
+++ b/Doc/Zsh/compsys.yo
@@ -354,7 +354,7 @@ tt(all): no further completion is attempted; a string
containing the substring tt(patterns): no pattern completion functions
will be called; a string containing tt(default): the
function for the `tt(-default-)' context will not be called, but
-functions defined for commands will
+functions defined for commands will be.
)
kindex(-math-, completion context)
item(tt(-math-))(
@@ -533,21 +533,41 @@ generated.
subsect(Overview)
When completion is attempted somewhere on the command line the
-completion system first works out the context. This takes account of a
+completion system begins building the context. The context represents
+everything that the shell knows about the meaning of the command line
+and the significance of the cursor position. This takes account of a
number of things including the command word (such as `tt(grep)' or
`tt(zsh)') and options to which the current word may be an argument
(such as the `tt(-o)' option to tt(zsh) which takes a shell option as an
argument).
-This context information is condensed into a string consisting of
-multiple fields separated by colons, referred to simply as `the context'
-in the remainder of the documentation. This is used to look up
-em(styles), context-sensitive options that can be used to configure the
-completion system. The context used for lookup may vary during the same
-call to the completion system.
+The context starts out very generic ("we are beginning a completion")
+and becomes more specific as more is learned ("the current word is in a
+position that is usually a command name" or "the current word might be a
+variable name" and so on). Therefore the context will vary during the
+same call to the completion system.
+
+This context information is condensed into a string consisting of multiple
+fields separated by colons, referred to simply as `the context' in the
+remainder of the documentation. Note that a user of the completion system
+rarely needs to compose a context string, unless for example a new
+function is being written to perform completion for a new command. What a
+user may need to do is compose a em(style) pattern, which is matched
+against a context when needed to look up context-sensitive options that
+configure the completion system.
+
+The next few paragraphs explain how a context is composed within the
+completion function suite. Following that is discussion of how em(styles)
+are defined. Styles determine such things as how the matches are
+generated, similarly to shell options but with much more control. They
+are defined with the tt(zstyle) builtin command (\
+ifzman(see zmanref(zshmodules))\
+ifnzman(noderef(The zsh/zutil Module))).
The context string always consists of a fixed set of fields, separated
-by colons and with a leading colon before the first, in the form
+by colons and with a leading colon before the first. Fields which are
+not yet known are left empty, but the surrounding colons appear anyway.
+The fields are always in the order
tt(:completion:)var(function)tt(:)var(completer)tt(:)var(command)tt(:)var(argument)tt(:)tt(tag). These have the following meaning:
startitemize()
@@ -628,17 +648,13 @@ described in
ifzman(the section `Bindable Commands' below)\
ifnzman(noderef(Bindable Commands)).
-Styles determine such things as how the matches are generated, similarly
-to shell options but with much more control. They can have any number
-of strings as their value. They are defined with the tt(zstyle) builtin
-command (\
-ifzman(see zmanref(zshmodules))\
-ifnzman(noderef(The zsh/zutil Module))).
-
When looking up styles the completion system uses full context names,
-including the tag. Looking up the value of a style therefore consists
-of two things: the context, which may be matched as a pattern, and the
-name of the style itself, which must be given exactly.
+including the tag. Looking up the value of a style therefore consists of
+two things: the context, which is matched to the most specific (best
+fitting) style pattern, and the name of the style itself, which must be
+matched exactly. The following examples demonstrate that style patterns
+may be loosely defined for styles that apply broadly, or as tightly
+defined as desired for styles that apply in narrower circumstances.
For example, many completion functions can generate matches in a
simple and a verbose form and use the tt(verbose) style to decide
@@ -661,7 +677,7 @@ completion for the tt(kill) builtin. If the style is set, the builtin
lists full job texts and process command lines; otherwise it shows the
bare job numbers and PIDs. To turn the style off for this use only:
-example(zstyle ':completion:*:*:kill:*' verbose no)
+example(zstyle ':completion:*:*:kill:*:*' verbose no)
For even more control, the style can use one of the tags `tt(jobs)' or
`tt(processes)'. To turn off verbose display only for jobs:
@@ -688,10 +704,15 @@ as tt(menu) and tt(list-rows-first).
Note that the order in which styles are em(defined) does not matter; the
style mechanism uses the most specific possible match for a particular
style to determine the set of values. More precisely, strings are
-preferred over patterns (for example, `tt(:completion::complete:foo)' is
-more specific than `tt(:completion::complete:*')), and longer patterns are
+preferred over patterns (for example, `tt(:completion::complete:::foo)' is
+more specific than `tt(:completion::complete:::*')), and longer patterns are
preferred over shorter patterns.
+A good rule of thumb is that any completion style pattern that needs to
+include more than one wildcard (tt(*)) and that does not end in a tag
+name, should include all six colons (tt(:)), possibly surrounding
+additional wildcards.
+
Style names like those of tags are arbitrary and depend on the completion
function. However, the following two sections list some of the most
common tags and styles.
@@ -1491,7 +1512,7 @@ For example, to make the tt(rm) command first complete only names of
object files and then the names of all files if there is no matching
object file:
-example(zstyle ':completion:*:*:rm:*' file-patterns \
+example(zstyle ':completion:*:*:rm:*:*' file-patterns \
'*.o:object-files' '%p:all-files')
To alter the default behaviour of file completion DASH()- offer files
@@ -1643,7 +1664,7 @@ For example, to have names of builtin commands, shell functions and
external commands appear in that order when completing in command
position:
-example(zstyle ':completion:*:*:-command-:*' group-order \
+example(zstyle ':completion:*:*:-command-:*:*' group-order \
builtins functions commands)
)
kindex(groups, completion style)
@@ -1839,7 +1860,7 @@ tested for all tags valid for the current completion, then the
tt(default) tag. The cursor will be moved back to the
previous line if this style is `true' for all types of match. Note
that unlike the tt(ALWAYS_LAST_PROMPT) option this is independent of the
-numeric prefix argument.
+numeric argument.
)
kindex(known-hosts-files)
item(tt(known-hosts-files))(
@@ -2029,7 +2050,7 @@ use the completers tt(_complete) and tt(_prefix) but allow
case-insensitive completion only with tt(_complete):
example(zstyle ':completion:*' completer _complete _prefix
-zstyle ':completion:*:complete:*' matcher-list \
+zstyle ':completion:*:complete:*:*:*' matcher-list \
'' 'm:{a-zA-Z}={A-Za-z}')
User-defined names, as explained for the tt(completer) style, are
@@ -2040,9 +2061,9 @@ with case-insensitive matching, then correction, and finally
partial-word completion:
example(zstyle ':completion:*' completer _complete _correct _complete:foo
-zstyle ':completion:*:complete:*' matcher-list \
+zstyle ':completion:*:complete:*:*:*' matcher-list \
'' 'm:{a-zA-Z}={A-Za-z}'
-zstyle ':completion:*:foo:*' matcher-list \
+zstyle ':completion:*:foo:*:*:*' matcher-list \
'm:{a-zA-Z}={A-Za-z} r:|[-_./]=* r:|=*')
If the style is unset in any context no match specification is applied.
@@ -2565,7 +2586,7 @@ an exception to this behavior.)
For example:
-example(zstyle ':completion:*:complete:-command-:*' tag-order \
+example(zstyle ':completion:*:complete:-command-:*:*' tag-order \
'commands functions')
specifies that completion in command position first offers
@@ -2624,7 +2645,7 @@ repeat them all. For example, to make completion of function names in
command position ignore all the completion functions starting with an
underscore the first time completion is tried:
-example(zstyle ':completion:*:*:-command-:*' tag-order \
+example(zstyle ':completion:*:*:-command-:*:*' tag-order \
'functions:-non-comp *' functions
zstyle ':completion:*:functions-non-comp' ignored-patterns '_*')
@@ -2660,7 +2681,7 @@ try normal completion without any match specification and, if that
generates no matches, try again with case-insensitive matching, restricting
the effect to arguments of the command tt(foo):
-example(zstyle ':completion:*:*:foo:*' tag-order '*' '*:-case'
+example(zstyle ':completion:*:*:foo:*:*' tag-order '*' '*:-case'
zstyle ':completion:*-case' matcher 'm:{a-z}={A-Z}')
First, all the tags offered when completing after tt(foo) are tried using
@@ -4119,7 +4140,7 @@ tt(compadd) when generating matches from the style value, or to
the functions for the fields if they are called.
)
findex(_describe)
-item(tt(_describe) [ tt(-oO) | tt(-t) var(tag) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)(
+item(tt(_describe) [tt(-12JVx)] [ tt(-oO) | tt(-t) var(tag) ] var(descr) var(name1) [ var(name2) ] var(opts) ... tt(-)tt(-) ...)(
This function associates completions with descriptions.
Multiple groups separated by tt(-)tt(-) can be supplied, potentially with
different completion options var(opts).
@@ -4150,6 +4171,9 @@ tt(prefix-needed) style.
With the tt(-t) option a var(tag) can be specified. The default is
`tt(values)' or, if the tt(-o) option is given, `tt(options)'.
+The options tt(-1), tt(-2), tt(-J), tt(-V), tt(-x) are passed to
+tt(_next_label).
+
If selected by the tt(list-grouped) style, strings with the same
description will appear together in the list.
@@ -4257,12 +4281,12 @@ option `tt(-)tt(-help)'.
)
findex(_guard)
item(tt(_guard) [ var(options) ] var(pattern descr))(
-This function is intended to be used in the var(action) for
-the specifications passed to tt(_arguments) and similar functions. It
-returns immediately with a non-zero return status if
-the string to be completed does not match the var(pattern). If the
-pattern matches, the var(descr) is displayed; the function then returns
-status zero if the word to complete is not empty, non-zero otherwise.
+This function displays var(descr) if var(pattern) matches the string to
+be completed. It is intended to be used in the var(action) for the
+specifications passed to tt(_arguments) and similar functions.
+
+The return status is zero if the message was displayed and the word to
+complete is not empty, and non-zero otherwise.
The var(pattern) may be preceded by any of the options understood by
tt(compadd) that are passed down from tt(_description), namely tt(-M),
diff --git a/Doc/Zsh/contrib.yo b/Doc/Zsh/contrib.yo
index 8c5e66b17..24be63eb9 100644
--- a/Doc/Zsh/contrib.yo
+++ b/Doc/Zsh/contrib.yo
@@ -595,22 +595,22 @@ In order to do that, you may use the tt(vcs_info) function.
The following VCSs are supported, showing the abbreviated name by which
they are referred to within the system:
startsitem()
-sitem(Bazaar (tt(bzr)))(http://bazaar-vcs.org/)
-sitem(Codeville (tt(cdv)))(http://codeville.org/)
-sitem(Concurrent Versioning System (tt(cvs)))(http://www.nongnu.org/cvs/)
-sitem(Darcs (tt(darcs)))(http://darcs.net/)
-sitem(Fossil (tt(fossil)))(http://fossil-scm.org/)
-sitem(Git (tt(git)))(http://git-scm.com/)
-sitem(GNU arch (tt(tla)))(http://www.gnu.org/software/gnu-arch/)
-sitem(Mercurial (tt(hg)))(http://mercurial.selenic.com/)
-sitem(Monotone (tt(mtn)))(http://monotone.ca/)
-sitem(Perforce (tt(p4)))(http://www.perforce.com/)
-sitem(Subversion (tt(svn)))(http://subversion.tigris.org/)
-sitem(SVK (tt(svk)))(http://svk.bestpractical.com/)
+sitem(Bazaar (tt(bzr)))(uref(http://bazaar.canonical.com/))
+sitem(Codeville (tt(cdv)))(uref(http://freecode.com/projects/codeville/))
+sitem(Concurrent Versioning System (tt(cvs)))(uref(http://www.nongnu.org/cvs/))
+sitem(Darcs (tt(darcs)))(uref(http://darcs.net/))
+sitem(Fossil (tt(fossil)))(uref(http://fossil-scm.org/))
+sitem(Git (tt(git)))(uref(http://git-scm.com/))
+sitem(GNU arch (tt(tla)))(uref(http://www.gnu.org/software/gnu-arch/))
+sitem(Mercurial (tt(hg)))(uref(http://mercurial.selenic.com/))
+sitem(Monotone (tt(mtn)))(uref(http://monotone.ca/))
+sitem(Perforce (tt(p4)))(uref(http://www.perforce.com/))
+sitem(Subversion (tt(svn)))(uref(http://subversion.apache.org/))
+sitem(SVK (tt(svk)))(uref(http://svk.bestpractical.com/))
endsitem()
There is also support for the patch management system tt(quilt)
-(http://savannah.nongnu.org/projects/quilt). See tt(Quilt Support)
+(uref(http://savannah.nongnu.org/projects/quilt)). See tt(Quilt Support)
below for details.
To load tt(vcs_info):
@@ -927,6 +927,10 @@ kindex(get-bookmarks)
item(tt(get-bookmarks))(
If set to true, the tt(hg) backend will try to get a list of current
bookmarks. They will be available via the `tt(%m)' replacement.
+
+The default is to generate a comma-separated list of all bookmark names
+that refer to the currently checked out revision. If a bookmark is active,
+its name is suffixed an asterisk and placed first in the list.
)
kindex(use-prompt-escapes)
item(tt(use-prompt-escapes))(
@@ -944,6 +948,21 @@ item(tt(hooks))(
A list style that defines hook-function names. See bf(Hooks in vcs_info)
below for details.
)
+kindex(patch-format)
+kindex(nopatch-format)
+xitem(tt(patch-format))
+item(tt(nopatch-format))(
+This pair of styles format the patch information used by the tt(%m) expando in
+formats and actionformats for the tt(git) and tt(hg) backends. The value is
+subject to certain tt(%)-expansions described below.
+)
+kindex(get-unapplied)
+item(tt(get-unapplied))(
+This boolean style controls whether a backend should attempt to gather a list
+of unapplied patches (for example with Mercurial Queue patches).
+
+Used by the tt(quilt) and tt(hg) backends.
+)
enditem()
The default values for these styles in all contexts are:
@@ -975,6 +994,9 @@ sitem(tt(use-quilt))(false)
sitem(tt(quilt-standalone))(false)
sitem(tt(quilt-patch-dir))(empty - use tt($QUILT_PATCHES))
sitem(tt(quiltcommand))(quilt)
+sitem(tt(patch-format))(var(backend dependent))
+sitem(tt(nopatch-format))(var(backend dependent))
+sitem(tt(get-unapplied))(false)
endsitem()
In normal tt(formats) and tt(actionformats) the following replacements are
@@ -996,11 +1018,26 @@ sitem(tt(%r))(The repository name. If tt(%R) is tt(/foo/bar/repoXY), tt(%r)
is tt(repoXY).)
sitem(tt(%S))(A subdirectory within a repository. If tt($PWD) is
tt(/foo/bar/repoXY/beer/tasty), tt(%S) is tt(beer/tasty).)
-sitem(tt(%m))(A "misc" replacement. It is at the discretion of the backend to
-decide what this replacement expands to. It is currently used by the tt(hg)
-and tt(git) backends to display patch information from the tt(mq) and
-tt(stgit) extensions.)
endsitem()
+startitem()
+item(tt(%m))(
+A "misc" replacement. It is at the discretion of the backend to
+decide what this replacement expands to.
+
+The tt(hg) and tt(git) backends use this expando to display patch information.
+tt(hg) sources patch information from the tt(mq) extensions; tt(git) from the
+tt(rebase) command and from the and tt(stgit) extension. The tt(patch-format)
+and tt(nopatch-format) styles control the generated string. The former is used
+when at least one patch from the patch queue has been applied, and the latter
+otherwise.
+
+The tt(hg) backend displays bookmark information in this expando (in addition
+to tt(mq) information). See the tt(get-mq) and tt(get-bookmarks) styles. Both
+of these styles may be enabled at the same time. If both are enabled, both
+resulting strings will be shown separated by a semicolon (that cannot currently
+be customized).
+)
+enditem()
In tt(branchformat) these replacements are done:
@@ -1290,6 +1327,9 @@ tt(get-revision) and tt(get-bookmarks) styles must be true.
This hook gets the names of the Mercurial bookmarks that
tt(vcs_info) collected from `hg'.
+If a bookmark is active, the key tt(${hook_com[hg-active-bookmark]}) is
+set to its name. The key is otherwise unset.
+
When setting tt(ret) to non-zero, the string in
tt(${hook_com[hg-bookmark-string]}) will be used in the tt(%m) escape in
tt(formats) and tt(actionformats) and will be available in the global
@@ -1377,6 +1417,30 @@ If tt(ret) is set to non-zero, the string in
tt(${hook_com[rev-replace]}) will be used unchanged as the
`tt(%i)' replacement in the variables set by tt(vcs_info).
)
+item(tt(pre-addon-quilt))(
+This hook is used when tt(vcs_info)'s quilt functionality is active in "addon"
+mode (quilt used on top of a real version control system). It is activated
+right before any quilt specific action is taken.
+
+Setting the `tt(ret)' variable in this hook to a non-zero value avoids any
+quilt specific actions from being run at all.
+)
+item(tt(set-patch-format))(
+This hook is used to control some of the possible expansions in
+tt(patch-format) and tt(nopatch-format) styles with patch queue systems such as
+quilt, mqueue and the like.
+
+This hook is used in the tt(git), tt(hg) and tt(quilt) backends.
+
+The hook allows the control of the tt(%p) (tt(${hook_com[applied]})) and tt(%u)
+(tt(${hook_com[unapplied]})) expansion in all backends that use the hook. With
+the mercurial backend, the tt(%g) (tt(${hook_com[guards]})) expansion is
+controllable in addition to that.
+
+If tt(ret) is set to non-zero, the string in tt(${hook_com[patch-replace]})
+will be used unchanged instead of an expanded format from tt(patch-format) or
+tt(nopatch-format).
+)
item(tt(set-message))(
Called each time before a `tt(vcs_info_msg_N_)' message is set.
It takes two arguments; the first being the `N' in the message
@@ -1864,7 +1928,7 @@ described immediately above, i.e. using styles to decide the word
boundaries. However, it is not a replacement for any existing function.
The basic behaviour is to delete the word around the cursor. There is no
-numeric prefix handling; only the single word around the cursor is
+numeric argument handling; only the single word around the cursor is
considered. If the widget contains the string tt(kill), the removed text
will be placed in the cutbuffer for future yanking. This can be obtained
by defining tt(kill-whole-word-match) as follows:
@@ -1930,14 +1994,14 @@ full history line. Note that leading zeroes must be typed (they are only
shown when necessary for removing ambiguity). The entire history is
searched; there is no distinction between forwards and backwards.
-With a prefix argument, the search is not anchored to the start of
+With a numeric argument, the search is not anchored to the start of
the line; the string typed by the use may appear anywhere in the line
in the history.
If the widget name contains `tt(-end)' the cursor is moved to the end of
the line inserted. If the widget name contains `tt(-space)' any space
in the text typed is treated as a wildcard and can match anything (hence
-a leading space is equivalent to giving a prefix argument). Both
+a leading space is equivalent to giving a numeric argument). Both
forms can be combined, for example:
example(zle -N history-beginning-search-menu-space-end \
@@ -1967,8 +2031,8 @@ vindex(incarg, use of)
item(tt(incarg))(
Typing the keystrokes for this widget with the cursor placed on or to the
left of an integer causes that integer to be incremented by one. With a
-numeric prefix argument, the number is incremented by the amount of the
-argument (decremented if the prefix argument is negative). The shell
+numeric argument, the number is incremented by the amount of the
+argument (decremented if the numeric argument is negative). The shell
parameter tt(incarg) may be set to change the default increment to
something other than one.
@@ -1997,7 +2061,7 @@ accented characters, the two keys are a base character followed by a code
for the accent, while for other special characters the two characters
together form a mnemonic for the character to be inserted. The
two-character codes are a subset of those given by RFC 1345 (see for
-example tt(http://www.faqs.org/rfcs/rfc1345.html)).
+example uref(http://www.faqs.org/rfcs/rfc1345.html)).
The function may optionally be followed by up to two characters which
replace one or both of the characters read from the keyboard; if both
@@ -2442,7 +2506,7 @@ This function may replace the tt(insert-last-word) widget, like so:
example(zle -N insert-last-word smart-insert-last-word)
-With a numeric prefix, or when passed command line arguments in a call
+With a numeric argument, or when passed command line arguments in a call
from another widget, it behaves like tt(insert-last-word), except that
words in comments are ignored when tt(INTERACTIVE_COMMENTS) is set.
@@ -2471,12 +2535,12 @@ The effect is similar to the function of the same name in Emacs.
Transpose the current line with the previous line and move the cursor
to the start of the next line. Repeating this (which can be done by
-providing a positive numeric prefix argument) has the effect of moving
+providing a positive numeric argument) has the effect of moving
the line above the cursor down by a number of lines.
-With a negative numeric prefix argument, requires two lines above the
+With a negative numeric argument, requires two lines above the
cursor. These two lines are transposed and the cursor moved to the
-start of the previous line. Using a numeric prefix less than -1
+start of the previous line. Using a numeric argument less than -1
has the effect of moving the line above the cursor up by minus that
number of lines.
)
@@ -3227,8 +3291,18 @@ A reasonably powerful calculator based on zsh's arithmetic evaluation
facility. The syntax is similar to that of formulae in most programming
languages; see
ifzman(the section `Arithmetic Evaluation' in zmanref(zshmisc))\
-ifnzman(noderef(Arithmetic Evaluation)) for details. The mathematical
-library tt(zsh/mathfunc) will be loaded if it is available; see
+ifnzman(noderef(Arithmetic Evaluation)) for details.
+
+Non-programmers should note that, as in many other programming
+languages, expressions involving only integers (whether constants
+without a `tt(.)', variables containing such constants as strings, or
+variables declared to be integers) are by default evaluated using
+integer arithmetic, which is not how an ordinary desk calculator
+operates. To force floating point operation, pass the option tt(-f);
+see further notes below.
+
+The mathematical library tt(zsh/mathfunc) will be loaded if it is
+available; see
ifzman(the section `The zsh/mathfunc Module' in zmanref(zshmodules))\
ifnzman(noderef(The zsh/mathfunc Module)). The mathematical functions
correspond to the raw system libraries, so trigonometric functions are
@@ -3609,6 +3683,17 @@ If you quit in the middle of a game, the next invocation of the tt(tetris)
widget will continue where you left off. If you lost, it will start a new
game.
)
+item(tt(tetriscurses))(
+This is a port of the above to zcurses. The input handling is improved
+a bit so that moving a block sideways doesn't automatically advance a
+timestep, and the graphics use unicode block graphics.
+
+This version does not save the game state between invocations, and is not
+invoked as a widget, but rather as:
+
+example(autoload -U tetriscurses
+tetriscurses)
+)
findex(zargs)
item(tt(zargs) [ var(option) ... tt(-)tt(-) ] [ var(input) ... ] [ tt(-)tt(-) var(command) [ var(arg) ... ] ])(
This function has a similar purpose to GNU xargs. Instead of
diff --git a/Doc/Zsh/expn.yo b/Doc/Zsh/expn.yo
index 5aab25954..8728803e0 100644
--- a/Doc/Zsh/expn.yo
+++ b/Doc/Zsh/expn.yo
@@ -1061,6 +1061,9 @@ for arrays which keep only the first occurrence of duplicated values
item(tt(hide))(
for parameters with the `hide' flag
)
+item(tt(hideval))(
+for parameters with the `hideval' flag
+)
item(tt(special))(
for special parameters defined by the shell
)
@@ -1124,6 +1127,19 @@ item(tt(p))(
Recognize the same escape sequences as the tt(print) builtin
in string arguments to any of the flags described below that
follow this argument.
+
+Alternatively, with this option string arguments may be in the form
+tt($)var(var) in which case the value of the variable is substituted.
+Note this form is strict; the string argument does not undergo general
+parameter expansion.
+
+For example,
+
+example(sep=:
+val=a:b:c
+print ${+LPAR()ps.$sep.+RPAR()val})
+
+splits the variable on a tt(:).
)
item(tt(~))(
Strings inserted into the expansion by any of the flags below are to
@@ -2372,7 +2388,7 @@ item(tt(p))(
named pipes (FIFOs)
)
item(tt(*))(
-executable plain files (0100)
+executable plain files (0100 or 0010 or 0001)
)
item(tt(%))(
device files (character or block special)
@@ -2695,6 +2711,10 @@ example(ls *(-/))
lists all directories and symbolic links that point to directories,
and
+example(ls *(-@))
+
+lists all broken symbolic links, and
+
example(ls *(%W))
lists all world-writable device files in the current directory, and
diff --git a/Doc/Zsh/ftp_sites.yo b/Doc/Zsh/ftp_sites.yo
index 62c1bff06..804d975f3 100644
--- a/Doc/Zsh/ftp_sites.yo
+++ b/Doc/Zsh/ftp_sites.yo
@@ -1,15 +1,15 @@
startitem()
item(Primary site)(
-nofill(tt(ftp://ftp.zsh.org/pub/)
-tt(http://www.zsh.org/pub/))
+nofill(uref(ftp://ftp.zsh.org/pub/)
+uref(http://www.zsh.org/pub/))
)
item(Australia)(
-nofill(tt(ftp://ftp.zsh.org/pub/)
-tt(http://www.zsh.org/pub/)
-tt(http://mirror.dejanseo.com.au/pub/zsh/))
+nofill(uref(ftp://ftp.zsh.org/pub/)
+uref(http://www.zsh.org/pub/)
+uref(http://mirror.dejanseo.com.au/pub/zsh/))
)
item(Hungary)(
-nofill(tt(ftp://ftp.cs.elte.hu/pub/zsh/)
-tt(http://www.cs.elte.hu/pub/zsh/))
+nofill(uref(ftp://ftp.cs.elte.hu/pub/zsh/)
+uref(http://www.cs.elte.hu/pub/zsh/))
)
enditem()
diff --git a/Doc/Zsh/func.yo b/Doc/Zsh/func.yo
index 6e9cfeee9..ace0a4051 100644
--- a/Doc/Zsh/func.yo
+++ b/Doc/Zsh/func.yo
@@ -247,10 +247,10 @@ findex(preexec)
vindex(preexec_functions)
item(tt(preexec))(
Executed just after a command has been read and is about to be
-executed. If the history mechanism is active (and the line was not
-discarded from the history buffer), the string that the user typed is
-passed as the first argument, otherwise it is an empty string. The
-actual command that will be executed (including expanded aliases) is
+executed. If the history mechanism is active (regardless of whether the
+line was discarded from the history buffer), the string that the user
+typed is passed as the first argument, otherwise it is an empty string.
+The actual command that will be executed (including expanded aliases) is
passed in two different forms: the second argument is a single-line,
size-limited version of the command (with things like function bodies
elided); the third argument contains the full text that is being
diff --git a/Doc/Zsh/grammar.yo b/Doc/Zsh/grammar.yo
index 4d04c2470..522ad0472 100644
--- a/Doc/Zsh/grammar.yo
+++ b/Doc/Zsh/grammar.yo
@@ -239,7 +239,11 @@ item(tt(case) var(word) tt(in) [ [tt(LPAR())] var(pattern) [ tt(|) var(pattern)
Execute the var(list) associated with the first var(pattern)
that matches var(word), if any. The form of the patterns
is the same as that used for filename generation. See
-noderef(Filename Generation).
+noderef(Filename Generation). Note further that the whole
+pattern with alternatives is treated by the shell as equivalent
+to a group of patterns within parentheses, even though in
+the tt(case) syntax whitespace may appear about the parentheses and the
+vertical bar.
If the var(list) that is executed is terminated with tt(;&) rather than
tt(;;), the following list is also executed. The rule for
@@ -528,29 +532,54 @@ characters up to a newline to be ignored.
texinode(Aliasing)(Quoting)(Comments)(Shell Grammar)
sect(Aliasing)
cindex(aliasing)
-Every token in the shell input is checked to see if there
+Every eligible em(word) in the shell input is checked to see if there
is an alias defined for it.
If so, it is replaced by the text of the alias if it is in command
position (if it could be the first word of a simple command),
or if the alias is global.
-If the text ends with a space, the next word in the shell input
-is treated as though it were in command position for purposes of alias
-expansion.
+If the replacement text ends with a space, the next word in the shell input
+is always eligible for purposes of alias expansion.
findex(alias, use of)
cindex(aliases, global)
An alias is defined using the tt(alias) builtin; global aliases
may be defined using the tt(-g) option to that builtin.
+A em(word) is defined as:
+
+startitemize()
+itemiz(Any plain string or glob pattern)
+itemiz(Any quoted string, using any quoting method (note that the quotes
+must be part of the alias definition for this to be eligible))
+itemiz(Any parameter reference or command substitution)
+itemiz(Any series of the foregoing, concatenated without whitespace or
+other tokens between them)
+itemiz(Any reserved word (tt(case), tt(do), tt(else), etc.))
+itemiz(With global aliasing, any command separator, any redirection
+operator, and `tt(LPAR())' or `tt(RPAR())' when not part of a glob pattern)
+enditemize()
+
+It is not presently possible to alias the `tt(LPAR()LPAR())' token that
+introduces arithmetic expressions, because until a full statement has been
+parsed, it cannot be distinguished from two consecutive `tt(LPAR())'
+tokens introducing nested subshells.
+
+When tt(POSIX_ALIASES) is set, only plain unquoted strings are eligible
+for aliasing. The tt(alias) builtin does not reject ineligible aliases,
+but they are not expanded.
+
Alias expansion is done on the shell input before any other expansion
except history expansion. Therefore, if an alias is defined for the
word tt(foo), alias expansion may be avoided by quoting part of the
word, e.g. tt(\foo). Any form of quoting works, although there is
nothing to prevent an alias being defined for the quoted form such as
-tt(\foo) as well. For use with completion, which would remove an
-initial backslash followed by a character that isn't special, it may be
-more convenient to quote the word by starting with a single quote,
-i.e. tt('foo); completion will automatically add the trailing single
-quote.
+tt(\foo) as well. Also, if a separator such as tt(&&) is aliased,
+tt(\&&) turns into the two tokens tt(\&) and tt(&), each of which may
+have been aliased separately. Similarly for tt(\<<), tt(\>|), etc.
+
+For use with completion, which would remove an initial backslash followed
+by a character that isn't special, it may be more convenient to quote the
+word by starting with a single quote, i.e. tt('foo); completion will
+automatically add the trailing single quote.
There is a commonly encountered problem with aliases
illustrated by the following code:
diff --git a/Doc/Zsh/manual.yo b/Doc/Zsh/manual.yo
index 5184928c2..e0b0f14cb 100644
--- a/Doc/Zsh/manual.yo
+++ b/Doc/Zsh/manual.yo
@@ -5,7 +5,8 @@ texitop(The Z Shell Manual)
texiifinfo(\
This Info file documents Zsh, a freely available UNIX command interpreter
(shell), which of the standard shells most closely resembles the Korn shell
-(ksh), although it is not completely compatible.
+(ksh), although it is not completely compatible. Zsh is able to emulate
+POSIX shells, but its default mode is not POSIX compatible, either.
cindex(version)
Version version(), last updated date().
@@ -184,16 +185,16 @@ produce a nicely formatted printed manual.
item(The HTML manual)(
An HTML version of this manual is available at the Zsh web site via:
-tt(http://zsh.sourceforge.net/Doc/).
+uref(http://zsh.sourceforge.net/Doc/).
(The HTML version is produced with bf(texi2html), which may be obtained
-from tt(http://www.nongnu.org/texi2html/). The command is
+from uref(http://www.nongnu.org/texi2html/). The command is
`tt(texi2html --output . --ifinfo --split=chapter --node-files zsh.texi)'.
If necessary, upgrade to version 1.78 of texi2html.)
)
enditem()
For those who do not have the necessary tools to process texinfo,
-precompiled documentation (PostScript, dvi, info and HTML formats)
+precompiled documentation (PostScript, dvi, PDF, info and HTML formats)
is available from the zsh archive site or its mirrors, in the file
tt(zsh-doc.tar.gz). (See noderef(Availability) for a list of sites.)
diff --git a/Doc/Zsh/metafaq.yo b/Doc/Zsh/metafaq.yo
index 34cd70e32..6cb299ad1 100644
--- a/Doc/Zsh/metafaq.yo
+++ b/Doc/Zsh/metafaq.yo
@@ -27,10 +27,10 @@ cindex(acquiring zsh by FTP)
cindex(availability of zsh)
INCLUDEFILE(Zsh/ftp_sites.yo)\
-The up-to-date source code is available via anonymous CVS and Git from
-Sourceforge. See tt(http://sourceforge.net/projects/zsh/) for details.
-A summary of instructions for the CVS and Git archives can be found at
-tt(http://zsh.sourceforget.net/).
+The up-to-date source code is available via Git from Sourceforge. See
+uref(http://sourceforge.net/projects/zsh/) for details. A summary of
+instructions for the archive can be found at
+uref(http://zsh.sourceforge.net/).
texinode(Mailing Lists)(The Zsh FAQ)(Availability)(Introduction)
sect(Mailing Lists)
@@ -75,18 +75,18 @@ maintained by Karsten Thygesen tt(<karthy@kom.auc.dk>).
The mailing lists are archived; the archives can be accessed via the
administrative addresses listed above. There is also a hypertext
archive, maintained by Geoff Wing tt(<gcw@zsh.org>), available at
-tt(http://www.zsh.org/mla/).
+uref(http://www.zsh.org/mla/).
texinode(The Zsh FAQ)(The Zsh Web Page)(Mailing Lists)(Introduction)
sect(The Zsh FAQ)
Zsh has a list of Frequently Asked Questions (FAQ), maintained by
Peter Stephenson tt(<pws@zsh.org>). It is regularly posted to the
newsgroup bf(comp.unix.shell) and the bf(zsh-announce) mailing list.
The latest version can be found at any of the Zsh FTP sites, or at
-tt(http://www.zsh.org/FAQ/). The contact address for FAQ-related matters
+uref(http://www.zsh.org/FAQ/). The contact address for FAQ-related matters
is tt(<faqmaster@zsh.org>).
texinode(The Zsh Web Page)(The Zsh Userguide)(The Zsh FAQ)(Introduction)
sect(The Zsh Web Page)
-Zsh has a web page which is located at tt(http://www.zsh.org/). This is
+Zsh has a web page which is located at uref(http://www.zsh.org/). This is
maintained by Karsten Thygesen tt(<karthy@zsh.org>), of SunSITE Denmark.
The contact address for web-related matters is tt(<webmaster@zsh.org>).
texinode(The Zsh Userguide)(See Also)(The Zsh Web Page)(Introduction)
@@ -95,10 +95,10 @@ A userguide is currently in preparation. It is intended to complement the
manual, with explanations and hints on issues where the manual can be
cabbalistic, hierographic, or downright mystifying (for example, the word
`hierographic' does not exist). It can be viewed in its current state at
-tt(http://zsh.sourceforge.net/Guide/). At the time of writing, chapters
+uref(http://zsh.sourceforge.net/Guide/). At the time of writing, chapters
dealing with startup files and their contents and the new completion system
were essentially complete.
sect(The Zsh Wiki)
-A `wiki' website for zsh has been created at tt(http://www.zshwiki.org/).
+A `wiki' website for zsh has been created at uref(http://www.zshwiki.org/).
This is a site which can be added to and modified directly by users without
any special permission. You can add your own zsh tips and configurations.
diff --git a/Doc/Zsh/mod_datetime.yo b/Doc/Zsh/mod_datetime.yo
index 619067698..27bc78157 100644
--- a/Doc/Zsh/mod_datetime.yo
+++ b/Doc/Zsh/mod_datetime.yo
@@ -8,25 +8,46 @@ findex(strftime)
cindex(date string, printing)
xitem(tt(strftime) [ tt(-s) var(scalar) ] var(format) var(epochtime) )
item(tt(strftime) tt(-r) [ tt(-q) ] [ tt(-s) var(scalar) ] var(format) var(timestring) )(
-Output the date denoted by var(epochtime) in the var(format)
-specified.
+Output the date denoted by var(epochtime) in the var(format) specified.
+See manref(strftime)(3) for details. The zsh extensions described in
+ifzman(the section EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\
+ifnzman(noderef(Prompt Expansion)) are also available.
-With the option tt(-r) (reverse), use the format var(format) to parse the
-input string var(timestring) and output the number of seconds since the
-epoch at which the time occurred. If no timezone is parsed, the current
-timezone is used; other parameters are set to zero if not present. If
-var(timestring) does not match var(format) the command returns status 1; it
-will additionally print an error message unless the option tt(-q) (quiet)
-is given. If var(timestring) matches var(format) but not all characters in
-var(timestring) were used, the conversion succeeds; however, a warning is
-issued unless the option tt(-q) is given. The matching is implemented by
-the system function tt(strptime); see manref(strptime)(3). This means that
-zsh format extensions are not available, however for reverse lookup they
-are not required. If the function is not implemented, the command returns
-status 2 and (unless tt(-q) is given) prints a message.
+startitem()
+item(tt(-q))(
+Run quietly; suppress printing of all error messages described below.
+Errors for invalid var(epochtime) values are always printed.
+)
+item(tt(-r))(
+With the option tt(-r) (reverse), use var(format) to parse the input
+string var(timestring) and output the number of seconds since the epoch at
+which the time occurred. The parsing is implemented by the system
+function tt(strptime); see manref(strptime)(3). This means that zsh
+format extensions are not available, but for reverse lookup they are not
+required.
+
+In most implementations of tt(strftime) any timezone in the
+var(timestring) is ignored and the local timezone declared by the tt(TZ)
+environment variable is used; other parameters are set to zero if not
+present.
+
+If var(timestring) does not match var(format) the command returns status 1
+and prints an error message. If var(timestring) matches var(format) but
+not all characters in var(timestring) were used, the conversion succeeds
+but also prints an error message.
+
+If either of the system functions tt(strptime) or tt(mktime) is not
+available, status 2 is returned and an error message is printed.
+)
+item(tt(-s) var(scalar))(
+Assign the date string (or epoch time in seconds if tt(-r) is given) to
+var(scalar) instead of printing it.
+)
+enditem()
-If tt(-s) var(scalar) is given, assign the date string (or epoch time
-in seconds if tt(-r) is given) to var(scalar) instead of printing it.
+Note that depending on the system's declared integral time type,
+tt(strftime) may produce incorrect results for epoch times greater than
+2147483647 which corresponds to 2038-01-19 03:14:07 +0000.
)
enditem()
diff --git a/Doc/Zsh/mod_db_gdbm.yo b/Doc/Zsh/mod_db_gdbm.yo
new file mode 100644
index 000000000..90974297c
--- /dev/null
+++ b/Doc/Zsh/mod_db_gdbm.yo
@@ -0,0 +1,51 @@
+COMMENT(!MOD!zsh/db/gdbm
+Builtins for managing associative array parameters tied to GDBM databases.
+!MOD!)
+The tt(zsh/db/gdbm) module is used to create "tied" associative arrays
+that interface to database files. If the GDBM interface is not available,
+the builtins defined by this module will report an error. This module is
+also intended as a prototype for creating additional database interfaces,
+so the tt(ztie) builtin may move to a more generic module in the future.
+
+The builtins in this module are:
+
+startitem()
+findex(ztie)
+cindex(database tied array, creating)
+item(tt(ztie -d db/gdbm -f) var(filename) [ tt(-r) ] var(arrayname))(
+Open the GDBM database identified by var(filename) and, if successful,
+create the associative array var(arrayname) linked to the file. To create
+a local tied array, the parameter must first be declared, so commands
+similar to the following would be executed inside a function scope:
+
+example(local -A sampledb
+ztie -d db/gdbm -f sample.gdbm sampledb)
+
+The tt(-r) option opens the database file for reading only, creating a
+parameter with the readonly attribute. Without this option, using
+`tt(ztie)' on a file for which the user does not have write permission is
+an error. If writable, the database is opened synchronously so fields
+changed in var(arrayname) are immediately written to var(filename).
+
+Changes to the file modes var(filename) after it has been opened do not
+alter the state of var(arrayname), but `tt(typeset -r) var(arrayname)'
+works as expected.
+)
+findex(zuntie)
+cindex(database tied array, destroying)
+item(tt(zuntie) [ tt(-u) ] var(arrayname) ...)(
+Close the GDBM database associated with each var(arrayname) and then
+unset the parameter. The tt(-u) option forces an unset of parameters
+made readonly with `tt(ztie -r)'.
+
+This happens automatically if the parameter is explicitly unset or its
+local scope (function) ends. Note that a readonly parameter may not be
+explicitly unset, so the only way to unset a global parameter created with
+`tt(ztie -r)' is to use `tt(zuntie -u)'.
+)
+enditem()
+
+The fields of an associative array tied to GDBM are neither cached nor
+otherwise stored in memory, they are read from or written to the database
+on each reference. Thus, for example, the values in a readonly array may
+be changed by a second writer of the same database file.
diff --git a/Doc/Zsh/mod_files.yo b/Doc/Zsh/mod_files.yo
index 5dbdae7d2..90e988474 100644
--- a/Doc/Zsh/mod_files.yo
+++ b/Doc/Zsh/mod_files.yo
@@ -10,7 +10,10 @@ all features now required by relevant standards committees.
For all commands, a variant beginning tt(zf_) is also available and loaded
automatically. Using the features capability of zmodload will let you load
-only those names you want.
+only those names you want. Note that it's possible to load only the
+builtins with zsh-specific names using the following command:
+
+example(zmodload -m -F zsh/files b:zf_\*)
The commands loaded by default are:
diff --git a/Doc/Zsh/mod_system.yo b/Doc/Zsh/mod_system.yo
index dce07175f..7101e37dc 100644
--- a/Doc/Zsh/mod_system.yo
+++ b/Doc/Zsh/mod_system.yo
@@ -178,12 +178,15 @@ used.
vindex(sysparams)
item(tt(sysparams))(
A readonly associative array. The keys are:
+
startitem()
item(tt(pid))(
+vindex(pid, sysparams)
Returns the process ID of the current process, even in subshells. Compare
tt($$), which returns the process ID of the main shell process.
)
item(tt(ppid))(
+vindex(ppid, sysparams)
Returns the process ID of the parent of the current process, even in
subshells. Compare tt($PPID), which returns the process ID of the parent
of the main shell process.
diff --git a/Doc/Zsh/options.yo b/Doc/Zsh/options.yo
index 068a253ac..20d9fc2a8 100644
--- a/Doc/Zsh/options.yo
+++ b/Doc/Zsh/options.yo
@@ -63,6 +63,10 @@ item(tt(AUTO_CD) (tt(-J)))(
If a command is issued that can't be executed as a normal command,
and the command is the name of a directory, perform the tt(cd)
command to that directory.
+This option is only applicable if the option tt(SHIN_STDIN) is set,
+i.e. if commands are being read from standard input. The option
+is designed for interactive use; it is recommended that tt(cd)
+be used explicitly in scripts to avoid ambiguity.
)
pindex(AUTO_PUSHD)
pindex(NO_AUTO_PUSHD)
@@ -492,9 +496,10 @@ pindex(NOFORCEFLOAT)
cindex(floating point, forcing use of)
cindex(forcing use of floating point)
item(tt(FORCE_FLOAT))(
-Constants in arithmetic evaluation will be treated as floating point
-even without the use of a decimal point. Integers in any base
-will be converted.
+Constants in arithmetic evaluation will be treated as
+floating point even without the use of a decimal point; the
+values of integer variables will be converted to floating point when
+used in arithmetic expressions. Integers in any base will be converted.
)
pindex(GLOB)
pindex(NO_GLOB)
@@ -535,7 +540,7 @@ pindex(GLOBSUBST)
pindex(NOGLOBSUBST)
item(tt(GLOB_SUBST) <C> <K> <S>)(
Treat any characters resulting from parameter expansion as being
-eligible for file expansion and filename generation, and any
+eligible for filename expansion and filename generation, and any
characters resulting from command substitution as being eligible for
filename generation. Braces (and commas in between) do not become eligible
for expansion.
@@ -804,7 +809,7 @@ pindex(NOHISTBEEP)
cindex(history beeping)
cindex(beep, history)
item(tt(HIST_BEEP) <D>)(
-Beep when an attempt is made to access a history entry which
+Beep in ZLE when a widget attempts to access a history entry which
isn't there.
)
pindex(HIST_EXPIRE_DUPS_FIRST)
@@ -1434,10 +1439,10 @@ shell is saved for output within a subshell (for example, within a
pipeline). When the option is set, the output of tt(jobs) is empty
until a job is started within the subshell.
-When the option is set, it becomes possible to use the tt(wait) builtin to
-wait for the last job started in the background (as given by tt($!)) even
-if that job has already exited. This works even if the option is turned
-on temporarily around the use of the tt(wait) builtin.
+In previous versions of the shell, it was necessary to enable
+tt(POSIX_JOBS) in order for the builtin command tt(wait) to return the
+status of background jobs that had already exited. This is no longer
+the case.
)
enditem()
@@ -1841,8 +1846,8 @@ cindex(history style, csh)
item(tt(CSH_JUNKIE_HISTORY) <C>)(
A history reference without an event specifier will always refer to the
previous command. Without this option, such a history reference refers
-to the same event as the previous history reference, defaulting to the
-previous command.
+to the same event as the previous history reference on the current
+command line, defaulting to the previous command.
)
pindex(CSH_JUNKIE_LOOPS)
pindex(NO_CSH_JUNKIE_LOOPS)
@@ -2092,7 +2097,7 @@ pindex(NOPOSIXTRAPS)
cindex(traps, on function exit)
cindex(traps, POSIX compatibility)
item(tt(POSIX_TRAPS) <K> <S>)(
-When the is option is set, the usual zsh behaviour of executing
+When this option is set, the usual zsh behaviour of executing
traps for tt(EXIT) on exit from shell functions is suppressed.
In that case, manipulating tt(EXIT) traps always alters the global
trap for exiting the shell; the tt(LOCAL_TRAPS) option is
@@ -2195,10 +2200,22 @@ pindex(NOPRIVILEGED)
cindex(privileged mode)
cindex(mode, privileged)
item(tt(PRIVILEGED) (tt(-p), ksh: tt(-p)))(
-Turn on privileged mode. This is enabled automatically on startup if the
-effective user (group) ID is not equal to the real user (group) ID. Turning
-this option off causes the effective user and group IDs to be set to the
-real user and group IDs. This option disables sourcing user startup files.
+Turn on privileged mode. Typically this is used when script is to be run
+with elevated privileges. This should be done as follows directly with
+the tt(-p) option to zsh so that it takes effect during startup.
+
+example(#!/bin/zsh -p)
+
+The option is enabled automatically on startup if the effective user
+(group) ID is not equal to the real user (group) ID. In this case,
+turning the option off causes the effective user and group IDs to be set
+to the real user and group IDs. Be aware that if that fails the shell may
+be running with different IDs than was intended so a script should check
+for failure and act accordingly, for example:
+
+example(unsetopt privileged || exit)
+
+The tt(PRIVILEGED) option disables sourcing user startup files.
If zsh is invoked as `tt(sh)' or `tt(ksh)' with this option set,
tt(/etc/suid_profile) is sourced (after tt(/etc/profile) on interactive
shells). Sourcing tt(~/.profile) is disabled and the contents of the
@@ -2231,7 +2248,7 @@ taken as a file to run will instead be treated as a normal positional
parameter.
Note that setting or unsetting this option on the command line does not
necessarily affect the state the option will have while the shell is
-running - that is purely an indicator of whether on not commands are
+running - that is purely an indicator of whether or not commands are
em(actually) being read from standard input.
The value of this option can only be changed via flags supplied at
invocation of the shell.
diff --git a/Doc/Zsh/params.yo b/Doc/Zsh/params.yo
index 3698829f3..9d06b6af6 100644
--- a/Doc/Zsh/params.yo
+++ b/Doc/Zsh/params.yo
@@ -1,48 +1,81 @@
texinode(Parameters)(Options)(Expansion)(Top)
chapter(Parameters)
cindex(parameters)
+cindex(variables)
sect(Description)
A parameter has a name, a value, and a number of attributes.
A name may be any sequence of alphanumeric
characters and underscores, or the single characters
`tt(*)', `tt(@)', `tt(#)', `tt(?)', `tt(-)', `tt($)', or `tt(!)'.
-The value may be a em(scalar) (a string),
-an integer, an array (indexed numerically), or an em(associative)
-array (an unordered set of name-value pairs, indexed by name). To declare
-the type of a parameter, or to assign a scalar or integer value to a
-parameter, use the tt(typeset) builtin.
+A parameter whose name begins with an alphanumeric or underscore is also
+referred to as a em(variable).
+
+cindex(scalar)
+cindex(parameters, scalar)
+cindex(parameters, array)
+cindex(parameters, associative array)
+cindex(hash)
+The attributes of a parameter determine the em(type) of its value, often
+referred to as the parameter type or variable type, and also control
+other processing that may be applied to the value when it is referenced.
+The value type may be a em(scalar) (a string, an integer, or a floating
+point number), an array (indexed numerically), or an em(associative)
+array (an unordered set of name-value pairs, indexed by name, also
+referred to as a em(hash)).
+
+cindex(export)
+cindex(environment)
+cindex(environment variables)
+cindex(variables, environment)
+Named scalar parameters may have the em(exported), tt(-x), attribute, to
+copy them into the process environment, which is then passed from the
+shell to any new processes that it starts. Exported parameters are called
+em(environment variables). The shell also em(imports) environment variables
+at startup time and automatically marks the corresponding parameters as
+exported. Some environment variables are not imported for reasons of
+security or because they would interfere with the correct operation of
+other shell features.
+
+cindex(special parameters)
+cindex(parameters, special)
+Parameters may also be em(special), that is, they have a predetermined
+meaning to the shell. Special parameters cannot have their type changed
+or their readonly attribute turned off, and if a special parameter is
+unset, then later recreated, the special properties will be retained.
+
+To declare the type of a parameter, or to assign a string or numeric value
+to a scalar parameter, use the tt(typeset) builtin.
findex(typeset, use of)
-The value of a scalar or integer parameter may also be assigned by
-writing:
+The value of a scalar parameter may also be assigned by writing:
cindex(assignment)
-
+ifzman()
indent(var(name)tt(=)var(value))
-If the integer attribute, tt(-i), is set for var(name), the var(value)
-is subject to arithmetic evaluation. Furthermore, by replacing `tt(=)'
-with `tt(+=)', a parameter can be added or appended to.
-
In scalar assignment, var(value) is expanded as a single string, in
which the elements of arrays are joined together; filename expansion is
-not performed unless the option tt(GLOB_ASSIGN) is set. See
-noderef(Array Parameters) for additional forms of assignment.
-
-To refer to the value of a parameter, write `tt($)var(name)' or
+not performed unless the option tt(GLOB_ASSIGN) is set.
+
+When the integer attribute, tt(-i), or a floating point attribute, tt(-E)
+or tt(-F), is set for var(name), the var(value) is subject to arithmetic
+evaluation. Furthermore, by replacing `tt(=)' with `tt(+=)', a parameter
+can be incremented or appended to. See noderef(Array Parameters) and
+ifzman(em(Arithmetic Evaluation) LPAR()in zmanref(zshexpn)RPAR())\
+ifnzman(noderef(Arithmetic Evaluation))
+for additional forms of assignment.
+
+Note that assignment may implicitly change the attributes of a parameter.
+For example, assigning a number to a variable in arithmetic evaluation may
+change its type to integer or float, and with tt(GLOB_ASSIGN) assigning a
+pattern to a variable may change its type to an array.
+
+To reference the value of a parameter, write `tt($)var(name)' or
`tt(${)var(name)tt(})'. See
ifzman(em(Parameter Expansion) in zmanref(zshexpn))\
ifnzman(noderef(Parameter Expansion))
-for complete details. This section also explains the effect
+for complete details. That section also explains the effect
of the difference between scalar and array assignment on parameter
expansion.
-
-In the parameter lists that follow, the mark `<S>' indicates that the
-parameter is special.
-Special parameters cannot have their type changed or their
-readonly attribute turned off, and if a special parameter is unset, then
-later recreated, the special properties will be retained. `<Z>' indicates
-that the parameter does not exist when the shell initializes in tt(sh) or
-tt(ksh) emulation mode.
startmenu()
menu(Array Parameters)
menu(Positional Parameters)
@@ -55,39 +88,48 @@ sect(Array Parameters)
To assign an array value, write one of:
findex(set, use of)
cindex(array assignment)
-
+ifzman()
indent(tt(set -A) var(name) var(value) ...)
indent(var(name)tt(=LPAR())var(value) ...tt(RPAR()))
If no parameter var(name) exists, an ordinary array parameter is created.
If the parameter var(name) exists and is a scalar, it is replaced by a new
-array. Ordinary array parameters may also be explicitly declared with:
-findex(typeset, use of)
+array. To append to an array without changing the existing values, use
+the syntax:
+ifzman()
+indent(var(name)tt(+=LPAR())var(value) ...tt(RPAR()))
+Ordinary array parameters may also be explicitly declared with:
+findex(typeset, use of)
+ifzman()
indent(tt(typeset -a) var(name))
Associative arrays em(must) be declared before assignment, by using:
-
+ifzman()
indent(tt(typeset -A) var(name))
When var(name) refers to an associative array, the list in an assignment
is interpreted as alternating keys and values:
-
+ifzman()
indent(set -A var(name) var(key) var(value) ...)
indent(var(name)tt(=LPAR())var(key) var(value) ...tt(RPAR()))
Every var(key) must have a var(value) in this case. Note that this
-assigns to the entire array, deleting any elements that do not appear
-in the list.
+assigns to the entire array, deleting any elements that do not appear in
+the list. The append syntax may also be used with an associative array:
+ifzman()
+indent(var(name)tt(+=LPAR())var(key) var(value) ...tt(RPAR()))
-To create an empty array (including associative arrays), use one of:
+This adds a new key/value pair if the key is not already present, and
+replaces the value for the existing key if it is.
+To create an empty array (including associative arrays), use one of:
+ifzman()
indent(tt(set -A) var(name))
indent(var(name)tt(=LPAR()RPAR()))
subsect(Array Subscripts)
cindex(subscripts)
-
Individual elements of an array may be selected using a subscript. A
subscript of the form `tt([)var(exp)tt(])' selects the single element
var(exp), where var(exp) is an arithmetic expression which will be subject
@@ -145,12 +187,32 @@ from the end of the array tt(foo), and
Subscripting may also be performed on non-array values, in which
case the subscripts specify a substring to be extracted.
For example, if tt(FOO) is set to `tt(foobar)', then
-`tt(echo $FOO[2,5])' prints `tt(ooba)'.
+`tt(echo $FOO[2,5])' prints `tt(ooba)'. Note that
+some forms of subscripting described below perform pattern matching,
+and in that case the substring extends from the start of the match
+of the first subscript to the end of the match of the second
+subscript. For example,
+
+example(string="abcdefghijklm"
+print ${string[+LPAR()r+RPAR()d?,+LPAR()r+RPAR()h?]})
+
+prints `tt(defghi)'. This is an obvious generalisation of the
+rule for single-character matches. For a single subscript,
+only a single character is referenced (not the range of characters
+covered by the match).
+
+Note that in substring operations the second subscript is handled
+differently by the tt(r) and tt(R) subscript flags: the former takes the
+shortest match as the length and the latter the longest match. Hence
+in the former case a tt(*) at the end is redundant while in
+the latter case it matches the whole remainder of the string. This
+does not affect the result of the single subscript case as here the
+length of the match is irrelevant.
subsect(Array Element Assignment)
A subscript may be used on the left side of an assignment like so:
-
+ifzman()
indent(var(name)tt([)var(exp)tt(]=)var(value))
In this form of assignment the element or range specified by var(exp)
@@ -162,7 +224,7 @@ other elements to accommodate the new values. (This is not supported for
associative arrays.)
This syntax also works as an argument to the tt(typeset) command:
-
+ifzman()
indent(tt(typeset) tt(")var(name)tt([)var(exp)tt(]"=)var(value))
The var(value) may em(not) be a parenthesized list in this case; only
@@ -174,12 +236,11 @@ could be used instead.
To delete an element of an ordinary array, assign `tt(LPAR()RPAR())' to
that element. To delete an element of an associative array, use the
tt(unset) command:
-
+ifzman()
indent(tt(unset) tt(")var(name)tt([)var(exp)tt(]"))
subsect(Subscript Flags)
cindex(subscript flags)
-
If the opening bracket, or the comma in a range, in any subscript
expression is directly followed by an opening parenthesis, the string up
to the matching closing one is considered to be a list of flags, as in
@@ -319,16 +380,13 @@ patterns used for reverse subscripting (the `tt(r)', `tt(R)', `tt(i)',
etc. flags), but it may also affect parameter substitutions that appear
as part of an arithmetic expression in an ordinary subscript.
-It is possible to avoid the use of subscripts in assignments to associative
-array elements by using the syntax:
+To avoid subscript parsing limitations in assignments to associative array
+elements, use the append syntax:
example(
aa+=('key with "*strange*" characters' 'value string')
)
-This adds a new key/value pair if the key is not already present, and
-replaces the value for the existing key if it is.
-
The basic rule to remember when writing a subscript expression is that all
text between the opening `tt([)' and the closing `tt(])' is interpreted
em(as if) it were in double quotes (\
@@ -493,6 +551,10 @@ were never exported has been removed.
texinode(Parameters Set By The Shell)(Parameters Used By The Shell)(Local Parameters)(Parameters)
sect(Parameters Set By The Shell)
+In the parameter lists that follow, the mark `<S>' indicates that the
+parameter is special. `<Z>' indicates that the parameter does not exist
+when the shell initializes in tt(sh) or tt(ksh) emulation mode.
+
The following parameters are automatically set by the shell:
startitem()
@@ -712,6 +774,17 @@ It may be reset, clearing the error condition. See
ifzman(em(Complex Commands) in zmanref(zshmisc))\
ifnzman(noderef(Complex Commands))
)
+vindex(TRY_BLOCK_INTERRUPT)
+item(tt(TRY_BLOCK_INTERRUPT) <S>)(
+This variable works in a similar way to tt(TRY_BLOCK_ERROR), but
+represents the status of an interrupt from the signal SIGINT, which
+typically comes from the keyboard when the user types tt(^C). If set to
+0, any such interrupt will be reset; otherwise, the interrupt is
+propagated after the tt(always) block.
+
+Note that it is possible that an interrupt arrives during the execution
+of the tt(always) block; this interrupt is also propagated.
+)
vindex(TTY)
item(tt(TTY))(
The name of the tty associated with the shell, if any.
@@ -870,7 +943,9 @@ The version number of the release of zsh.
enditem()
texinode(Parameters Used By The Shell)()(Parameters Set By The Shell)(Parameters)
sect(Parameters Used By The Shell)
-The following parameters are used by the shell.
+The following parameters are used by the shell. Again, `<S>' indicates
+that the parameter is special and `<Z>' indicates that the parameter does
+not exist when the shell initializes in tt(sh) or tt(ksh) emulation mode.
In cases where there are two parameters with an upper- and lowercase
form of the same name, such as tt(path) and tt(PATH), the lowercase form
@@ -997,10 +1072,25 @@ item(tt(HISTORY_IGNORE))(
If set, is treated as a pattern at the time history files are written.
Any potential history entry that matches the pattern is skipped. For
example, if the value is `tt(fc *)' then commands that invoke the
-interactive history editor are never written to the history file (compare
-the tt(HIST_NO_STORE) option or the tt(zshaddhistory) hook, either of
-which would prevent such commands from being added to the interactive
-history at all).
+interactive history editor are never written to the history file.
+
+Note that tt(HISTORY_IGNORE) defines a single pattern: to
+specify alternatives use the `tt(+LPAR()first|second|...+RPAR())'
+syntax.
+
+Compare the tt(HIST_NO_STORE) option or the tt(zshaddhistory) hook,
+either of which would prevent such commands from being added to the
+interactive history at all. If you wish to use tt(HISTORY_IGNORE) to
+stop history being added in the first place, you can define the
+following hook:
+
+example(zshaddhistory+LPAR()RPAR() {
+ emulate -L zsh
+ ## uncomment if HISTORY_IGNORE
+ ## should use EXTENDED_GLOB syntax
+ # setopt extendedglob
+ [[ $1 != ${~HISTORY_IGNORE} ]]
+})
)
vindex(HISTSIZE)
item(tt(HISTSIZE) <S>)(
@@ -1355,7 +1445,7 @@ sitem(tt(%U))(CPU seconds spent in user mode.)
sitem(tt(%S))(CPU seconds spent in kernel mode.)
sitem(tt(%E))(Elapsed time in seconds.)
sitem(tt(%P))(The CPU percentage, computed as
-(100*tt(%U)PLUS()tt(%S))/tt(%E).)
+100*(tt(%U)PLUS()tt(%S))/tt(%E).)
sitem(tt(%W))(Number of times the process was swapped.)
sitem(tt(%X))(The average amount in (shared) text space used in kilobytes.)
sitem(tt(%D))(The average amount in (unshared) data/stack space used in
@@ -1402,15 +1492,27 @@ vindex(watch)
vindex(WATCH)
item(tt(watch) <S> <Z> (tt(WATCH) <S>))(
An array (colon-separated list) of login/logout events to report.
+
If it contains the single word `tt(all)', then all login/logout events
are reported. If it contains the single word `tt(notme)', then all
events are reported as with `tt(all)' except tt($USERNAME).
+
An entry in this list may consist of a username,
an `tt(@)' followed by a remote hostname,
-and a `tt(%)' followed by a line (tty).
+and a `tt(%)' followed by a line (tty). Any of these may
+be a pattern (be sure to quote this during the assignment to
+tt(watch) so that it does not immediately perform file generation);
+the setting of the tt(EXTENDED_GLOB) option is respected.
Any or all of these components may be present in an entry;
if a login/logout event matches all of them,
it is reported.
+
+For example, with the tt(EXTENDED_GLOB) option set, the following:
+
+example(watch=('^(pws|barts)'))
+
+causes reports for activity assoicated with any user other than tt(pws)
+or tt(barts).
)
vindex(WATCHFMT)
item(tt(WATCHFMT))(
@@ -1466,6 +1568,12 @@ The date in `var(mm)tt(/)var(dd)tt(/)var(yy)' format.
item(tt(%D))(
The date in `var(yy)tt(-)var(mm)tt(-)var(dd)' format.
)
+item(tt(%D{)var(string)tt(}))(
+The date formatted as var(string) using the tt(strftime) function, with
+zsh extensions as described by
+ifzman(EXPANSION OF PROMPT SEQUENCES in zmanref(zshmisc))\
+ifnzman(noderef(Prompt Expansion)).
+)
item(tt(%LPAR())var(x)tt(:)var(true-text)tt(:)var(false-text)tt(RPAR()))(
Specifies a ternary expression.
The character following the var(x) is
diff --git a/Doc/Zsh/prompt.yo b/Doc/Zsh/prompt.yo
index 17af5b0fb..307587678 100644
--- a/Doc/Zsh/prompt.yo
+++ b/Doc/Zsh/prompt.yo
@@ -93,7 +93,7 @@ continuation lines and tt(PS4) for debugging with the tt(XTRACE) option; in
the latter case it will also work non-interactively.
)
xitem(tt(%d))
-item(tt(/))(
+item(tt(%/))(
Current working directory. If an integer follows the `tt(%)',
it specifies a number of trailing components of the current working
directory to show; zero means the whole path. A negative integer
@@ -274,7 +274,7 @@ The value of the first element of the tt(psvar) array parameter. Following
the `tt(%)' with an integer gives that element of the array. Negative
integers count from the end of the array.
)
-item(tt(%LPAR())var(x.true-text.false-text)tt(RPAR()))(
+item(tt(%LPAR())var(x)tt(.)var(true-text)tt(.)var(false-text)tt(RPAR()))(
Specifies a ternary expression. The character following the var(x) is
arbitrary; the same character is used to separate the text for the
`true' result from that for the `false' result.
@@ -364,17 +364,18 @@ level (i.e. truncations inside a `tt(%LPAR())' are separate), which
ever comes first. In particular, a truncation with argument zero
(e.g., `tt(%<<)') marks the end of the range of the string to be
truncated while turning off truncation from there on. For example, the
-prompt '%10<...<%~%<<%# ' will print a truncated representation of the
+prompt `tt(%10<...<%~%<<%# )' will print a truncated representation of the
current directory, followed by a `tt(%)' or `tt(#)', followed by a
space. Without the `tt(%<<)', those two characters would be included
-in the string to be truncated. Note that `tt(%-0<<)' is a distinct
+in the string to be truncated. Note that `tt(%-0<<)' is not equivalent
+to `tt(%<<)' but specifies that the prompt is truncated at the right margin.
Truncation applies only within each individual line of the prompt, as
delimited by embedded newlines (if any). If the total length of any line
of the prompt after truncation is greater than the terminal width, or if
the part to be truncated contains embedded newlines, truncation behavior
is undefined and may change in a future version of the shell. Use
-`tt(%-var(n)LPAR()l.var(true-text).var(false-text)RPAR())' to remove parts
+`tt(%-)var(n)tt(LPAR()l.)var(true-text)tt(.)var(false-text)tt(RPAR())' to remove parts
of the prompt when the available space is less than var(n).
)
enditem()
diff --git a/Doc/Zsh/roadmap.yo b/Doc/Zsh/roadmap.yo
index ba598e5ea..bd064e2b2 100644
--- a/Doc/Zsh/roadmap.yo
+++ b/Doc/Zsh/roadmap.yo
@@ -41,13 +41,15 @@ set appropriate variables, and the number of history lines retained by
default is quite small (30 lines). See the description of the shell
variables (referred to in the documentation as parameters) tt(HISTFILE),
tt(HISTSIZE) and tt(SAVEHIST) in ifzman(zmanref(zshparam))\
-ifnzman(noderef(Parameters Used By The Shell)).
+ifnzman(noderef(Parameters Used By The Shell)). Note that it's
+currently only possible to read and write files saving history
+when the shell is interactive, i.e. it does not work from scripts.
The shell now supports the UTF-8 character set (and also others if
supported by the operating system). This is (mostly) handled transparently
by the shell, but the degree of support in terminal emulators is variable.
There is some discussion of this in the shell FAQ,
-http://zsh.dotsrc.org/FAQ/ . Note in particular that for combining
+uref(http://www.zsh.org/FAQ/). Note in particular that for combining
characters to be handled the option tt(COMBINING_CHARS) needs to be set.
Because the shell is now more sensitive to the definition of the
character set, note that if you are upgrading from an older version of
diff --git a/Doc/Zsh/zle.yo b/Doc/Zsh/zle.yo
index 98f38025a..653678eba 100644
--- a/Doc/Zsh/zle.yo
+++ b/Doc/Zsh/zle.yo
@@ -40,6 +40,17 @@ the following setting:
example(zle_highlight=(none))
+In many places, references are made to the tt(numeric argument). This can
+by default be entered in emacs mode by holding the alt key and typing
+a number, or pressing escape before each number, and in vi command mode
+by typing the number before entering a command. Generally the numeric
+argument causes the next command entered to be repeated the specified
+number of times, unless otherwise noted below. See also
+ifzman(the em(Arguments) subsection of the em(Widgets) section )\
+ifnzman(noderef(Arguments) )\
+for some other ways the numeric argument can be modified. The default
+bindings mentioned here use the tt(digit-argument) widget.
+
startmenu()
menu(Keymaps)
menu(Zle Builtins)
@@ -60,12 +71,14 @@ or more names. If all of a keymap's names are deleted, it disappears.
findex(bindkey, use of)
tt(bindkey) can be used to manipulate keymap names.
-Initially, there are six keymaps:
+Initially, there are eight keymaps:
startsitem()
sitem(tt(emacs))(EMACS emulation)
sitem(tt(viins))(vi emulation - insert mode)
sitem(tt(vicmd))(vi emulation - command mode)
+sitem(tt(viopp))(vi emulation - operator pending)
+sitem(tt(visual))(vi emulation - selection active)
sitem(tt(isearch))(incremental search mode)
sitem(tt(command))(read a command name)
sitem(tt(.safe))(fallback keymap)
@@ -122,6 +135,21 @@ in user-defined widgets with the tt(read-command) widget, described
ifzman(below)\
ifnzman(in noderef(Miscellaneous) below)\
.
+subsect(Local Keymaps)
+cindex(local keymaps)
+While for normal editing a single keymap is used exclusively, in many
+modes a local keymap allows for some keys to be customised. For example,
+in an incremental search mode, a binding in the tt(isearch) keymap will
+override a binding in the tt(main) keymap but all keys that are not
+overriden can still be used.
+
+If a key sequence is defined in a local keymap, it will hide a key
+sequence in the global keymap that is a prefix of that sequence. An
+example of this occurs with the binding of tt(iw) in tt(viopp) as this
+hides the binding of tt(i) in tt(vicmd). However, a longer sequence in
+the global keymap that shares the same prefix can still apply so for
+example the binding of tt(^Xa) in the global keymap will be unaffected
+by the binding of tt(^Xb) in the local keymap.
texinode(Zle Builtins)(Zle Widgets)(Keymaps)(Zsh Line Editor)
sect(Zle Builtins)
@@ -295,6 +323,8 @@ sitem(tt(\t))(horizontal tab)
sitem(tt(\v))(vertical tab)
sitem(tt(\)var(NNN))(character code in octal)
sitem(tt(\x)var(NN))(character code in hexadecimal)
+sitem(tt(\u)var(NNNN))(unicode character code in hexadecimal)
+sitem(tt(\U)var(NNNNNNNN))(unicode character code in hexadecimal)
sitem(tt(\M)[tt(-)]var(X))(character with meta bit set)
sitem(tt(\C)[tt(-)]var(X))(control character)
sitem(tt(^)var(X))(control character)
@@ -630,9 +660,9 @@ item(var(widget) tt([ -n) var(num) tt(]) tt([ -Nw ] [ -K) var(keymap) tt(]) var(
Invoke the specified widget. This can only be done when ZLE is
active; normally this will be within a user-defined widget.
-With the options tt(-n) and tt(-N), the current numerical argument will be
+With the options tt(-n) and tt(-N), the current numeric argument will be
saved and then restored after the call to tt(widget); `tt(-n) var(num)'
-sets the numerical argument temporarily to var(num), while `tt(-N)' sets it
+sets the numeric argument temporarily to var(num), while `tt(-N)' sets it
to the default, i.e. as if there were none.
With the option tt(-K), var(keymap) will be used as the current keymap
@@ -713,6 +743,21 @@ local scope, like parameters created in a function using tt(local).
Inside completion widgets and traps called while ZLE is active, these
parameters are available read-only.
+Note that the parameters appear as local to any ZLE widget in
+which they appear. Hence if it is desired to override them this needs
+to be done within a nested function:
+
+example(widget-function+LPAR()+RPAR() {
+ # $WIDGET here refers to the special variable
+ # that is local inside widget-function
+ +LPAR()+RPAR() {
+ # This anonymous nested function allows WIDGET
+ # to be used as a local variable. The -h
+ # removes the special status of the variable.
+ local -h WIDGET
+ }
+})
+
startitem()
vindex(BUFFER)
item(tt(BUFFER) (scalar))(
@@ -817,7 +862,10 @@ cursor remains between the new tt($LBUFFER) and the old tt($RBUFFER).
)
vindex(MARK)
item(tt(MARK) (integer))(
-Like tt(CURSOR), but for the mark.
+Like tt(CURSOR), but for the mark. With vi-mode operators that wait for
+a movement command to select a region of text, setting tt(MARK) allows
+the selection to extend in both directions from the the initial cursor
+position.
)
vindex(NUMERIC)
item(tt(NUMERIC) (integer))(
@@ -863,7 +911,9 @@ cursor remains between the old tt($LBUFFER) and the new tt($RBUFFER).
vindex(REGION_ACTIVE)
item(tt(REGION_ACTIVE) (integer))(
Indicates if the region is currently active. It can be assigned 0 or 1
-to deactivate and activate the region respectively;
+to deactivate and activate the region respectively. A value of 2
+activates the region in line-wise mode with the highlighted text
+extending for whole lines only;
ifzman(see em(Character Highlighting) below)\
ifnzman(noderef(Character Highlighting)).
)
@@ -1040,6 +1090,7 @@ menu(Modifying Text)
menu(Arguments)
menu(Completion)
menu(Miscellaneous)
+menu(Text Objects)
endmenu()
texinode(Movement)(History Control)()(Zle Widgets)
subsect(Movement)
@@ -1049,6 +1100,11 @@ item(tt(vi-backward-blank-word) (unbound) (B) (unbound))(
Move backward one word, where a word is defined as a series of
non-blank characters.
)
+tindex(vi-backward-blank-word-end)
+item(tt(vi-backward-blank-word-end) (unbound) (gE) (unbound))(
+Move to the end of the previous word, where a word is defined as a
+series of non-blank characters.
+)
tindex(backward-char)
item(tt(backward-char) (^B ESC-[D) (unbound) (unbound))(
Move backward one character.
@@ -1069,6 +1125,10 @@ tindex(vi-backward-word)
item(tt(vi-backward-word) (unbound) (b) (unbound))(
Move to the beginning of the previous word, vi-style.
)
+tindex(vi-backward-word-end)
+item(tt(vi-backward-word-end) (unbound) (ge) (unbound))(
+Move to the end of the previous word, vi-style.
+)
tindex(beginning-of-line)
item(tt(beginning-of-line) (^A) (unbound) (unbound))(
Move to the beginning of the line. If already at the beginning
@@ -1078,6 +1138,10 @@ tindex(vi-beginning-of-line)
item(tt(vi-beginning-of-line))(
Move to the beginning of the line, without changing lines.
)
+tindex(down-line)
+item(tt(down-line) (unbound) (unbound) (unbound))(
+Move down a line in the buffer.
+)
tindex(end-of-line)
item(tt(end-of-line) (^E) (unbound) (unbound))(
Move to the end of the line. If already at the end
@@ -1170,12 +1234,16 @@ tindex(vi-rev-repeat-find)
item(tt(vi-rev-repeat-find) (unbound) (,) (unbound))(
Repeat the last tt(vi-find) command in the opposite direction.
)
+tindex(up-line)
+item(tt(up-line) (unbound) (unbound) (unbound))(
+Move up a line in the buffer.
+)
enditem()
texinode(History Control)(Modifying Text)(Movement)(Zle Widgets)
subsect(History Control)
startitem()
tindex(beginning-of-buffer-or-history)
-item(tt(beginning-of-buffer-or-history) (ESC-<) (unbound) (unbound))(
+item(tt(beginning-of-buffer-or-history) (ESC-<) (gg) (unbound))(
Move to the beginning of the buffer, or if already there,
move to the first event in the history list.
)
@@ -1450,7 +1518,7 @@ reexamined. Note that negative numbers should be preceded by a
If two arguments are given, the second specifies the word on the command
line in normal array index notation (as a more natural alternative to the
-prefix argument). Hence 1 is the first word, and -1 (the default) is the
+numeric argument). Hence 1 is the first word, and -1 (the default) is the
last word.
If a third argument is given, its value is ignored, but it is used to
@@ -1565,6 +1633,13 @@ Read a movement command from the keyboard, and kill
from the cursor position to the endpoint of the movement.
Then enter insert mode.
If the command is tt(vi-change), change the current line.
+
+For compatibility with vi, if the command is tt(vi-forward-word)
+or tt(vi-forward-blank-word), the whitespace after the word is not
+included. If you prefer the more consistent behaviour with the
+whitespace included use the following key binding:
+
+example(bindkey -a -s cw dwi)
)
tindex(vi-change-eol)
item(tt(vi-change-eol) (unbound) (C) (unbound))(
@@ -1681,7 +1756,7 @@ item(tt(vi-open-line-below) (unbound) (o) (unbound))(
Open a line below the cursor and enter insert mode.
)
tindex(vi-oper-swap-case)
-item(tt(vi-oper-swap-case))(
+item(tt(vi-oper-swap-case) (unbound) (g~) (unbound))(
Read a movement command from the keyboard, and swap
the case of all characters
from the cursor position to the endpoint of the movement.
@@ -1704,6 +1779,13 @@ Insert the contents of the kill buffer after the cursor.
If the kill buffer contains a sequence of lines (as opposed to characters),
paste it below the current line.
)
+tindex(put-replace-selection)
+item(tt(put-replace-selection) (unbound) (unbound) (unbound))(
+Replace the contents of the current region or selection with the
+contents of the kill buffer. If the kill buffer contains a sequence of
+lines (as opposed to characters), the current line will be split by the
+pasted lines.
+)
tindex(quoted-insert)
item(tt(quoted-insert) (^V) (unbound) (unbound))(
Insert the next character typed into the buffer literally.
@@ -1786,7 +1868,7 @@ tindex(yank-pop)
item(tt(yank-pop) (ESC-y) (unbound) (unbound))(
Remove the text just yanked, rotate the kill-ring (the history of
previously killed text) and yank the new top. Only works following
-tt(yank) or tt(yank-pop).
+tt(yank), tt(vi-put-before), tt(vi-put-after) or tt(yank-pop).
)
tindex(vi-yank)
item(tt(vi-yank) (unbound) (y) (unbound))(
@@ -1833,14 +1915,14 @@ spaces; if instead it is followed by tt(-2), then tt(forward-char),
move backward two spaces.
Inside a widget function, if passed an argument, i.e. `tt(zle
-universal-argument) var(num)', the numerical argument will be set to
+universal-argument) var(num)', the numeric argument will be set to
var(num); this is equivalent to `tt(NUMERIC=)var(num)'.
)
tindex(argument-base)
item(tt(argument-base))(
Use the existing numeric argument as a numeric base, which must be in the
range 2 to 36 inclusive. Subsequent use of tt(digit-argument) and
-tt(universal-argument) will input a new prefix in the given base.
+tt(universal-argument) will input a new numeric argument in the given base.
The usual hexadecimal convention is used: the letter tt(a) or tt(A)
corresponds to 10, and so on. Arguments in bases requiring digits from 10
upwards are more conveniently input with tt(universal-argument), since
@@ -1929,7 +2011,7 @@ When a previous completion displayed a list below the prompt, this
widget can be used to move the prompt below the list.
)
enditem()
-texinode(Miscellaneous)()(Completion)(Zle Widgets)
+texinode(Miscellaneous)(Text Objects)(Completion)(Zle Widgets)
subsect(Miscellaneous)
startitem()
tindex(accept-and-hold)
@@ -1997,9 +2079,9 @@ Reads a key sequence, then prints the function bound to that sequence.
tindex(exchange-point-and-mark)
item(tt(exchange-point-and-mark) (^X^X) (unbound) (unbound))(
Exchange the cursor position (point) with the position of the mark.
-Unless a negative prefix argument is given, the region between
+Unless a negative numeric argument is given, the region between
point and mark is activated so that it can be highlighted.
-If a zero prefix argument is given, the region is activated but
+If a zero numeric argument is given, the region is activated but
point and mark are not swapped.
)
tindex(execute-named-cmd)
@@ -2169,7 +2251,8 @@ item(tt(send-break) (^G ESC-^G) (unbound) (unbound))(
Abort the current editor function, e.g. tt(execute-named-command), or the
editor itself, e.g. if you are in tt(vared). Otherwise abort the parsing of
the current line; in this case the aborted line is available in the shell
-variable tt(ZLE_LINE_ABORTED).
+variable tt(ZLE_LINE_ABORTED). If the editor is aborted from within
+tt(vared), the variable tt(ZLE_VARED_ABORTED) is set.
)
tindex(run-help)
item(tt(run-help) (ESC-H ESC-h) (unbound) (unbound))(
@@ -2180,19 +2263,29 @@ command. tt(run-help) is normally aliased to tt(man).
tindex(vi-set-buffer)
item(tt(vi-set-buffer) (unbound) (") (unbound))(
Specify a buffer to be used in the following command.
-There are 35 buffers that can be specified:
-the 26 `named' buffers tt("a) to tt("z)
-and the nine `queued' buffers tt("1) to tt("9). The named buffers can also
-be specified as tt("A) to tt("Z).
-
-When a buffer is specified for a cut command, the text being cut replaces
-the previous contents of the specified buffer. If a named buffer
-is specified using a capital, the newly cut text is appended to the buffer
-instead of overwriting it.
-
-If no buffer is specified for a cut command, tt("1) is used, and the
-contents of tt("1) to tt("8) are each shifted along one buffer; the contents of
-tt("9) is lost.
+There are 37 buffers that can be specified:
+the 26 `named' buffers tt("a) to tt("z), the `yank' buffer tt("0),
+the nine `queued' buffers tt("1) to tt("9) and the `black hole' buffer
+tt("_). The named buffers can also be specified as tt("A) to tt("Z).
+
+When a buffer is specified for a cut, change or yank command, the text
+concerned replaces the previous contents of the specified buffer. If
+a named buffer is specified using a capital, the newly cut text is
+appended to the buffer instead of overwriting it. When using the tt("_)
+buffer, nothing happens. This can be useful for deleting text without
+affecting the normal registers.
+
+If no buffer is specified for a cut or change command, tt("1) is used, and
+the contents of tt("1) to tt("8) are each shifted along one buffer;
+the contents of tt("9) is lost. If no buffer is specified for a yank
+command, tt("0") is used. Finally, a paste command without a specified
+buffer will paste the text from the most recent command regardless of any
+buffer that might have been used with that command.
+
+When called from a widget function by the tt(zle) command, the buffer
+can optionally be specified with an argument. For example,
+
+example(zle vi-set-buffer A)
)
tindex(vi-set-mark)
item(tt(vi-set-mark) (unbound) (m) (unbound))(
@@ -2201,7 +2294,7 @@ Set the specified mark at the cursor position.
tindex(set-mark-command)
item(tt(set-mark-command) (^@) (unbound) (unbound))(
Set the mark at the cursor position. If called with a negative
-prefix argument, do not set the mark but deactivate the region so that
+numeric argument, do not set the mark but deactivate the region so that
it is no longer highlighted (it is still usable for other purposes).
Otherwise the region is marked as active.
)
@@ -2222,7 +2315,7 @@ This command is executed when a key sequence that is not bound to any
command is typed. By default it beeps.
)
tindex(undo)
-item(tt(undo) (^_ ^Xu ^X^U) (unbound) (unbound))(
+item(tt(undo) (^_ ^Xu ^X^U) (u) (unbound))(
Incrementally undo the last text modification. When called from a
user-defined widget, takes an optional argument indicating a previous state
of the undo history as returned by the tt(UNDO_CHANGE_NO) variable;
@@ -2233,16 +2326,30 @@ insert mode is reverted, the changes having been merged when command mode was
selected.
)
tindex(redo)
-item(tt(redo))(
+item(tt(redo) (unbound) (^R) (unbound))(
Incrementally redo undone text modifications.
)
tindex(vi-undo-change)
-item(tt(vi-undo-change) (unbound) (u) (unbound))(
+item(tt(vi-undo-change) (unbound) (unbound) (unbound))(
Undo the last text modification.
If repeated, redo the modification.
)
+tindex(visual-mode)
+item(tt(visual-mode) (unbound) (v) (unbound))(
+Toggle vim-style visual selection mode. If line-wise visual mode is
+currently enabled then it is changed to being character-wise. If used
+following an operator, it forces the subsequent movement command to be
+treated as a character-wise movement.
+)
+tindex(visual-line-mode)
+item(tt(visual-line-mode) (unbound) (V) (unbound))(
+Toggle vim-style line-wise visual selection mode. If character-wise
+visual mode is currently enabled then it is changed to being line-wise. If used
+following an operator, it forces the subsequent movement command to be
+treated as a line-wise movement.
+)
tindex(what-cursor-position)
-item(tt(what-cursor-position) (^X=) (unbound) (unbound))(
+item(tt(what-cursor-position) (^X=) (ga) (unbound))(
Print the character under the cursor, its code as an octal, decimal and
hexadecimal number, the current cursor position within the buffer and the
column of the cursor in the current line.
@@ -2267,6 +2374,50 @@ If the last command executed was a digit as part of an argument,
continue the argument. Otherwise, execute vi-beginning-of-line.
)
enditem()
+texinode(Text Objects)()(Miscellaneous)(Zle Widgets)
+subsect(Text Objects)
+cindex(text objects)
+Text objects are commands that can be used to select a block of text
+according to some criteria. They are a feature of the vim text editor
+and so are primarily intended for use with vi operators or from visual
+selection mode. However, they can also be used from vi-insert or emacs
+mode. Key bindings listed below apply to the tt(viopp) and tt(visual)
+keymaps.
+
+startitem()
+tindex(select-a-blank-word)
+item(tt(select-a-blank-word) (aW))(
+Select a word including adjacent blanks, where a word is defined as a
+series of non-blank characters. With a numeric argument, multiple words
+will be selected.
+)
+tindex(select-a-shell-word)
+item(tt(select-a-shell-word) (aa))(
+Select the current command argument applying the normal rules for
+quoting.
+)
+tindex(select-a-word)
+item(tt(select-a-word) (aw))(
+Select a word including adjacent blanks, using the normal vi-style word
+definition. With a numeric argument, multiple words will be selected.
+)
+tindex(select-in-blank-word)
+item(tt(select-in-blank-word) (iW))(
+Select a word, where a word is defined as a series of non-blank
+characters. With a numeric argument, multiple words will be selected.
+)
+tindex(select-in-shell-word)
+item(tt(select-in-shell-word) (ia))(
+Select the current command argument applying the normal rules for
+quoting. If the argument begins and ends with matching quote characters,
+these are not included in the selection.
+)
+tindex(select-in-word)
+item(tt(select-in-word) (iw))(
+Select a word, using the normal vi-style word definition. With a numeric
+argument, multiple words will be selected.
+)
+enditem()
texinode(Character Highlighting)()(Zle Widgets)(Zsh Line Editor)
sect(Character Highlighting)
@@ -2301,8 +2452,8 @@ tt(set-mark-command). The region is only highlighted if it is active,
which is the case if tt(set-mark-command) or tt(exchange-point-and-mark)
has been called and the line has not been subsequently modified. The
region can be deactivated by calling tt(set-mark-command) with a
-negative prefix argument, or reactivated by calling
-tt(exchange-point-and-mark) with a zero prefix argument. Note
+negative numeric argument, or reactivated by calling
+tt(exchange-point-and-mark) with a zero numeric argument. Note
that whether or not the region is active has no effect on its
use within widgets, it simply determines whether it is highlighted.
)
diff --git a/Doc/zman.yo b/Doc/zman.yo
index 3329cb975..73cc186e0 100644
--- a/Doc/zman.yo
+++ b/Doc/zman.yo
@@ -32,6 +32,7 @@ COMMENT(--- emphasised text ---)
def(em)(1)(NOTRANS(\fI)ARG1+NOTRANS(\fP))
def(bf)(1)(NOTRANS(\fB)ARG1+NOTRANS(\fP))
def(tt)(1)(NOTRANS(\fB)ARG1+NOTRANS(\fP))
+def(uref)(1)(NOTRANS(\fB)ARG1+NOTRANS(\fP))
def(var)(1)(NOTRANS(\fI)ARG1+NOTRANS(\fP))
COMMENT(--- man page headers ---)
diff --git a/Doc/ztexi.yo b/Doc/ztexi.yo
index 636896117..699567724 100644
--- a/Doc/ztexi.yo
+++ b/Doc/ztexi.yo
@@ -38,6 +38,7 @@ COMMENT(--- emphasised text ---)
def(em)(1)(+NOTRANS(@emph{)ARG1+NOTRANS(}))
def(bf)(1)(+NOTRANS(@cite{)ARG1+NOTRANS(}))
def(tt)(1)(+NOTRANS(@t{)ARG1+NOTRANS(}))
+def(uref)(1)(+NOTRANS(@t{@uref{)ARG1+NOTRANS(}}))
def(var)(1)(+NOTRANS(@var{)ARG1+NOTRANS(}))
COMMENT(--- man page headers ---)
diff --git a/Etc/FAQ.yo b/Etc/FAQ.yo
index 08ea979ee..8702d2baa 100644
--- a/Etc/FAQ.yo
+++ b/Etc/FAQ.yo
@@ -47,7 +47,10 @@ def(startitem)(0)() \
def(enditem)(0)()\
def(item)(2)(
ARG1: ARG2)\
-def(nofill)(1)(ARG1)
+def(nofill)(1)(ARG1)\
+def(uref)(1)(ARG1)\
+def(LPAR)(0)(CHAR(40))\
+def(RPAR)(1)(CHAR(41))
myreport(Z-Shell Frequently-Asked Questions)(Peter Stephenson)(2010/02/15)
COMMENT(-- the following are for Usenet and must appear first)\
description(\
@@ -302,7 +305,7 @@ sect(On what machines will it run?)
sect(What's the latest version?)
- Zsh 5.0.7 is the latest production version. For details of all the
+ Zsh 5.0.8 is the latest production version. For details of all the
changes, see the NEWS file in the source distribution.
A beta of the next version is sometimes available. Development of zsh is
@@ -696,9 +699,9 @@ label(23)
cd() { builtin cd "$@"; print -D $PWD; }
)
(which converts your home directory to a tt(~)). In fact, this problem is
- better solved by defining the special function chpwd() (see the manual).
- Note also that the mytt(;) at the end of the function is optional in zsh,
- but not in ksh or sh (for sh's where it exists).
+ better solved by defining the special function chpwd+LPAR()RPAR() (see
+ the manual). Note also that the mytt(;) at the end of the function is
+ optional in zsh, but not in ksh or sh (for sh's where it exists).
Here is Bart Schaefer's guide to converting csh aliases for zsh.
@@ -1017,19 +1020,26 @@ sect(In which startup file do I put...?)
reason it is important for administrators to make sure tt(/etc/zshenv)
is as brief as possible.
- The order in which the four files are searched (none of them myem(need)
- to exist) is the one just given. However, tt(.zprofile) and tt(.zlogin)
- are only run when the shell is a login shell --- when you first login,
- of course, and whenever you start zsh with the tt(-l) option. All
- login shells are interactive. The order is the only difference
- between those; you should decide whether you need things set before or
- after tt(.zshrc). These files are a good place to set environment
- variables (i.e. mytt(export) commands), since they are passed on to
- all shells without you having to set them again, and also to check
- that your terminal is set up properly (except that if you want to
- change settings for terminal emulator windows like tt(xterm) you will
- need to put those in tt(.zshrc), since usually you do not get a login
- shell here).
+ The order in which the four files are searched (none of them
+ myem(need) to exist) is the one just given. However, tt(.zprofile)
+ and tt(.zlogin) are only run when the shell is a login shell --- when
+ you first login, of course, and whenever you start zsh with the tt(-l)
+ option. The order is the only difference between those; you should
+ decide whether you need things set before or after tt(.zshrc). These
+ files are a good place to set environment variables (i.e. mytt(export)
+ commands), since they are passed on to all shells without you having
+ to set them again, and also to check that your terminal is set up
+ properly (except that if you want to change settings for terminal
+ emulator windows like tt(xterm) you will need to put those in
+ tt(.zshrc), since usually you do not get a login shell here).
+
+ Login shells are often interactive, but this is not necessarily the
+ case. It is the programme that starts the shell that decides if it is
+ to be a login shell, and it is not required that the shell be run
+ interactively. A possible example is a display manager that starts a
+ shell to initialise your environment before running the window manager
+ to create terminals: it might run this as a login shell but with no
+ terminal, so it is not interactive.
The only file you can alter which is started with every zsh (unless
you use the tt(-f) option) is tt(.zshenv), so this is a good place to \
@@ -1756,7 +1766,7 @@ sect(Why is my output duplicated with `tt(foo 2>&1 >foo.out | bar)'?)
actually see is that the output is going both to the pipe and into the
file. To be more explicit, here's the same example with real commands:
verb(
- % { print output; print error >&2 } 2>&1 >foo.out | sed 's/error/erratic'
+ % { print output; print error >&2 } 2>&1 >foo.out | sed 's/error/erratic/'
erratic
output
% cat foo.out
@@ -1777,7 +1787,14 @@ sect(Why is my output duplicated with `tt(foo 2>&1 >foo.out | bar)'?)
to both files when the redirector appears twice. What's going on in the
first example is exactly the same, however the second redirector is
disguised as a pipe. So if you want to turn this effect off, you need
- to unset the option mytt(MULTIOS).
+ to unset the option mytt(MULTIOS), or alternatively write the following:
+ verb(
+ % { print output; print error >&2 } 2>&1 >&- >foo.out | sed 's/error/erratic/'
+ erratic
+ )
+ By closing stdout with tt(>&-), we're cancelling the previous redirections
+ (to the pipe) and start anew with tt(>foo.out) instead of adding it as a
+ redirection target to stdout.
sect(What are these `^' and `~' pattern characters, anyway?)
@@ -1863,7 +1880,7 @@ label(327)
mytt(something) mustn't contain tt(/) if the pattern is being used for
globbing.
- Likewise, mytt(abc(<->~<10-100>).txt) matches a file consisting of
+ Likewise, mytt(abc+LPAR()<->~<10-100>RPAR().txt) matches a file consisting of
tt(abc), then some digits, then tt(.txt), unless the digits happen to
match a number from 10 to 100 inclusive (remember the handy mytt(<->)
pattern for matching integers with optional limits to the range). So
diff --git a/Etc/zsh-development-guide b/Etc/zsh-development-guide
index 2ed75423b..7f5266bd9 100644
--- a/Etc/zsh-development-guide
+++ b/Etc/zsh-development-guide
@@ -60,12 +60,12 @@ Git Workflow
Zsh has migrated from CVS to git for version control. Thus far, we have
avoided further changes to our workflow.
-
+
* To allow changesets to be cross-referenced between the mailing list
archives and version control history, commit messages should start with
the mailing list sequence number. This number is generated by the list
server and inserted as an X-Seq: header field in the e-mail.
-
+
* An entry in the ChangeLog file should be added manually before pushing
a commit to the master repository. Don't create a separate change for
this: amend the existing commit in your local repository.
@@ -82,6 +82,7 @@ Micro Git Tutorial:
% $VISUAL file1.c file2.c new-file3.c
% git add new-file3.c
% git commit -a
+ % git pull --rebase
% git push
"git commit -a" automatically finds files which are tracked and have
@@ -89,6 +90,12 @@ Micro Git Tutorial:
the index to be part of the next commit, and can be used for new files
or for existing files (commit -a is a shortcut for the latter)
+"git pull --rebase" ensures your local branch is up to date, needed
+before pushing; the "--rebase" option means that any changes
+in files also modified by you are handled by replaying your changes
+onto the remote ones, which avoids any unnecessary merges in the
+resulting history.
+
"git push" assumes that you're on the master branch and the repository
was created by cloning it from some place, with default options.
diff --git a/Functions/Calendar/after b/Functions/Calendar/after
new file mode 100644
index 000000000..7fb0166f7
--- /dev/null
+++ b/Functions/Calendar/after
@@ -0,0 +1,67 @@
+# Glob qualifier function, e.g
+#
+# print *(e:after 2014/08/01:)
+# print *(e-after today:12:00-)
+#
+# If named before:
+# Match files modified before a given time.
+#
+# If named after:
+# Match files modified after a given time. Use as glob qualifier.
+# N.B.: "after" actually includes the given time as it is to second
+# precision (it would be inconvenient to exclude the first second of a date).
+# It should therefore more logically be called "from", but that's a less
+# obvious name.
+#
+# File to test is in $REPLY.
+#
+# Similar to age, but only takes at most one data, which is
+# compared directly with the current time.
+
+emulate -L zsh
+
+zmodload -F zsh/stat b:zstat
+zmodload -i zsh/parameter
+
+autoload -Uz calendar_scandate
+
+local timefmt
+local -a vals tmp
+
+[[ -e $REPLY ]] || return 1
+zstat -A vals +mtime -- $REPLY || return 1
+
+if (( $# == 1 )); then
+ if [[ $1 = :* ]]; then
+ timefmt="%Y/%m/%d:%H:%M:%S"
+ zstat -A tmp -F $timefmt +mtime -- ${1#:} || return 1
+ local AGEREF=$tmp[1]
+ else
+ local AGEREF=$1
+ fi
+fi
+
+integer mtime=$vals[1] date1 date2
+local REPLY REPLY2
+
+# allow a time only (meaning today)
+if calendar_scandate -t $AGEREF; then
+ date1=$REPLY
+
+ case $0 in
+ (after)
+ (( mtime >= date1 ))
+ ;;
+
+ (before)
+ (( mtime < date1 ))
+ ;;
+
+ (*)
+ print "$0: must be named 'after' or 'before'" >&2
+ return 1
+ ;;
+ esac
+else
+ return 1
+fi
diff --git a/Functions/Calendar/before b/Functions/Calendar/before
new file mode 100644
index 000000000..7fb0166f7
--- /dev/null
+++ b/Functions/Calendar/before
@@ -0,0 +1,67 @@
+# Glob qualifier function, e.g
+#
+# print *(e:after 2014/08/01:)
+# print *(e-after today:12:00-)
+#
+# If named before:
+# Match files modified before a given time.
+#
+# If named after:
+# Match files modified after a given time. Use as glob qualifier.
+# N.B.: "after" actually includes the given time as it is to second
+# precision (it would be inconvenient to exclude the first second of a date).
+# It should therefore more logically be called "from", but that's a less
+# obvious name.
+#
+# File to test is in $REPLY.
+#
+# Similar to age, but only takes at most one data, which is
+# compared directly with the current time.
+
+emulate -L zsh
+
+zmodload -F zsh/stat b:zstat
+zmodload -i zsh/parameter
+
+autoload -Uz calendar_scandate
+
+local timefmt
+local -a vals tmp
+
+[[ -e $REPLY ]] || return 1
+zstat -A vals +mtime -- $REPLY || return 1
+
+if (( $# == 1 )); then
+ if [[ $1 = :* ]]; then
+ timefmt="%Y/%m/%d:%H:%M:%S"
+ zstat -A tmp -F $timefmt +mtime -- ${1#:} || return 1
+ local AGEREF=$tmp[1]
+ else
+ local AGEREF=$1
+ fi
+fi
+
+integer mtime=$vals[1] date1 date2
+local REPLY REPLY2
+
+# allow a time only (meaning today)
+if calendar_scandate -t $AGEREF; then
+ date1=$REPLY
+
+ case $0 in
+ (after)
+ (( mtime >= date1 ))
+ ;;
+
+ (before)
+ (( mtime < date1 ))
+ ;;
+
+ (*)
+ print "$0: must be named 'after' or 'before'" >&2
+ return 1
+ ;;
+ esac
+else
+ return 1
+fi
diff --git a/Functions/Calendar/calendar b/Functions/Calendar/calendar
index 00f59981c..aff39b369 100644
--- a/Functions/Calendar/calendar
+++ b/Functions/Calendar/calendar
@@ -12,6 +12,7 @@ local -A reply
zmodload -i zsh/datetime || return 1
zmodload -i zsh/zutil || return 1
+zmodload -F zsh/files b:zf_ln || return 1
autoload -Uz calendar_{add,parse,read,scandate,show,lockfiles}
@@ -254,8 +255,7 @@ if (( verbose )); then
fi
local mycmds="${TMPPREFIX:-/tmp/zsh}.calendar_cmds.$$"
-touch $mycmds
-chmod 600 $mycmds
+zf_ln -fn =(<<<'') $mycmds || return 1
# start of subshell for OS file locking
(
diff --git a/Functions/Misc/run-help-ip b/Functions/Misc/run-help-ip
new file mode 100644
index 000000000..3f15b01fb
--- /dev/null
+++ b/Functions/Misc/run-help-ip
@@ -0,0 +1,42 @@
+#! zsh -f
+#
+# Install this function by placing it in your FPATH and then
+# adding to your .zshrc the line if you use run-help function:
+# autoload -Uz run-help-ip
+
+if [ $# -eq 0 ]; then
+ man ip
+ return
+fi
+
+if ! man -w ip-address >/dev/null 2>&1; then
+ man ip
+ return
+fi
+
+while [[ $# != 0 && $1 == -* ]]; do
+ shift
+done
+
+case $1 in
+ (addr*) man ip-address ;;
+ (addrlabel) man ip-addrlabel ;;
+ (l2*) man ip-l2tp ;;
+ (li*) man ip-link ;;
+ (ma*) man ip-maddress ;;
+ (mo*) man ip-monitor ;;
+ (mr*) man ip-mroute ;;
+ (nei*) man ip-neighbour ;;
+ (netc*) man ip-netconf ;;
+ (netn*) man ip-netns ;;
+ (nt*) man ip-ntable ;;
+ (ro*) man ip-route ;;
+ (ru*) man ip-rule ;;
+ (tcp*) man ip-tcp_metrics ;;
+ (to*) man ip-token ;;
+ (tu*) man ip-tunnel ;;
+ (xf*) man ip-xfrm ;;
+ (*) man ip ;;
+esac
+
+return $?
diff --git a/Functions/Misc/tetriscurses b/Functions/Misc/tetriscurses
new file mode 100644
index 000000000..371456082
--- /dev/null
+++ b/Functions/Misc/tetriscurses
@@ -0,0 +1,386 @@
+# I noticed we don't ship any contrib and/or example scripts using the
+# zcurses module, and also that the builtin tetris is sort of boring, so
+# I figured I'd port it to curses. It works pretty well, but I noticed
+# two problems with the zcurses module in the process:
+#
+# 1. the HAVE_USE_DEFAULT_COLORS define seems to never be defined?
+#
+# 2a. resizing the window causes 'zcurses input' to wait forever for a
+# key, even with a timeout defined.
+#
+# Bart says:
+# >This probably has something to do with the special-casing around wgetch()
+# >for signals handled by the "trap" command. See the big comment in
+# >Src/Modules/curses.c lines 1073-1103.
+#
+# >It may be problematic to mix curses with the generic signal handling in
+# >the main shell. We may need to swap in a SIGWINCH handler wrapper while
+# >the curses UI is active, and restore the main handler when leaving it.
+#
+# 2b. resizing the window doesn't cause an event while running the
+# program, but if i resize before starting(?) i get an event RESIZE on
+# my first input call.
+#
+# Bart says:
+# >There's probably some state that needs to be cleared on entry to
+# >zccmd_input() so that curses doesn't see something left over from the
+# >previous signal. Unfortunately I don't know what that would be.
+
+if (( $LINES < 22 || $COLUMNS < 46 )); then
+ echo >&2 'terminal needs to be at least 22 lines and 46 columns'
+ return
+fi
+
+emulate -L zsh
+
+typeset -a tetris_shapes
+tetris_shapes=(
+ 0x0f00 0x4444 0x0f00 0x4444
+ 0x4e00 0x4c40 0x0e40 0x4640
+ 0x6600 0x6600 0x6600 0x6600
+ 0x4620 0x6c00 0x4620 0x6c00
+ 0x2640 0x6300 0x2640 0x6300
+ 0x6440 0x8e00 0x44c0 0x0e20
+ 0xc440 0x0e80 0x4460 0x2e00
+)
+typeset -A tetris_rotations
+tetris_rotations=(
+ 0x0f00 0x4444 0x4444 0x0f00
+ 0x4e00 0x4c40 0x4c40 0x0e40 0x0e40 0x4640 0x4640 0x4e00
+ 0x6600 0x6600
+ 0x4620 0x6c00 0x6c00 0x4620
+ 0x2640 0x6300 0x6300 0x2640
+ 0x6440 0x8e00 0x8e00 0x44c0 0x44c0 0x0e20 0x0e20 0x6440
+ 0xc440 0x0e80 0x0e80 0x4460 0x4460 0x2e00 0x2e00 0xc440
+)
+local tetris_vsz=20 tetris_hsz=11
+local tetris_blankline=${(l:11:: :)}
+local tetris_blankboard=${(j::):-${(l:11:: :)}${(s: :)^${(l:20:: :)}}}
+
+local tetris_board=$tetris_blankboard
+local tetris_score=0
+local tetris_lines=0
+
+local tetris_{block{,_next,_x,_y},i}
+
+function __tetris-next-block {
+ tetris_block_next=$tetris_shapes[1+RANDOM%$#tetris_shapes]
+}
+
+function __tetris-new-block {
+ tetris_block=$tetris_block_next
+ __tetris-next-block
+ __tetris-draw-next-block
+ tetris_block_y=0
+ tetris_block_x=4
+ if ! __tetris-block-fits; then
+ __tetris-game-over
+ fi
+ __tetris-place-block "*"
+}
+
+function __tetris-left {
+ __tetris-place-block " "
+ (( tetris_block_x-- ))
+ __tetris-block-fits || (( tetris_block_x++ ))
+ __tetris-place-block "*"
+}
+
+function __tetris-right {
+ __tetris-place-block " "
+ (( tetris_block_x++ ))
+ __tetris-block-fits || (( tetris_block_x-- ))
+ __tetris-place-block "*"
+}
+
+function __tetris-rotate {
+ __tetris-place-block " "
+ local save_block=$tetris_block
+ tetris_block=$tetris_rotations[$tetris_block]
+ __tetris-block-fits || tetris_block=$save_block
+ __tetris-place-block "*"
+}
+
+function __tetris-drop {
+ __tetris-place-block " "
+ ((tetris_block_y++))
+ while __tetris-block-fits; do
+ ((tetris_block_y++))
+ ((tetris_score+=2))
+ done
+ ((tetris_block_y--))
+ __tetris-block-dropped
+}
+
+function __tetris-timeout {
+ __tetris-place-block " "
+ ((tetris_block_y++))
+ if __tetris-block-fits; then
+ __tetris-place-block "*"
+ return
+ fi
+ ((tetris_block_y--))
+ __tetris-block-dropped
+}
+
+function __tetris-block-dropped {
+ integer bonus=1
+ __tetris-place-block "O"
+ local fl=${tetris_blankline// /O} i=$((tetris_block_y*tetris_hsz))
+ repeat 4; do
+ if [[ $tetris_board[i+1,i+tetris_hsz] == $fl ]]; then
+ if (( fancygraphics )); then for char in {7..1}; do
+ tetris_board[i+1,i+tetris_hsz]=${tetris_blankline// /$char}
+ __tetris-render-screen
+ zcurses timeout score 50
+ zcurses input score
+ done; fi
+ tetris_board[i+1,i+tetris_hsz]=
+ tetris_board=$tetris_blankline$tetris_board
+ ((tetris_score+=100*(bonus++*(tetris_lines/10+10))))
+ ((tetris_lines+=1))
+ if ((tetris_lines % 10 == 0)); then
+ ((timestep = timestep * 0.80))
+ fi
+ fi
+ ((i += tetris_hsz))
+ done
+ __tetris-new-block
+}
+
+function __tetris-block-fits {
+ local y x i=$((1+tetris_block_y*tetris_hsz+tetris_block_x)) b=0x8000
+ for ((y=0; y!=4; y++)); do
+ for ((x=0; x!=4; x++)); do
+ if ((tetris_block&b)); then
+ ((x+tetris_block_x >= 0)) || return 1
+ ((x+tetris_block_x < tetris_hsz)) || return 1
+ ((y+tetris_block_y >= 0)) || return 1
+ ((y+tetris_block_y < tetris_vsz)) || return 1
+ [[ $tetris_board[i] == " " ]] || return 1
+ fi
+ ((b >>= 1))
+ ((i++))
+ done
+ ((i+=tetris_hsz-4))
+ done
+ return 0
+}
+
+function __tetris-draw-next-block {
+ local tetris_preview
+ local y x i=1 b=0x8000
+ for ((y=0; y!=4; y++)); do
+ tetris_preview=" "
+ for ((x=0; x!=4; x++)); do
+ ((tetris_block_next&b)) && tetris_preview[i]=\*
+ ((b >>= 1))
+ ((i++))
+ done
+ i=1
+ zcurses move preview $((y+1)) 1
+ zcurses string preview ${${${tetris_preview//O/$filled_block}//\*/$active_block}// / }
+ done
+}
+
+function __tetris-place-block {
+ local y x i=$((1+tetris_block_y*tetris_hsz+tetris_block_x)) b=0x8000
+ for ((y=0; y!=4; y++)); do
+ for ((x=0; x!=4; x++)); do
+ ((tetris_block&b)) && tetris_board[i]=$1
+ ((b >>= 1))
+ ((i++))
+ done
+ ((i+=tetris_hsz-4))
+ done
+}
+
+function __tetris-render-screen {
+ local i x piece
+ setopt localoptions histsubstpattern extendedglob
+ local -a match mbegin mend
+ local -A animation
+ animation=( 7 ▇▇ 6 ▆▆ 5 ▅▅ 4 ▄▄ 3 ▃▃ 2 ▂▂ 1 ▁▁ )
+ for (( i = 0; i < tetris_vsz; i++ )); do
+ zcurses move gamearea $(( i + 1 )) 1
+ zcurses string gamearea ${${${${${tetris_board[1+i*tetris_hsz,(i+1)*tetris_hsz]}//O/$filled_block}//\*/$active_block}// / }//(#b)([1-7])/$animation[$match[1]]}
+ done
+
+ zcurses clear score
+ zcurses move score 1 1
+ zcurses string score "Score: $tetris_score"$'\
+'" Lines: $tetris_lines"$'\
+'" Speed: ${timestep%.*} ms"
+
+ zcurses border gamearea
+ zcurses border score
+ zcurses border preview
+ zcurses refresh gamearea score preview $debug
+}
+
+function __tetris-game-over {
+ gameover=1
+}
+
+function __tetris-new-game {
+ gameover=0
+ timestep=1000
+ tetris_score=0
+ tetris_lines=0
+ __tetris-next-block
+ __tetris-new-block
+ __tetris-render-screen
+}
+
+function __tetris-game-over-screen {
+ __tetris-debug "Died with $tetris_score points!"
+ tetris_board=$tetris_blankboard
+ local text="You got $tetris_score points!"
+ local gameover_height=4 gameover_width=$(( $#text + 2 ))
+ zcurses addwin gameover $gameover_height $gameover_width \
+ $(( off_y + (game_height-gameover_height)/2 )) \
+ $(( off_x + (game_width+score_width-gameover_width)/2 ))
+ zcurses move gameover 1 1
+ zcurses string gameover $text
+ text='Play again? [yn]'
+ zcurses move gameover 2 $(( (gameover_width - $#text)/2 ))
+ zcurses string gameover $text
+ zcurses border gameover
+ keepplaying=
+ until [[ $keepplaying = [ynq] ]]; do
+ zcurses input gameover keepplaying
+ done
+ zcurses delwin gameover
+ zcurses refresh stdscr
+ zcurses timeout gamearea ${timestep%.*}
+ __tetris-new-game
+}
+
+function __tetris-debug {
+ if [[ -z $debug ]]; then
+ return
+ fi
+ zcurses scroll debug -1
+ zcurses move debug 0 0
+ zcurses string debug "$1"
+}
+
+function __tetris-remove-wins {
+ local delwin
+ local -a delwins
+ delwins=(gamearea score debug gameover help preview)
+ for delwin in ${delwins:*zcurses_windows}; do
+ zcurses delwin $delwin
+ done
+}
+
+function __tetris-help {
+ local i
+ local help_height=9 help_width=23
+ zcurses addwin help $help_height $help_width \
+ $(( off_y + (game_height - help_height) / 2 )) \
+ $(( off_x + (game_width + score_width - help_width) / 2 ))
+ zcurses move help 1 1
+ zcurses string help $'left: h, j, left\
+ right: right, n, l\
+ rotate: up, c, i\
+ soft drop: down, t, k\
+ hard drop: space\
+ quit: q\
+ press space to return'
+ zcurses border help
+ until [[ $i == [\ q] ]]; do
+ zcurses input help i
+ if [[ $i == q ]]; then
+ keepplaying=n
+ fi
+ done
+ zcurses delwin help
+ zcurses refresh stdscr
+}
+
+zmodload zsh/curses && {
+ zcurses init
+ __tetris-remove-wins
+ zcurses refresh
+ echoti civis
+ local debug=
+ if (( ${@[(I)--debug|-d]} )); then
+ debug=debug
+ fi
+ local off_x off_y
+ local game_height=22 game_width=25
+ local score_height=5 score_width=20
+ local preview_height=6 preview_width=10
+ local filled_block active_block
+ local fancygraphics
+ if zmodload zsh/langinfo && [[ $langinfo[CODESET] = UTF-8 ]]; then
+ filled_block=██
+ active_block=▒▒
+ fancygraphics=${@[(I)--silly]}
+ else
+ filled_block='[]'
+ active_block='()'
+ fancygraphics=0
+ fi
+ off_x=$(( (COLUMNS-game_width-score_width-1) / 2 ))
+ off_y=$(( (LINES-game_height) / 2 ))
+ zcurses clear stdscr redraw
+ zcurses refresh stdscr
+ zcurses addwin gamearea $game_height $game_width $off_y $off_x
+ zcurses scroll gamearea off
+ zcurses addwin score $score_height $score_width \
+ $off_y $(( off_x + game_width + 1 ))
+ zcurses scroll score off
+ zcurses addwin preview $preview_height $preview_width \
+ $(( off_y + score_height )) $(( off_x + game_width + 1 ))
+ zcurses scroll preview off
+ if [[ -n $debug ]]; then
+ zcurses addwin debug $(( game_height - score_height - preview_height - 1 )) \
+ $score_width \
+ $(( off_y + score_height + preview_height ))\
+ $(( off_x + game_width + 1 ))
+ fi
+ typeset -F SECONDS
+ local now prev timestep timeout key kkey keepplaying=y gameover=0
+ prev=$SECONDS
+ __tetris-new-game
+ zcurses timeout gamearea 0
+ while [[ $keepplaying == y ]]; do
+ if zcurses input gamearea key kkey; then
+ __tetris-debug "got input $key$kkey"
+ case $key$kkey in
+ LEFT|h|j) __tetris-left;;
+ RIGHT|n|l) __tetris-right;;
+ UP|c|i) __tetris-rotate;;
+ DOWN|t|k) __tetris-timeout; ((tetris_score++)); prev=$SECONDS;;
+ " ") __tetris-drop;;
+ q) break;;
+ F1|H) __tetris-help;;
+ esac
+ else
+ __tetris-debug "timed out"
+ __tetris-timeout
+ fi
+ now=$SECONDS
+ if (( prev + timestep/1000. < now )); then
+ (( prev += timestep/1000. ))
+ fi
+ timeout=${$(( 1000.*(prev + timestep/1000. - now) + 1 ))%.*}
+ if (( timeout < 0 )); then
+ __tetris-debug "BUG: timeout < 0"
+ timeout=${timestep%.*}
+ fi
+ zcurses timeout gamearea $timeout
+ __tetris-debug "timeout: $timeout"
+
+ __tetris-render-screen
+ if [[ $gameover == 1 ]]; then
+ __tetris-game-over-screen
+ fi
+ done
+} always {
+ __tetris-remove-wins
+ echoti cnorm
+ zcurses end
+}
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
index ee50be6ca..c348da2a7 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_git
@@ -195,14 +195,6 @@ fi
VCS_INFO_adjust
VCS_INFO_git_getaction ${gitdir}
-
-VCS_INFO_get_get_rebase()
-{
- if [[ -f "$1" ]]; then
- echo "$(< "$1")"
- fi
-}
-
local patchdir=${gitdir}/patches/${gitbranch}
if [[ -d $patchdir ]] && [[ -f $patchdir/applied ]] \
&& [[ -f $patchdir/unapplied ]]
@@ -213,6 +205,7 @@ then
elif [[ -d "${gitdir}/rebase-merge" ]]; then
patchdir="${gitdir}/rebase-merge"
local p
+ [[ -f "${patchdir}/done" ]] &&
for p in ${(f)"$(< "${patchdir}/done")"}; do
# remove action
git_patches_applied+=("${${(s: :)p}[2,-1]}")
@@ -223,11 +216,16 @@ elif [[ -d "${gitdir}/rebase-apply" ]]; then
# Fake patch names for all but current patch
patchdir="${gitdir}/rebase-apply"
local cur=$(< "${patchdir}/next")
- local p
+ local p subject
for p in $(seq $(($cur - 1))); do
git_patches_applied+=("$(printf "%04d" $p) ?")
done
- git_patches_applied+=("$(< "${patchdir}/original-commit") ${${(f)$(< "${patchdir}/msg-clean")}[1]}")
+ subject="${$(< "${patchdir}/msg-clean")[(f)1]}"
+ if [[ -f "${patchdir}/original-commit" ]]; then
+ git_patches_applied+=("$(< ${patchdir}/original-commit) $subject")
+ else
+ git_patches_applied+=("? $subject")
+ fi
git_patches_unapplied=($(seq $cur $(< "${patchdir}/last")))
VCS_INFO_git_handle_patches
diff --git a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
index cedaf5676..1274ca337 100644
--- a/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
+++ b/Functions/VCS_Info/Backends/VCS_INFO_get_data_hg
@@ -6,6 +6,7 @@
setopt localoptions extendedglob NO_shwordsplit
local hgbase bmfile branchfile rebasefile dirstatefile mqseriesfile \
+ curbmfile curbm \
mqstatusfile mqguardsfile patchdir mergedir \
r_csetid r_lrev r_branch i_bmhash i_bmname \
revformat branchformat hgactionstring hgchanges \
@@ -24,6 +25,7 @@ r_lrev='' # local revision
patchdir="${hgbase}/.hg/patches"
mergedir="${hgbase}/.hg/merge/"
bmfile="${hgbase}/.hg/bookmarks"
+curbmfile="${hgbase}/.hg/bookmarks.current"
branchfile="${hgbase}/.hg/branch"
rebasefile="${hgbase}/.hg/rebasestate"
dirstatefile="${hgbase}/.hg/dirstate"
@@ -125,8 +127,23 @@ if zstyle -t ":vcs_info:${vcs}:${usercontext}:${rrn}" get-bookmarks \
[[ $i_bmhash == $r_csetid* ]] && hgbmarks+=( $i_bmname )
done < ${bmfile}
+ if [[ -r "$curbmfile" ]] ; then
+ curbm=$(<"${curbmfile}")
+ hook_com[hg-active-bookmark]=$curbm
+ else
+ # leave curbm empty and [hg-active-bookmark] undefined.
+ fi
+
if VCS_INFO_hook 'gen-hg-bookmark-string' "${hgbmarks[@]}"; then
+ # If there is an active bookmark, annotate it and put it first.
+ if [[ -n $curbm ]] ; then
+ hgbmarks[(i)$curbm]=()
+ hgbmarks[1,0]="${curbm}*"
+ fi
hgbmstring=${(j:, :)hgbmarks}
+ # Deannotate the array, in case later code expects it to be valid.
+ # (The order is not restored.)
+ [[ -n $curbm ]] && hgbmarks[1]=${${hgbmarks[1]}[1,-2]}
else
hgbmstring=${hook_com[hg-bookmark-string]}
fi
diff --git a/Functions/VCS_Info/VCS_INFO_quilt b/Functions/VCS_Info/VCS_INFO_quilt
index db15dda74..34ff1edbf 100644
--- a/Functions/VCS_Info/VCS_INFO_quilt
+++ b/Functions/VCS_Info/VCS_INFO_quilt
@@ -87,7 +87,7 @@ function VCS_INFO_quilt() {
local patches pc tmp qstring root
local -i ret
local -x context
- local -a applied unapplied all applied_string unapplied_string quiltcommand
+ local -a applied unapplied all applied_string unapplied_string quiltcommand quilt_env
local -Ax hook_com
context=":vcs_info:${vcs}.quilt-${mode}:${usercontext}:${rrn}"
@@ -105,17 +105,6 @@ function VCS_INFO_quilt() {
;;
esac
- zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}"
- if [[ "${patches}" != /* ]]; then
- tmp=${patches:-patches}
- patches="$(VCS_INFO_quilt-dirfind "${tmp}")"
- ret=$?
- (( ret )) && return ${ret}
- patches=${patches}/${tmp}
- else
- [[ -d ${patches} ]] || return 1
- fi
-
pc="$(VCS_INFO_quilt-dirfind .pc .version)"
ret=$?
if (( ret == 0 )); then
@@ -129,12 +118,27 @@ function VCS_INFO_quilt() {
else
applied=()
fi
+ patches=$(<$pc/.quilt_patches)
fi
if zstyle -t "${context}" get-unapplied; then
# This zstyle call needs to be moved further up if `quilt' needs
# to be run in more places than this one.
zstyle -s "${context}" quiltcommand quiltcommand || quiltcommand='quilt'
- unapplied=( ${(f)"$(QUILT_PATCHES=$patches $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} )
+ quilt_env=(env)
+ if [ -z "$patches" ]; then
+ zstyle -s "${context}" quilt-patch-dir patches || patches="${QUILT_PATCHES}"
+ if [[ "${patches}" != /* ]]; then
+ tmp=${patches:-patches}
+ patches="$(VCS_INFO_quilt-dirfind "${tmp}")"
+ ret=$?
+ (( ret )) && return ${ret}
+ patches=${patches}/${tmp}
+ else
+ [[ -d ${patches} ]] || return 1
+ fi
+ quilt_env+=(QUILT_PATCHES="$patches")
+ fi
+ unapplied=( ${(f)"$(${quilt_env[@]} $quiltcommand --quiltrc /dev/null unapplied 2> /dev/null)"} )
unapplied=( ${unapplied:#} )
else
unapplied=()
diff --git a/Functions/VCS_Info/vcs_info b/Functions/VCS_Info/vcs_info
index 5a421dfed..46938691d 100644
--- a/Functions/VCS_Info/vcs_info
+++ b/Functions/VCS_Info/vcs_info
@@ -94,6 +94,7 @@ vcs_info () {
for pat in ${dps} ; do
if [[ ${PWD} == ${~pat} ]] ; then
+ VCS_INFO_maxexports
[[ -n ${vcs_info_msg_0_} ]] && VCS_INFO_set --nvcs
return 0
fi
diff --git a/Functions/Zftp/zfcd_match b/Functions/Zftp/zfcd_match
index 95de4c583..9159f496c 100644
--- a/Functions/Zftp/zfcd_match
+++ b/Functions/Zftp/zfcd_match
@@ -12,7 +12,6 @@ fi
local ZFTP_VERBOSE=45
# should we redirect 2>/dev/null or let the user see it?
-local tmpf=${TMPPREFIX}zfcm$$
local -a match mbegin mend
if [[ $ZFTP_SYSTEM = UNIX* ]]; then
@@ -27,9 +26,10 @@ if [[ $ZFTP_SYSTEM = UNIX* ]]; then
# If we're using -F, we get away with using a directory
# to list, but not a glob. Don't ask me why.
reply=(${${(M)${(f)"$(zftp ls -lF $dir)"}:#d*}/(#b)*[[:space:]](*)\//$match[1]})
-# zftp ls -LF $dir >$tmpf
-# reply=($(awk '/\/$/ { print substr($1, 1, length($1)-1) }' $tmpf))
-# rm -f $tmpf
+# () {
+# zftp ls -LF $dir >|$1
+# reply=($(awk '/\/$/ { print substr($1, 1, length($1)-1) }' $1))
+# } =(<<<'')
[[ -n $dir && $dir != */ ]] && dir="$dir/"
if [[ -n $WIDGET ]]; then
_wanted directories expl 'remote directory' \
diff --git a/Functions/Zftp/zfcget b/Functions/Zftp/zfcget
index 476a730a6..569ee9de1 100644
--- a/Functions/Zftp/zfcget
+++ b/Functions/Zftp/zfcget
@@ -14,7 +14,7 @@ emulate -L zsh
[[ $curcontext = :zf* ]] || local curcontext=:zfcget
local loc rem stat=0 opt opt_G opt_t remlist locst remst
-local tmpfile=${TMPPREFIX}zfcget$$ rstat tsize
+local rstat tsize
while getopts :Gt opt; do
[[ $opt = '?' ]] && print "zfcget: bad option: -$OPTARG" && return 1
@@ -39,10 +39,11 @@ for remlist in $*; do
else
# Compare the sizes.
locst=($(zftp local $loc))
- zftp remote $rem >$tmpfile
- rstat=$?
- remst=($(<$tmpfile))
- rm -f $tmpfile
+ () {
+ zftp remote $rem >|$1
+ rstat=$?
+ remst=($(<$1))
+ } =(<<<'temporary file')
if [[ $rstat = 2 ]]; then
print "Server does not support SIZE command.\n" \
"Assuming you know what you're doing..." 2>&1
diff --git a/Functions/Zftp/zfcput b/Functions/Zftp/zfcput
index 85141b68d..eafecde78 100644
--- a/Functions/Zftp/zfcput
+++ b/Functions/Zftp/zfcput
@@ -14,7 +14,6 @@ emulate -L zsh
[[ $curcontext = :zf* ]] || local curcontext=:zfcput
local loc rem stat=0 locst remst offs tailtype
-local tmpfile=${TMPPREFIX}zfcget$$ rstat
# find how tail works. this is intensely annoying, since it's completely
# standard in C. od's no use, since we can only skip whole blocks.
@@ -40,10 +39,11 @@ for loc in $*; do
else
# Compare the sizes.
locst=($(zftp local $loc))
- zftp remote $rem >$tmpfile
- rstat=$?
- remst=($(<$tmpfile))
- rm -f $tmpfile
+ () {
+ zftp remote $rem >|$1
+ rstat=$?
+ remst=($(<$1))
+ } =(<<<'temporary file')
if [[ $rstat = 2 ]]; then
print "Server does not support remote status commands.\n" \
"You will have to find out the size by hand and use zftp append." 2>&1
diff --git a/Functions/Zftp/zffcache b/Functions/Zftp/zffcache
index 48afdcba0..b609c2104 100644
--- a/Functions/Zftp/zffcache
+++ b/Functions/Zftp/zffcache
@@ -19,8 +19,5 @@ fi
if [[ $1 = -d ]]; then
unset $fcache_name
elif (( ${(P)#fcache_name} == 0 )); then
- local tmpf=${TMPPREFIX}zffcache$$
- zftp ls >$tmpf
- eval "$fcache_name=(\${(f)\"\$(<\$tmpf)\"})"
- rm -f $tmpf
+ eval "$fcache_name=(\${(f)\"\$(zftp ls)\"})"
fi
diff --git a/Functions/Zftp/zfget_match b/Functions/Zftp/zfget_match
index 1d90bea60..3a33c9886 100644
--- a/Functions/Zftp/zfget_match
+++ b/Functions/Zftp/zfget_match
@@ -1,28 +1,29 @@
# function zfget_match {
emulate -L zsh
+zmodload -F zsh/files b:zf_ln || return 1
# the zfcd hack: this may not be necessary here
if [[ $1 == $HOME || $1 == $HOME/* ]]; then
1="~${1#$HOME}"
fi
-local tmpf=${TMPPREFIX}zfgm$$
-
if [[ $ZFTP_SYSTEM == UNIX* && $1 == */* ]]; then
+ setopt localoptions clobber
+ local tmpf=${TMPPREFIX}zfgm$$
+ zf_ln -fn =(<<<'') $tmpf || return 1
+
if [[ -n $WIDGET ]]; then
local dir=${1:h}
[[ $dir = */ ]] || dir="$dir/"
zftp ls -LF $dir >$tmpf
local reply
reply=(${${${(f)"$(<$tmpf)"}##$dir}%\*})
- rm -f $tmpf
_wanted files expl 'remote file' compadd -P $dir - $reply
else
# On the first argument to ls, we usually get away with a glob.
zftp ls "$1*$2" >$tmpf
reply=($(<$tmpf))
- rm -f $tmpf
fi
else
local fcache_name
diff --git a/Functions/Zftp/zfrglob b/Functions/Zftp/zfrglob
index 1fb8d761a..677b85f4b 100644
--- a/Functions/Zftp/zfrglob
+++ b/Functions/Zftp/zfrglob
@@ -33,12 +33,12 @@ if [[ $pat != *[][*?]* &&
( -n $zfrglob || $pat != *[(|)#^]* ) ]]; then
return 0
fi
-local tmpf=${TMPPREFIX}zfrglob$$
if [[ $zfrglob != '' ]]; then
- zftp ls "$pat" >$tmpf 2>/dev/null
- eval "$1=(\$(<\$tmpf))"
- rm -f $tmpf
+ () {
+ zftp ls "$pat" >|$1 2>/dev/null
+ eval "$1=(\$(<\$1))"
+ } =(<<<'temporary file')
else
if [[ $ZFTP_SYSTEM = UNIX* && $pat = */* ]]; then
# not the current directory and we know how to handle paths
@@ -49,10 +49,11 @@ else
dir=/
fi
nondir=${pat##*/}
- zftp ls "$dir" 2>/dev/null >$tmpf
- files=($(<$tmpf))
+ () {
+ zftp ls "$dir" 2>/dev/null >|$1
+ files=($(<$1))
+ } =(<<<'temporary file')
files=(${files:t})
- rm -f $tmpf
else
# we just have to do an ls and hope that's right
local fcache_name
diff --git a/Functions/Zftp/zftransfer b/Functions/Zftp/zftransfer
index c70bf7248..c97ae4645 100644
--- a/Functions/Zftp/zftransfer
+++ b/Functions/Zftp/zftransfer
@@ -43,10 +43,11 @@ zfautocheck || return 1
local style
zstyle -s ':zftp:zftransfer' progress style
if [[ -n $style && $style != none ]]; then
- local ZFTP_TSIZE array tmpfile=${TMPPREFIX}zft$$
- zftp remote $file1 >$tmpfile 2>/dev/null
- array=($(<$tmpfile))
- rm -f $tmpfile
+ local ZFTP_TSIZE array
+ () {
+ zftp remote $file1 >|$1 2>/dev/null
+ array=($(<$1))
+ } =(<<<'temporary file')
[[ $#array -eq 2 ]] && ZFTP_TSIZE=$array[1]
fi
diff --git a/Functions/Zftp/zftype b/Functions/Zftp/zftype
index 0cdf7e2aa..81f95dece 100644
--- a/Functions/Zftp/zftype
+++ b/Functions/Zftp/zftype
@@ -1,13 +1,11 @@
# function zftype {
-local type zftmp=${TMPPREFIX}zftype$$
+local type
[[ $curcontext = :zf* ]] || local curcontext=:zftype
zfautocheck -d
if (( $# == 0 )); then
- zftp type >$zftmp
- type=$(<$zftmp)
- rm -f $zftmp
+ type=$(zftp type)
if [[ $type = I ]]; then
print "Current type is image (binary)"
return 0
diff --git a/Functions/Zftp/zfuget b/Functions/Zftp/zfuget
index c1033c930..2850975e7 100644
--- a/Functions/Zftp/zfuget
+++ b/Functions/Zftp/zfuget
@@ -26,7 +26,7 @@
emulate -L zsh
[[ $curcontext = :zf* ]] || local curcontext=:zfuget
-local loc rem locstats remstats doit tmpfile=${TMPPREFIX}zfuget$$
+local loc rem locstats remstats doit
local rstat remlist opt opt_v opt_s opt_G opt_t
integer stat do_close
@@ -66,12 +66,13 @@ for remlist in $*; do
doit=y
remstats=()
if [[ -f $loc ]]; then
- zftp local $loc >$tmpfile
- locstats=($(<$tmpfile))
- zftp remote $rem >$tmpfile
- rstat=$?
- remstats=($(<$tmpfile))
- rm -f $tmpfile
+ () {
+ zftp local $loc >|$1
+ locstats=($(<$1))
+ zftp remote $rem >|$1
+ rstat=$?
+ remstats=($(<$1))
+ } =(<<<'temporary file')
if [[ $rstat = 2 ]]; then
print "Server does not implement full command set required." 1>&2
return 1
diff --git a/Functions/Zftp/zfuput b/Functions/Zftp/zfuput
index 4e0e42dcd..f4e6a0fd6 100644
--- a/Functions/Zftp/zfuput
+++ b/Functions/Zftp/zfuput
@@ -12,7 +12,7 @@
emulate -L zsh
[[ $curcontext = :zf* ]] || local curcontext=:zfuput
-local loc rem locstats remstats doit tmpfile=${TMPPREFIX}zfuput$$
+local loc rem locstats remstats doit
local rstat opt opt_v opt_s
integer stat do_close
@@ -52,12 +52,13 @@ for rem in $*; do
stat=1
continue
fi
- zftp local $loc >$tmpfile
- locstats=($(<$tmpfile))
- zftp remote $rem >$tmpfile
- rstat=$?
- remstats=($(<$tmpfile))
- rm -f $tmpfile
+ () {
+ zftp local $loc >|$1
+ locstats=($(<$1))
+ zftp remote $rem >|$1
+ rstat=$?
+ remstats=($(<$1))
+ } =(<<<'temporary file')
if [[ $rstat = 2 ]]; then
print "Server does not implement full command set required." 1>&2
return 1
diff --git a/Functions/Zle/edit-command-line b/Functions/Zle/edit-command-line
index 250cac65f..100af9601 100644
--- a/Functions/Zle/edit-command-line
+++ b/Functions/Zle/edit-command-line
@@ -6,12 +6,10 @@
# will give ksh-like behaviour for that key,
# except that it will handle multi-line buffers properly.
-local tmpfile=${TMPPREFIX:-/tmp/zsh}ecl$$
+() {
+ exec </dev/tty
+ ${=${VISUAL:-${EDITOR:-vi}}} $1
+ print -Rz - "$(<$1)"
+} =(<<<"$PREBUFFER$BUFFER")
-print -R - "$PREBUFFER$BUFFER" >$tmpfile
-exec </dev/tty
-${=${VISUAL:-${EDITOR:-vi}}} $tmpfile
-print -Rz - "$(<$tmpfile)"
-
-command rm -f $tmpfile
zle send-break # Force reload from the buffer stack
diff --git a/NEWS b/NEWS
index bf8969b26..86b0bd40c 100644
--- a/NEWS
+++ b/NEWS
@@ -4,8 +4,35 @@ CHANGES FROM PREVIOUS VERSIONS OF ZSH
Note also the list of incompatibilities in the README file.
-Changes since 5.0.0
--------------------
+Changes from 5.0.7 to 5.0.8
+---------------------------
+
+- Global aliases can be created for syntactic tokens such as command
+ separators (";", "&", "|", "&&", "||"), redirection operators, etc.
+ Use at your own risk! The POSIX_ALIASES option is interpreted more
+ strictly to prevent expansion of these and other alias names containing
+ quotes, glob metacharacters, parameter references, etc.
+
+- There have been various further improvements to builtin handling
+ with the POSIX_BUILTINS option (off by default) for compatibility with
+ the POSIX standard.
+
+- 'whence -v' is now more informative, and 'whence -S' shows you
+ how a full chain of symbolic links resolves to a command.
+
+- The 'p' parameter flag now allows an argument to be specified
+ as a reference to a variable, e.g. ${(ps.$sep.)foo} to split $foo
+ on a string given by $sep.
+
+- Elements of the watch variable may now be patterns.
+
+- The logic for retrying history locking has been improved.
+
+- Some rationalisations have been made to the zsh/db/gdbm module that
+ should make it more useful and predictable in operation.
+
+Changes from 5.0.0 to 5.0.7
+---------------------------
- Numeric constants encountered in mathematical expressions (but not other
contexts) can contain underscores as separators that will be ignored on
@@ -14,69 +41,72 @@ Changes since 5.0.0
in output, e.g.
setopt cbases
zmodload zsh/mathfunc
- print $(( [#16_4] 2**32 - 1 )) $(( [#_3] 4 * atan(1.0) ))
-
+ print $(( [#16_4] 2**32 - 1 )) $(( [#_3] 4 * atan(1.0) ))
+
- "functions -T" turns on tracing for the specified function(s) only,
similar to "functions -t" except that tracing is turned off for any
functions called from the specified one(s) that don't also have the -t
or -T flag.
-
+
- The option FORCE_FLOAT has been added to force all arithmetic constants
to be treated as floating point. This is most useful locally within
functions or scripts performing floating point calculations.
-
-- The default $fpath/$FPATH is now designed always to include
- /usr/local/share/zsh/site-functions. This directory does not need to
+
+- The default $fpath/$FPATH is now designed to include
+ /usr/local/share/zsh/site-functions unless the installer has
+ specifically decided to use another path, i.e. regardless of
+ the standard installation location. This directory does not need to
exist. Sites that set an explicit site directory can put that in
/etc/zshenv as before. The intention of the new path element is to
increase the likelihood that locally added functions can be found with
- the shell running "out of the box", no matter how the shell was
- configured.
+ the shell running "out of the box", unless the shell has been
+ deliberately configured differently by the installer for some special
+ purpose.
- Individual pattern characters can be disabled. For example, to allow '^'
to be an ordinary character even if the option EXTENDED_GLOB is set, use
"disable -p '^'".
-
+
- The variable editing builtin vared can be given custom editing widgets
for initialisation and finishing.
-
+
- The line editor's capability for listening on file descriptors
additional to the terminal has been enhanced so that the handler for
such file descriptors can be a line editor widget. Previously the
handler always behaved as a standard shell function.
-
+
- Hooks for adding history (the function zshaddhistory and the
array zshaddhistory_functions) can return status 2 to indicate that
history is to be saved internally within the shell but not written.
-
+
- In file completion, the recursive-files style can be set to an array of
patterns to match against "$PWD/". In any matched location, it is
possible to complete files in arbitrarily deep subdirectories without
needing to type the directory prefix. See example in the zshcompsys
manual.
-
+
- The _user_expand completer now allows expansion functions in the
user-expand files to return a string in REPLY that will be used to name
the set of expansions returned.
-
+
- The parameter HISTORY_IGNORE may be set to a pattern which matches
lines in the internal history that are to be omitted from the history
file at file write time. This differs from history changes made in
the zshaddhistory hook or by the HIST_IGNORE_* options, all of which
take effect immediately on the internal history list itself.
-
+
- The parameter ZLE_RPROMPT_INDENT can be set to 0 to remove the space
before the right hand side of the screen (this causes problems with
some terminals). It is not special and is not set by default; the
effect in that case is as if it was 1, as in previous versions.
-
+
- If the option EXTENDED_GLOB is in effect, it is possible to force
globbing within conditional code using the [[ ... ]] syntax by flagging
that a certain string is a glob using the (#q) glob qualifier syntax.
The resulting glob is treated as a single argument. For example,
[[ -n *.c(#qN) ]] tests whether there are any .c files in the current
directory.
-
+
- In prompt strings, the %N(l.true.false) conditional (line length) and
the %N<..< and %N>..> truncation operators now accept negative values
of N, which count the remaining space to the opposite margin (positive
@@ -627,7 +657,7 @@ Further enhancements to new completion system:
different styles
- Many more supplied completions for standard commands which work out of
the box, and better handling of command line options/arguments which
- behave in the usual way
+ behave in the usual way
- $fpath now set up to use installed functions by default; functions
can be loaded just by `autoload -U compinit; compinit'
- Much improved handling of nested quoting and nested braces
@@ -985,7 +1015,7 @@ The shell will drop privileges when this option is unset by resetting its
euid to uid and its egid to gid.
The =number substitution for accessing the directory stack is changed to
-~number to allow =command substitution when a command name begins with a
+~number to allow =command substitution when a command name begins with a
digit.
<> is a redirection operator which opens the standard input for both
diff --git a/README b/README
index e3ccc70b1..142daadf1 100644
--- a/README
+++ b/README
@@ -5,16 +5,11 @@ THE Z SHELL (ZSH)
Version
-------
-This is version 5.0.7 of the shell. This is a stable release.
-There are minor new features as well as bug fixes since 5.0.6.
-
-Note in particular there is a security fix to disallow evaluation of the
-initial values of integer variables imported from the environment (they
-are instead treated as literal numbers). That could allow local
-privilege escalation, under some specific and atypical conditions where
-zsh is being invoked in privilege elevation contexts when the
-environment has not been properly sanitized, such as when zsh is invoked
-by sudo on systems where "env_reset" has been disabled.
+This is version 5.0.8 of the shell. This is a stable release.
+There are no significant new features since 5.0.7, but there
+are many bugfixes and some significant internal improvements, notably
+a more predictable effect for keyboard interrupts and proper parsing
+of $(...) expressions.
Installing Zsh
--------------
@@ -35,6 +30,93 @@ Zsh is a shell with lots of features. For a list of some of these, see the
file FEATURES, and for the latest changes see NEWS. For more
details, see the documentation.
+Incompatibilites between 5.0.7 and 5.0.8
+----------------------------------------
+
+Various arithmetic operations have changed, in particular with respect
+to the choice of integer or floating point operations. The new
+behaviour is intended to be more consistent, but is not compatible with
+the old.
+
+1) Previously, the modulus operation, `%', implicitly converted the
+operation to integer and output an integer result, even if one
+or both of the arguments were floating point. Now, the C math
+library fmod() operator is used to implement the operation where
+one of the arguments is floating point. For example:
+
+Old behavour:
+
+% print $(( 5.5 % 2 ))
+1
+
+New behaviour:
+
+% print $(( 5.5 % 2 ))
+1.5
+
+
+2) Previously, assignments to variables assigned the correct type to
+variables declared as floating point or integer, but this type was
+not propagated to the value of the expression, as a C programmer
+would naturally expect. Now, the type of the variable is propagated
+so long as the variable is declared as a numeric type (however this
+happened, e.g. the variable may have been implicitly typed by a
+previous assignment). For example:
+
+Old behaviour:
+
+% integer var
+% print $(( var = 5.5 / 2.0 ))
+2.75
+% print $var
+2
+
+New behaviour:
+
+% integer var
+% print $(( var = 5.5 / 2.0 ))
+2
+% print $var
+2
+
+
+3) Previously, the FORCE_FLOAT option only forced the use of floating
+point in arithmetic expressions for integer constants, i.e. numbers
+typed directly into the expression, but not for variables. Hence
+an operation involving only integer variables (or string variables
+containing integers) was not forced to be performed with floating point
+arithmetic. Now, operations involving variables are also forced to
+floating point. For example:
+
+Old behaviour:
+
+% unsetopt FORCE_FLOAT
+% print $(( 1 / 2 ))
+0
+% integer i=1 j=2
+% print $(( i / j ))
+0
+% setopt FORCE_FLOAT
+% print $(( 1 / 2 ))
+0.5
+% print $(( i / j ))
+0
+
+New behaviour:
+
+% unsetopt FORCE_FLOAT
+% print $(( 1 / 2 ))
+0
+% integer i=1 j=2
+% print $(( i / j ))
+0
+% setopt FORCE_FLOAT
+% print $(( 1 / 2 ))
+0.5
+% print $(( i / j ))
+0.5
+
+
Incompatibilities between 5.0.2 and 5.0.5
-----------------------------------------
diff --git a/Src/Builtins/rlimits.c b/Src/Builtins/rlimits.c
index 9da31831d..85ec1811c 100644
--- a/Src/Builtins/rlimits.c
+++ b/Src/Builtins/rlimits.c
@@ -518,7 +518,7 @@ do_limit(char *nam, int lim, rlim_t val, int hard, int soft, int set)
}
} else
limits[lim].rlim_cur = val;
- if (set && zsetlimit(lim, "limit"))
+ if (set && zsetlimit(lim, nam))
return 1;
}
}
diff --git a/Src/Builtins/sched.c b/Src/Builtins/sched.c
index c1cc98354..bcf7661f4 100644
--- a/Src/Builtins/sched.c
+++ b/Src/Builtins/sched.c
@@ -346,7 +346,7 @@ schedgetfn(UNUSED(Param pm))
for (i = 0, sch = schedcmds; sch; sch = sch->next, i++)
;
- aptr = ret = zhalloc(sizeof(char **) * (i+1));
+ aptr = ret = zhalloc(sizeof(char *) * (i+1));
for (sch = schedcmds; sch; sch = sch->next, aptr++) {
char tbuf[40], *flagstr;
time_t t;
diff --git a/Src/Modules/attr.c b/Src/Modules/attr.c
index 6e08b10c5..78c1104a9 100644
--- a/Src/Modules/attr.c
+++ b/Src/Modules/attr.c
@@ -98,36 +98,33 @@ static int
bin_getattr(char *nam, char **argv, Options ops, UNUSED(int func))
{
int ret = 0;
- int list_len, val_len = 0, attr_len = 0, slen;
+ int val_len = 0, attr_len = 0, slen;
char *value, *file = argv[0], *attr = argv[1], *param = argv[2];
int symlink = OPT_ISSET(ops, 'h');
unmetafy(file, &slen);
unmetafy(attr, NULL);
- list_len = xlistxattr(file, NULL, 0, symlink);
- if (list_len > 0) {
- val_len = xgetxattr(file, attr, NULL, 0, symlink);
- if (val_len == 0) {
+ val_len = xgetxattr(file, attr, NULL, 0, symlink);
+ if (val_len == 0) {
+ if (param)
+ unsetparam(param);
+ return 0;
+ }
+ if (val_len > 0) {
+ value = (char *)zalloc(val_len+1);
+ attr_len = xgetxattr(file, attr, value, val_len, symlink);
+ if (attr_len > 0 && attr_len <= val_len) {
+ value[attr_len] = '\0';
if (param)
- unsetparam(param);
- return 0;
- }
- if (val_len > 0) {
- value = (char *)zalloc(val_len+1);
- attr_len = xgetxattr(file, attr, value, val_len, symlink);
- if (attr_len > 0 && attr_len <= val_len) {
- value[attr_len] = '\0';
- if (param)
- setsparam(param, metafy(value, attr_len, META_DUP));
- else
- printf("%s\n", value);
- }
- zfree(value, val_len+1);
+ setsparam(param, metafy(value, attr_len, META_DUP));
+ else
+ printf("%s\n", value);
}
+ zfree(value, val_len+1);
}
- if (list_len < 0 || val_len < 0 || attr_len < 0 || attr_len > val_len) {
+ if (val_len < 0 || attr_len < 0 || attr_len > val_len) {
zwarnnam(nam, "%s: %e", metafy(file, slen, META_NOALLOC), errno);
- ret = 1 + (attr_len > val_len || attr_len < 0);
+ ret = 1 + ((val_len > 0 && attr_len > val_len) || attr_len < 0);
}
return ret;
}
@@ -189,24 +186,20 @@ bin_listattr(char *nam, char **argv, Options ops, UNUSED(int func))
if (list_len > 0 && list_len <= val_len) {
char *p = value;
if (param) {
- if (strlen(value) + 1 == list_len)
- setsparam(param, metafy(value, list_len-1, META_DUP));
- else {
- int arrlen = 0;
- char **array = NULL, **arrptr = NULL;
+ int arrlen = 0;
+ char **array = NULL, **arrptr = NULL;
- while (p < &value[list_len]) {
- arrlen++;
- p += strlen(p) + 1;
- }
- arrptr = array = (char **)zshcalloc((arrlen+1) * sizeof(char *));
- p = value;
- while (p < &value[list_len]) {
- *arrptr++ = metafy(p, -1, META_DUP);
- p += strlen(p) + 1;
- }
- setaparam(param, array);
+ while (p < &value[list_len]) {
+ arrlen++;
+ p += strlen(p) + 1;
+ }
+ arrptr = array = (char **)zshcalloc((arrlen+1) * sizeof(char *));
+ p = value;
+ while (p < &value[list_len]) {
+ *arrptr++ = metafy(p, -1, META_DUP);
+ p += strlen(p) + 1;
}
+ setaparam(param, array);
} else while (p < &value[list_len]) {
printf("%s\n", p);
p += strlen(p) + 1;
diff --git a/Src/Modules/datetime.c b/Src/Modules/datetime.c
index 00ebd2b49..63a04dc89 100644
--- a/Src/Modules/datetime.c
+++ b/Src/Modules/datetime.c
@@ -94,7 +94,7 @@ reverse_strftime(char *nam, char **argv, char *scalar, int quiet)
}
static int
-bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
+output_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
{
int bufsize, x;
char *endptr = NULL, *scalar = NULL, *buffer;
@@ -145,6 +145,25 @@ bin_strftime(char *nam, char **argv, Options ops, UNUSED(int func))
return 0;
}
+static int
+bin_strftime(char *nam, char **argv, Options ops, int func)
+{
+ int result = 1;
+ char *tz = getsparam("TZ");
+
+ startparamscope();
+ if (tz && *tz) {
+ Param pm = createparam("TZ", PM_LOCAL|PM_SCALAR|PM_EXPORTED);
+ if (pm)
+ pm->level = locallevel; /* because createparam() doesn't */
+ setsparam("TZ", ztrdup(tz));
+ }
+ result = output_strftime(nam, argv, ops, func);
+ endparamscope();
+
+ return result;
+}
+
static zlong
getcurrentsecs(UNUSED(Param pm))
{
diff --git a/Src/Modules/db_gdbm.c b/Src/Modules/db_gdbm.c
index 9a2a7a5b9..76d4751bf 100644
--- a/Src/Modules/db_gdbm.c
+++ b/Src/Modules/db_gdbm.c
@@ -39,16 +39,17 @@
#include <gdbm.h>
-#if 0 /* what is this for? */
static char *backtype = "db/gdbm";
-#endif
static const struct gsu_scalar gdbm_gsu =
{ gdbmgetfn, gdbmsetfn, gdbmunsetfn };
+/**/
+static const struct gsu_hash gdbm_hash_gsu =
+{ hashgetfn, gdbmhashsetfn, gdbmhashunsetfn };
static struct builtin bintab[] = {
- BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:", NULL),
- BUILTIN("zuntie", 0, bin_zuntie, 1, -1, 0, NULL, NULL),
+ BUILTIN("ztie", 0, bin_ztie, 1, -1, 0, "d:f:r", NULL),
+ BUILTIN("zuntie", 0, bin_zuntie, 1, -1, 0, "u", NULL),
};
/**/
@@ -57,36 +58,67 @@ bin_ztie(char *nam, char **args, Options ops, UNUSED(int func))
{
char *resource_name, *pmname;
GDBM_FILE dbf = NULL;
+ int read_write = GDBM_SYNC, pmflags = PM_REMOVABLE;
Param tied_param;
if(!OPT_ISSET(ops,'d')) {
- zwarnnam(nam, "you must pass `-d db/gdbm' to ztie", NULL);
+ zwarnnam(nam, "you must pass `-d %s'", backtype);
return 1;
}
if(!OPT_ISSET(ops,'f')) {
- zwarnnam(nam, "you must pass `-f' with a filename to ztie", NULL);
+ zwarnnam(nam, "you must pass `-f' with a filename", NULL);
return 1;
}
+ if (OPT_ISSET(ops,'r')) {
+ read_write |= GDBM_READER;
+ pmflags |= PM_READONLY;
+ } else {
+ read_write |= GDBM_WRCREAT;
+ }
/* Here should be a lookup of the backend type against
* a registry.
*/
-
- pmname = ztrdup(*args);
+ if (strcmp(OPT_ARG(ops, 'd'), backtype) != 0) {
+ zwarnnam(nam, "unsupported backend type `%s'", OPT_ARG(ops, 'd'));
+ return 1;
+ }
resource_name = OPT_ARG(ops, 'f');
+ pmname = *args;
+
+ if ((tied_param = (Param)paramtab->getnode(paramtab, pmname)) &&
+ !(tied_param->node.flags & PM_UNSET)) {
+ /*
+ * Unset any existing parameter. Note there's no implicit
+ * "local" here, but if the existing parameter is local
+ * that will be reflected in the new one.
+ *
+ * We need to do this before attempting to open the DB
+ * in case this variable is already tied to a DB.
+ *
+ * This can fail if the variable is readonly or restricted.
+ * We could call unsetparam() and check errflag instead
+ * of the return status.
+ */
+ if (unsetparam_pm(tied_param, 0, 1))
+ return 1;
+ }
- if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys, 0))) {
- zwarnnam(nam, "cannot create the requested parameter name", NULL);
+ dbf = gdbm_open(resource_name, 0, read_write, 0666, 0);
+ if(!dbf) {
+ zwarnnam(nam, "error opening database file %s", resource_name);
return 1;
}
- dbf = gdbm_open(resource_name, 0, GDBM_WRCREAT | GDBM_SYNC, 0666, 0);
- if(!dbf) {
- zwarnnam(nam, "error opening database file %s", resource_name);
+ if (!(tied_param = createspecialhash(pmname, &getgdbmnode, &scangdbmkeys,
+ pmflags))) {
+ zwarnnam(nam, "cannot create the requested parameter %s", pmname);
+ gdbm_close(dbf);
return 1;
}
+ tied_param->gsu.h = &gdbm_hash_gsu;
tied_param->u.hash->tmpdata = (void *)dbf;
return 0;
@@ -97,20 +129,33 @@ static int
bin_zuntie(char *nam, char **args, Options ops, UNUSED(int func))
{
Param pm;
- GDBM_FILE dbf;
-
- pm = (Param) paramtab->getnode(paramtab, args[0]);
- if(!pm) {
- zwarnnam(nam, "cannot untie %s", args[0]);
- return 1;
+ char *pmname;
+ int ret = 0;
+
+ for (pmname = *args; *args++; pmname = *args) {
+ pm = (Param) paramtab->getnode(paramtab, pmname);
+ if(!pm) {
+ zwarnnam(nam, "cannot untie %s", pmname);
+ ret = 1;
+ continue;
+ }
+ if (pm->gsu.h != &gdbm_hash_gsu) {
+ zwarnnam(nam, "not a tied gdbm hash: %s", pmname);
+ ret = 1;
+ continue;
+ }
+
+ queue_signals();
+ if (OPT_ISSET(ops,'u'))
+ gdbmuntie(pm); /* clear read-only-ness */
+ if (unsetparam_pm(pm, 0, 1)) {
+ /* assume already reported */
+ ret = 1;
+ }
+ unqueue_signals();
}
- dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
- gdbm_close(dbf);
-/* free(pm->u.hash->tmpdata); */
- paramtab->removenode(paramtab, pm->node.nam);
-
- return 0;
+ return ret;
}
/**/
@@ -153,7 +198,7 @@ gdbmsetfn(Param pm, char *val)
/**/
static void
-gdbmunsetfn(Param pm, int um)
+gdbmunsetfn(Param pm, UNUSED(int um))
{
datum key;
GDBM_FILE dbf;
@@ -191,9 +236,7 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags)
{
Param pm = NULL;
datum key, content;
- GDBM_FILE dbf;
-
- dbf = (GDBM_FILE)(ht->tmpdata);
+ GDBM_FILE dbf = (GDBM_FILE)(ht->tmpdata);
pm = (Param) hcalloc(sizeof(struct param));
@@ -216,6 +259,89 @@ scangdbmkeys(HashTable ht, ScanFunc func, int flags)
}
+/**/
+static void
+gdbmhashsetfn(Param pm, HashTable ht)
+{
+ int i;
+ HashNode hn;
+ GDBM_FILE dbf;
+ datum key, content;
+
+ if (!pm->u.hash || pm->u.hash == ht)
+ return;
+
+ if (!(dbf = (GDBM_FILE)(pm->u.hash->tmpdata)))
+ return;
+
+ key = gdbm_firstkey(dbf);
+ while (key.dptr) {
+ queue_signals();
+ (void)gdbm_delete(dbf, key);
+ free(key.dptr);
+ unqueue_signals();
+ key = gdbm_firstkey(dbf);
+ }
+
+ /* just deleted everything, clean up */
+ (void)gdbm_reorganize(dbf);
+
+ if (!ht)
+ return;
+
+ for (i = 0; i < ht->hsize; i++)
+ for (hn = ht->nodes[i]; hn; hn = hn->next) {
+ struct value v;
+
+ v.isarr = v.flags = v.start = 0;
+ v.end = -1;
+ v.arr = NULL;
+ v.pm = (Param) hn;
+
+ key.dptr = v.pm->node.nam;
+ key.dsize = strlen(key.dptr) + 1;
+
+ queue_signals();
+
+ content.dptr = getstrvalue(&v);
+ content.dsize = strlen(content.dptr) + 1;
+
+ (void)gdbm_store(dbf, key, content, GDBM_REPLACE);
+
+ unqueue_signals();
+ }
+}
+
+/**/
+static void
+gdbmuntie(Param pm)
+{
+ GDBM_FILE dbf = (GDBM_FILE)(pm->u.hash->tmpdata);
+ HashTable ht = pm->u.hash;
+
+ if (dbf) /* paranoia */
+ gdbm_close(dbf);
+
+ ht->tmpdata = NULL;
+
+ /* for completeness ... createspecialhash() should have an inverse */
+ ht->getnode = ht->getnode2 = gethashnode2;
+ ht->scantab = NULL;
+
+ pm->node.flags &= ~(PM_SPECIAL|PM_READONLY);
+ pm->gsu.h = &stdhash_gsu;
+}
+
+/**/
+static void
+gdbmhashunsetfn(Param pm, UNUSED(int exp))
+{
+ gdbmuntie(pm);
+ /* hash table is now normal, so proceed normally... */
+ pm->gsu.h->setfn(pm, NULL);
+ pm->node.flags |= PM_UNSET;
+}
+
#else
# error no gdbm
#endif /* have gdbm */
diff --git a/Src/Modules/langinfo.c b/Src/Modules/langinfo.c
index f10fdfef5..eb45d161b 100644
--- a/Src/Modules/langinfo.c
+++ b/Src/Modules/langinfo.c
@@ -395,7 +395,8 @@ liitem(const char *name)
static HashNode
getlanginfo(UNUSED(HashTable ht), const char *name)
{
- int len, *elem;
+ int len;
+ nl_item *elem;
char *listr, *nameu;
Param pm = NULL;
diff --git a/Src/Modules/tcp.c b/Src/Modules/tcp.c
index 3f92050ae..0d9522047 100644
--- a/Src/Modules/tcp.c
+++ b/Src/Modules/tcp.c
@@ -623,6 +623,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
zthost = zsh_getipnodebyname(desthost, AF_INET, 0, &herrno);
if (!zthost || errflag) {
zwarnnam(nam, "host resolution failure: %s", desthost);
+ zsfree(desthost);
return 1;
}
@@ -630,6 +631,7 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
if (!sess) {
zwarnnam(nam, "unable to allocate a TCP session slot");
+ zsfree(desthost);
return 1;
}
@@ -665,6 +667,8 @@ bin_ztcp(char *nam, char **args, Options ops, UNUSED(int func))
sess->fd = redup(sess->fd, targetfd);
if (sess->fd < 0) {
zerrnam(nam, "could not duplicate socket fd to %d: %e", targetfd, errno);
+ zsfree(desthost);
+ tcp_close(sess);
return 1;
}
}
diff --git a/Src/Modules/zftp.c b/Src/Modules/zftp.c
index d16e2f618..09d4bd703 100644
--- a/Src/Modules/zftp.c
+++ b/Src/Modules/zftp.c
@@ -50,7 +50,6 @@ struct zftp_session;
typedef struct zftp_session *Zftp_session;
#include "tcp.h"
-#include "tcp.mdh"
#include "zftp.mdh"
#include "zftp.pro"
diff --git a/Src/Modules/zpty.c b/Src/Modules/zpty.c
index d119658c3..7b6130c6f 100644
--- a/Src/Modules/zpty.c
+++ b/Src/Modules/zpty.c
@@ -189,7 +189,11 @@ get_pty(int master, int *retfd)
#endif
if (master) {
+#ifdef HAVE_POSIX_OPENPT
+ if ((mfd = posix_openpt(O_RDWR|O_NOCTTY)) < 0)
+#else
if ((mfd = open("/dev/ptmx", O_RDWR|O_NOCTTY)) < 0)
+#endif
return 1;
if (grantpt(mfd) || unlockpt(mfd) || !(name = ptsname(mfd))) {
@@ -304,7 +308,7 @@ newptycmd(char *nam, char *pname, char **args, int echo, int nblock)
prog = parse_string(zjoin(args, ' ', 1), 0);
if (!prog) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
scriptname = oscriptname;
ineval = oineval;
return 1;
diff --git a/Src/Modules/zselect.c b/Src/Modules/zselect.c
index c02074646..30a3f51a5 100644
--- a/Src/Modules/zselect.c
+++ b/Src/Modules/zselect.c
@@ -251,7 +251,7 @@ bin_zselect(char *nam, char **args, UNUSED(Options ops), UNUSED(int func))
outptr = outdata = (char **)zalloc((fdcount+1)*sizeof(char *));
while (nonempty(fdlist))
*outptr++ = getlinknode(fdlist);
- *outptr = '\0';
+ *outptr = NULL;
/* and store in array parameter */
if (outhash)
sethparam(outhash, outdata);
diff --git a/Src/Modules/zutil.c b/Src/Modules/zutil.c
index 1cca0c4b8..c89495070 100644
--- a/Src/Modules/zutil.c
+++ b/Src/Modules/zutil.c
@@ -301,7 +301,8 @@ setstypat(Style s, char *pat, Patprog prog, char **vals, int eval)
int ef = errflag;
eprog = parse_string(zjoin(vals, ' ', 1), 0);
- errflag = ef;
+ /* Keep any user interrupt error status */
+ errflag = ef | (errflag & ERRFLAG_INT);
if (!eprog)
{
@@ -394,10 +395,11 @@ evalstyle(Stypat p)
unsetparam("reply");
execode(p->eval, 1, 0, "style");
if (errflag) {
- errflag = ef;
+ /* Keep any user interrupt error status */
+ errflag = ef | (errflag & ERRFLAG_INT);
return NULL;
}
- errflag = ef;
+ errflag = ef | (errflag & ERRFLAG_INT);
queue_signals();
if ((ret = getaparam("reply")))
diff --git a/Src/Zle/compcore.c b/Src/Zle/compcore.c
index 35d410cc6..000f9da2a 100644
--- a/Src/Zle/compcore.c
+++ b/Src/Zle/compcore.c
@@ -1524,7 +1524,7 @@ set_comp_sep(void)
ol = zlemetaline;
addedx = 1;
noerrs = 1;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
/*
* tl is the length of the temporary string including
@@ -1671,9 +1671,9 @@ set_comp_sep(void)
noaliases = ona;
strinend();
inpop();
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
noerrs = ne;
- lexrestore();
+ zcontext_restore();
wb = owb;
we = owe;
zlemetaline = ol;
@@ -3492,7 +3492,7 @@ freematch(Cmatch m, int nbeg, int nend)
if (m->brsl)
zfree(m->brsl, nend * sizeof(int));
- zfree(m, sizeof(m));
+ zfree(m, sizeof(*m));
}
/* This frees the groups of matches. */
diff --git a/Src/Zle/compctl.c b/Src/Zle/compctl.c
index 0b7a32445..189582d22 100644
--- a/Src/Zle/compctl.c
+++ b/Src/Zle/compctl.c
@@ -1515,7 +1515,7 @@ printcompctl(char *s, Compctl cc, int printflags, int ispat)
if (cclist & COMP_LIST)
printf(" --");
}
- if (cc && cc->xor) {
+ if (cc->xor) {
/* print xor'd (+) completions */
printf(" +");
if (cc->xor != &cc_default)
@@ -1879,7 +1879,7 @@ ccmakehookfn(UNUSED(Hookdef dummy), struct ccmakedat *dat)
if (!m || !(m = m->next))
break;
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
}
redup(osi, 0);
dat->lst = 1;
@@ -2121,7 +2121,7 @@ getreal(char *str)
if (!errflag && nonempty(l) &&
((char *) peekfirst(l)) && ((char *) peekfirst(l))[0])
return dupstring(peekfirst(l));
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
return dupstring(str);
}
@@ -2599,7 +2599,7 @@ makecomplistlist(Compctl cc, char *s, int incmd, int compadd)
makecomplistflags(cc, s, incmd, compadd);
/* Reset some information variables for the next try. */
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
offs = oloffs;
wb = owb;
we = owe;
@@ -2795,7 +2795,7 @@ sep_comp_string(char *ss, char *s, int noffs)
* get the words we have to expand. */
addedx = 1;
noerrs = 1;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
tmp = (char *) zhalloc(tl = sl + 3 + strlen(s));
strcpy(tmp, ss);
@@ -2847,9 +2847,9 @@ sep_comp_string(char *ss, char *s, int noffs)
noaliases = ona;
strinend();
inpop();
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
noerrs = ne;
- lexrestore();
+ zcontext_restore();
wb = owb;
we = owe;
zlemetacs = ocs;
@@ -3685,7 +3685,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
for (i = 0; i <= maxjob; i++)
if ((jobtab[i].stat & STAT_INUSE) &&
- jobtab[i].procs && jobtab[i].procs->text) {
+ jobtab[i].procs && jobtab[i].procs->text[0]) {
int stopped = jobtab[i].stat & STAT_STOPPED;
j = dupstring(jobtab[i].procs->text);
@@ -3707,7 +3707,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
/* Put the string in the lexer buffer and call the lexer to *
* get the words we have to expand. */
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
tmpbuf = (char *)zhalloc(strlen(cc->str) + 5);
sprintf(tmpbuf, "foo %s", cc->str); /* KLUDGE! */
@@ -3725,8 +3725,8 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
noaliases = ona;
strinend();
inpop();
- errflag = 0;
- lexrestore();
+ errflag &= ~ERRFLAG_ERROR;
+ zcontext_restore();
/* Fine, now do full expansion. */
prefork(foo, 0);
if (!errflag) {
@@ -3853,7 +3853,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
yaptr = get_user_var(uv);
if ((tt = cc->explain)) {
tt = dupstring(tt);
- if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
+ if ((cc->mask & CC_EXPANDEXPL) && !parsestr(&tt)) {
singsub(&tt);
untokenize(tt);
}
@@ -3873,7 +3873,7 @@ makecomplistflags(Compctl cc, char *s, int incmd, int compadd)
}
} else if ((tt = cc->explain)) {
tt = dupstring(tt);
- if ((cc->mask & CC_EXPANDEXPL) && !parsestr(tt)) {
+ if ((cc->mask & CC_EXPANDEXPL) && !parsestr(&tt)) {
singsub(&tt);
untokenize(tt);
}
diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index 5e5ba9f20..f54206619 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -780,6 +780,7 @@ clnicezputs(int do_colors, char *s, int ml)
/* Is the screen full? */
if (ml == mlend - 1 && col == zterm_columns - 1) {
mlprinted = ml - oml;
+ free(ums);
return 0;
}
if (t < wptr) {
@@ -804,6 +805,7 @@ clnicezputs(int do_colors, char *s, int ml)
ml++;
if (mscroll && !--mrestlines && (ask = asklistscroll(ml))) {
mlprinted = ml - oml;
+ free(ums);
return ask;
}
col -= zterm_columns;
@@ -1375,7 +1377,7 @@ compprintlist(int showall)
tcout(TCCLEAREOD);
g = ((lasttype && lastg) ? lastg : amatches);
- while (g) {
+ while (g && !errflag) {
char **pp = g->ylist;
#ifdef ZSH_HEAP_DEBUG
@@ -1389,7 +1391,7 @@ compprintlist(int showall)
ml = lastml;
lastused = 1;
}
- while (*e) {
+ while (*e && !errflag) {
if (((*e)->count || (*e)->always) &&
(!listdat.onlyexpl ||
(listdat.onlyexpl & ((*e)->always > 0 ? 2 : 1)))) {
@@ -1469,11 +1471,11 @@ compprintlist(int showall)
nl = nc = g->lins;
- while (n && nl--) {
+ while (n && nl-- && !errflag) {
i = g->cols;
mc = 0;
pq = pp;
- while (n && i--) {
+ while (n && i-- && !errflag) {
if (pq - g->ylist >= g->lcount)
break;
if (compzputs(*pq, mscroll))
@@ -1582,7 +1584,7 @@ compprintlist(int showall)
} else
p = skipnolist(g->matches, showall);
- while (n && nl--) {
+ while (n && nl-- && !errflag) {
if (!lasttype && ml >= mlbeg) {
lasttype = 3;
lastg = g;
@@ -1596,7 +1598,7 @@ compprintlist(int showall)
i = g->cols;
mc = 0;
q = p;
- while (n && i--) {
+ while (n && i-- && !errflag) {
wid = (g->widths ? g->widths[mc] : g->width);
if (!(m = *q)) {
if (clprintm(g, NULL, mc, ml, (!i), wid))
@@ -2059,8 +2061,8 @@ complistmatches(UNUSED(Hookdef dummy), Chdata dat)
i = zterm_columns * listdat.nlines;
free(mtab);
- mtab = (Cmatch **) zalloc(i * sizeof(Cmatch **));
- memset(mtab, 0, i * sizeof(Cmatch **));
+ mtab = (Cmatch **) zalloc(i * sizeof(Cmatch *));
+ memset(mtab, 0, i * sizeof(Cmatch *));
free(mgtab);
mgtab = (Cmgroup *) zalloc(i * sizeof(Cmgroup));
#ifdef DEBUG
@@ -2790,7 +2792,9 @@ domenuselect(Hookdef dummy, Chdata dat)
Menustack s = (Menustack) zhalloc(sizeof(*s));
int ol;
- mode = 0;
+ if (mode == MM_INTER)
+ do_single(*minfo.cur);
+ mode = 0;
s->prev = u;
u = s;
s->line = dupstring(zlemetaline);
@@ -2880,7 +2884,8 @@ domenuselect(Hookdef dummy, Chdata dat)
brend = dupbrinfo(u->brend, &lastbrend, 0);
nbrbeg = u->nbrbeg;
nbrend = u->nbrend;
- origline = u->origline;
+ zsfree(origline);
+ origline = ztrdup(u->origline);
origcs = u->origcs;
origll = u->origll;
strcpy(status, u->status);
@@ -3234,7 +3239,8 @@ domenuselect(Hookdef dummy, Chdata dat)
* don't want that, just what the user typed,
* so restore the information.
*/
- origline = modeline;
+ zsfree(origline);
+ origline = ztrdup(modeline);
origcs = modecs;
origll = modell;
zlemetacs = 0;
diff --git a/Src/Zle/compmatch.c b/Src/Zle/compmatch.c
index 4cd3b9ffe..05ae43ae6 100644
--- a/Src/Zle/compmatch.c
+++ b/Src/Zle/compmatch.c
@@ -1014,6 +1014,7 @@ comp_match(char *pfx, char *sfx, char *w, Patprog cp, Cline *clp, int qu,
Brinfo *bpl, int bcp, Brinfo *bsl, int bcs, int *exact)
{
char *r = NULL;
+ int onoerrs = noerrs;
if (cp) {
/* We have a globcomplete-like pattern, just use that. */
@@ -1033,12 +1034,14 @@ comp_match(char *pfx, char *sfx, char *w, Patprog cp, Cline *clp, int qu,
*/
teststr = dupstring(r);
tokenize(teststr);
+ noerrs = 1;
if (parse_subst_string(teststr))
teststr = r;
else {
remnulargs(teststr);
untokenize(teststr);
}
+ noerrs = onoerrs;
} else
teststr = r;
if (!pattry(cp, teststr))
diff --git a/Src/Zle/compresult.c b/Src/Zle/compresult.c
index fcceb670c..9f383f4b8 100644
--- a/Src/Zle/compresult.c
+++ b/Src/Zle/compresult.c
@@ -1090,15 +1090,16 @@ do_single(Cmatch m)
}
if (tryit) {
noerrs = 1;
- parsestr(p);
+ p = dupstring(p);
+ parsestr(&p);
singsub(&p);
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
noerrs = ne;
}
} else {
p = (char *) zhalloc(strlen(prpre) + strlen(str) +
strlen(psuf) + 3);
- sprintf(p, "%s%s%s", ((prpre && *prpre) ?
+ sprintf(p, "%s%s%s", (*prpre ?
prpre : "./"), str, psuf);
}
/* And do the stat. */
diff --git a/Src/Zle/computil.c b/Src/Zle/computil.c
index b11c39f25..a81d1ddad 100644
--- a/Src/Zle/computil.c
+++ b/Src/Zle/computil.c
@@ -4060,7 +4060,8 @@ cfp_test_exact(LinkList names, char **accept, char *skipped)
if (sl > PATH_MAX2)
return NULL;
- suf = dyncat(skipped, rembslash(dyncat(compprefix, compsuffix)));
+ suf = dyncat(skipped, rembslash(dyncat(compprefix ? compprefix : "",
+ compsuffix ? compsuffix : "")));
for (node = firstnode(names); node; incnode(node)) {
l = strlen(p = (char *) getdata(node));
diff --git a/Src/Zle/iwidgets.list b/Src/Zle/iwidgets.list
index e3ffe3e8c..b41661a7d 100644
--- a/Src/Zle/iwidgets.list
+++ b/Src/Zle/iwidgets.list
@@ -24,7 +24,7 @@
"backward-kill-word", backwardkillword, ZLE_KILL | ZLE_KEEPSUFFIX
"backward-word", backwardword, 0
"beep", handlefeep, 0
-"beginning-of-buffer-or-history", beginningofbufferorhistory, 0
+"beginning-of-buffer-or-history", beginningofbufferorhistory, ZLE_LINEMOVE
"beginning-of-history", beginningofhistory, 0
"beginning-of-line", beginningofline, 0
"beginning-of-line-hist", beginningoflinehist, 0
@@ -41,11 +41,12 @@
"digit-argument", digitargument, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
"down-case-word", downcaseword, 0
"down-history", downhistory, 0
+"down-line", downline, ZLE_LINEMOVE | ZLE_LASTCOL
"down-line-or-history", downlineorhistory, ZLE_LINEMOVE | ZLE_LASTCOL
"down-line-or-search", downlineorsearch, ZLE_LINEMOVE | ZLE_LASTCOL
"emacs-backward-word", emacsbackwardword, 0
"emacs-forward-word", emacsforwardword, 0
-"end-of-buffer-or-history", endofbufferorhistory, 0
+"end-of-buffer-or-history", endofbufferorhistory, ZLE_LINEMOVE
"end-of-history", endofhistory, 0
"end-of-line", endofline, 0
"end-of-line-hist", endoflinehist, 0
@@ -88,6 +89,7 @@
"push-input", pushinput, 0
"push-line", pushline, 0
"push-line-or-edit", pushlineoredit, 0
+"put-replace-selection", putreplaceselection, ZLE_KEEPSUFFIX
"quoted-insert", quotedinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX
"quote-line", quoteline, 0
"quote-region", quoteregion, 0
@@ -98,13 +100,19 @@
"reset-prompt", resetprompt, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
"reverse-menu-complete", reversemenucomplete, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_ISCOMP
"run-help", processcmd, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
+"select-a-word", selectword, ZLE_KEEPSUFFIX
+"select-in-word", selectword, ZLE_KEEPSUFFIX
+"select-a-blank-word", selectword, ZLE_KEEPSUFFIX
+"select-in-blank-word", selectword, ZLE_KEEPSUFFIX
+"select-a-shell-word", selectargument, ZLE_KEEPSUFFIX
+"select-in-shell-word", selectargument, ZLE_KEEPSUFFIX
"self-insert", selfinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX
"self-insert-unmeta", selfinsertunmeta, ZLE_MENUCMP | ZLE_KEEPSUFFIX
"send-break", sendbreak, 0
"set-mark-command", setmarkcommand, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
-"split-undo", splitundo, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_NOTCOMMAND
+"split-undo", splitundo, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
"spell-word", spellword, 0
-"set-local-history", setlocalhistory, 0
+"set-local-history", setlocalhistory, ZLE_LASTCOL
"transpose-chars", transposechars, 0
"transpose-words", transposewords, 0
"undefined-key", undefinedkey, 0
@@ -112,6 +120,7 @@
"universal-argument", universalargument, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_NOTCOMMAND
"up-case-word", upcaseword, 0
"up-history", uphistory, 0
+"up-line", upline, ZLE_LINEMOVE | ZLE_LASTCOL
"up-line-or-history", uplineorhistory, ZLE_LINEMOVE | ZLE_LASTCOL
"up-line-or-search", uplineorsearch, ZLE_LINEMOVE | ZLE_LASTCOL
"vi-add-eol", viaddeol, 0
@@ -119,20 +128,22 @@
"vi-backward-blank-word", vibackwardblankword, 0
"vi-backward-char", vibackwardchar, 0
"vi-backward-delete-char", vibackwarddeletechar, ZLE_KEEPSUFFIX
-"vi-backward-kill-word", vibackwardkillword, ZLE_KILL | ZLE_KEEPSUFFIX
+"vi-backward-kill-word", vibackwardkillword, ZLE_KEEPSUFFIX
"vi-backward-word", vibackwardword, 0
+"vi-backward-word-end", vibackwardwordend, 0
+"vi-backward-blank-word-end", vibackwardblankwordend, 0
"vi-beginning-of-line", vibeginningofline, 0
-"vi-caps-lock-panic", vicapslockpanic, 0
-"vi-change", vichange, 0
+"vi-caps-lock-panic", vicapslockpanic, ZLE_LASTCOL
+"vi-change", vichange, ZLE_LASTCOL | ZLE_VIOPER
"vi-change-eol", vichangeeol, 0
"vi-change-whole-line", vichangewholeline, 0
"vi-cmd-mode", vicmdmode, 0
-"vi-delete", videlete, ZLE_KILL | ZLE_KEEPSUFFIX
+"vi-delete", videlete, ZLE_KEEPSUFFIX | ZLE_LASTCOL | ZLE_VIOPER
"vi-delete-char", videletechar, ZLE_KEEPSUFFIX
"vi-digit-or-beginning-of-line", vidigitorbeginningofline, 0
"vi-down-line-or-history", vidownlineorhistory, ZLE_LINEMOVE
"vi-end-of-line", viendofline, ZLE_LASTCOL
-"vi-fetch-history", vifetchhistory, 0
+"vi-fetch-history", vifetchhistory, ZLE_LINEMOVE
"vi-find-next-char", vifindnextchar, 0
"vi-find-next-char-skip", vifindnextcharskip, 0
"vi-find-prev-char", vifindprevchar, 0
@@ -145,22 +156,22 @@
"vi-forward-word-end", viforwardwordend, 0
"vi-goto-column", vigotocolumn, 0
"vi-goto-mark", vigotomark, 0
-"vi-goto-mark-line", vigotomarkline, 0
+"vi-goto-mark-line", vigotomarkline, ZLE_LINEMOVE
"vi-history-search-backward", vihistorysearchbackward, 0
"vi-history-search-forward", vihistorysearchforward, 0
-"vi-indent", viindent, 0
+"vi-indent", viindent, ZLE_LASTCOL | ZLE_VIOPER
"vi-insert", viinsert, 0
"vi-insert-bol", viinsertbol, 0
"vi-join", vijoin, 0
-"vi-kill-eol", vikilleol, ZLE_KILL | ZLE_KEEPSUFFIX
-"vi-kill-line", vikillline, ZLE_KILL | ZLE_KEEPSUFFIX
+"vi-kill-eol", vikilleol, ZLE_KEEPSUFFIX
+"vi-kill-line", vikillline, ZLE_KEEPSUFFIX
"vi-match-bracket", vimatchbracket, 0
"vi-open-line-above", viopenlineabove, 0
"vi-open-line-below", viopenlinebelow, 0
-"vi-oper-swap-case", vioperswapcase, 0
+"vi-oper-swap-case", vioperswapcase, ZLE_LASTCOL | ZLE_VIOPER
"vi-pound-insert", vipoundinsert, 0
-"vi-put-after", viputafter, ZLE_YANK | ZLE_KEEPSUFFIX
-"vi-put-before", viputbefore, ZLE_YANK | ZLE_KEEPSUFFIX
+"vi-put-after", viputafter, ZLE_YANKAFTER | ZLE_KEEPSUFFIX
+"vi-put-before", viputbefore, ZLE_YANKBEFORE | ZLE_KEEPSUFFIX
"vi-quoted-insert", viquotedinsert, ZLE_MENUCMP | ZLE_KEEPSUFFIX
"vi-repeat-change", virepeatchange, 0
"vi-repeat-find", virepeatfind, 0
@@ -172,15 +183,17 @@
"vi-set-buffer", visetbuffer, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
"vi-set-mark", visetmark, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
"vi-substitute", visubstitute, 0
-"vi-swap-case", viswapcase, 0
+"vi-swap-case", viswapcase, ZLE_LASTCOL
"vi-undo-change", viundochange, ZLE_KEEPSUFFIX
-"vi-unindent", viunindent, 0
+"vi-unindent", viunindent, ZLE_LASTCOL | ZLE_VIOPER
"vi-up-line-or-history", viuplineorhistory, ZLE_LINEMOVE
-"vi-yank", viyank, 0
+"vi-yank", viyank, ZLE_LASTCOL | ZLE_VIOPER
"vi-yank-eol", viyankeol, 0
"vi-yank-whole-line", viyankwholeline, 0
+"visual-line-mode", visuallinemode, ZLE_MENUCMP | ZLE_LASTCOL
+"visual-mode", visualmode, ZLE_MENUCMP | ZLE_LASTCOL
"what-cursor-position", whatcursorposition, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
"where-is", whereis, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
"which-command", processcmd, ZLE_MENUCMP | ZLE_KEEPSUFFIX | ZLE_LASTCOL
-"yank", yank, ZLE_YANK | ZLE_KEEPSUFFIX
-"yank-pop", yankpop, ZLE_YANK | ZLE_KEEPSUFFIX
+"yank", yank, ZLE_YANKBEFORE | ZLE_KEEPSUFFIX
+"yank-pop", yankpop, ZLE_KEEPSUFFIX | ZLE_NOTCOMMAND
diff --git a/Src/Zle/textobjects.c b/Src/Zle/textobjects.c
new file mode 100644
index 000000000..9b3277a97
--- /dev/null
+++ b/Src/Zle/textobjects.c
@@ -0,0 +1,322 @@
+/*
+ * textobjects.c - ZLE module implementing Vim style text objects
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 2014 Oliver Kiddle
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Oliver Kiddle or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Oliver Kiddle and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Oliver Kiddle and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Oliver Kiddle and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+
+#include "zle.mdh"
+#include "textobjects.pro"
+
+/* class of character: 0 is whitespace, 1 is word character, 2 is other */
+static int
+wordclass(ZLE_CHAR_T x)
+{
+ return (ZC_iblank(x) ? 0 : ((ZC_ialnum(x) || (ZWC('_') == x)) ? 1 : 2));
+}
+
+static int
+blankwordclass(ZLE_CHAR_T x)
+{
+ return (ZC_iblank(x) ? 0 : 1);
+}
+
+/**/
+int
+selectword(UNUSED(char **args))
+{
+ int n = zmult;
+ int all = (bindk == t_selectaword || bindk == t_selectablankword);
+ int (*viclass)(ZLE_CHAR_T) = (bindk == t_selectaword ||
+ bindk == t_selectinword) ? wordclass : blankwordclass;
+ int sclass = viclass(zleline[zlecs]);
+ int doblanks = all && sclass;
+
+ if (!invicmdmode()) {
+ region_active = 1;
+ mark = zlecs;
+ }
+ if (!region_active || zlecs == mark) {
+ /* search back to first character of same class as the start position
+ * also stop at the beginning of the line */
+ mark = zlecs;
+ while (mark) {
+ int pos = mark;
+ DECPOS(pos);
+ if (zleline[pos] == ZWC('\n') || viclass(zleline[pos]) != sclass)
+ break;
+ mark = pos;
+ }
+ /* similarly scan forward over characters of the same class */
+ while (zlecs < zlell) {
+ INCCS();
+ int pos = zlecs;
+ /* single newlines within blanks are included */
+ if (all && !sclass && pos < zlell && zleline[pos] == ZWC('\n'))
+ INCPOS(pos);
+
+ if (zleline[pos] == ZWC('\n') || viclass(zleline[pos]) != sclass)
+ break;
+ }
+
+ if (all) {
+ int nclass = viclass(zleline[zlecs]);
+ /* if either start or new position is blank advance over
+ * a new block of characters of a common type */
+ if (!nclass || !sclass) {
+ while (zlecs < zlell) {
+ INCCS();
+ if (zleline[zlecs] == ZWC('\n') ||
+ viclass(zleline[zlecs]) != nclass)
+ break;
+ }
+ if (n < 2)
+ doblanks = 0;
+ }
+ }
+ } else {
+ /* For visual mode, advance one char so repeated
+ * invocations select subsequent words */
+ if (zlecs > mark) {
+ if (zlecs < zlell)
+ INCCS();
+ } else if (zlecs)
+ DECCS();
+ if (zlecs < mark) {
+ /* visual mode with the cursor before the mark: move cursor back */
+ while (n-- > 0) {
+ int pos = zlecs;
+ /* first over blanks */
+ if (all && (!viclass(zleline[pos]) ||
+ zleline[pos] == ZWC('\n'))) {
+ all = 0;
+ while (pos) {
+ DECPOS(pos);
+ if (zleline[pos] == ZWC('\n'))
+ break;
+ zlecs = pos;
+ if (viclass(zleline[pos]))
+ break;
+ }
+ } else if (zlecs && zleline[zlecs] == ZWC('\n')) {
+ /* for in widgets pass over one newline */
+ DECPOS(pos);
+ if (zleline[pos] != ZWC('\n'))
+ zlecs = pos;
+ }
+ pos = zlecs;
+ sclass = viclass(zleline[zlecs]);
+ /* now retreat over non-blanks */
+ while (zleline[pos] != ZWC('\n') &&
+ viclass(zleline[pos]) == sclass) {
+ zlecs = pos;
+ if (!pos) {
+ zlecs = 0;
+ break;
+ }
+ DECPOS(pos);
+ }
+ /* blanks again but only if there were none first time */
+ if (all && zlecs) {
+ pos = zlecs;
+ DECPOS(pos);
+ if (!viclass(zleline[pos])) {
+ while (pos) {
+ DECPOS(pos);
+ if (zleline[pos] == ZWC('\n') ||
+ viclass(zleline[pos]))
+ break;
+ zlecs = pos;
+ }
+ }
+ }
+ }
+ return 0;
+ }
+ n++;
+ doblanks = 0;
+ }
+ region_active = !!region_active; /* force to character wise */
+
+ /* for each digit argument, advance over further block of one class */
+ while (--n > 0) {
+ if (zlecs < zlell && zleline[zlecs] == ZWC('\n'))
+ INCCS();
+ sclass = viclass(zleline[zlecs]);
+ while (zlecs < zlell) {
+ INCCS();
+ if (zleline[zlecs] == ZWC('\n') ||
+ viclass(zleline[zlecs]) != sclass)
+ break;
+ }
+ /* for 'a' widgets, advance extra block if either consists of blanks */
+ if (all) {
+ if (zlecs < zlell && zleline[zlecs] == ZWC('\n'))
+ INCCS();
+ if (!sclass || !viclass(zleline[zlecs]) ) {
+ sclass = viclass(zleline[zlecs]);
+ if (n == 1 && !sclass)
+ doblanks = 0;
+ while (zlecs < zlell) {
+ INCCS();
+ if (zleline[zlecs] == ZWC('\n') ||
+ viclass(zleline[zlecs]) != sclass)
+ break;
+ }
+ }
+ }
+ }
+
+ /* if we didn't remove blanks at either end we remove some at the start */
+ if (doblanks) {
+ int pos = mark;
+ while (pos) {
+ DECPOS(pos);
+ /* don't remove blanks at the start of the line, i.e indentation */
+ if (zleline[pos] == ZWC('\n'))
+ break;
+ if (!ZC_iblank(zleline[pos])) {
+ INCPOS(pos);
+ mark = pos;
+ break;
+ }
+ }
+ }
+ /* Adjustment: vi operators don't include the cursor position, in insert
+ * or emacs mode the region also doesn't but for vi visual mode it is
+ * included. */
+ if (zlecs && zlecs > mark && !virangeflag)
+ DECCS();
+
+ return 0;
+}
+
+/**/
+int
+selectargument(UNUSED(char **args))
+{
+ int ne = noerrs, ocs = zlemetacs;
+ int owb = wb, owe= we, oadx = addedx, ona = noaliases;
+ char *p;
+ int ll, cs;
+ char *linein;
+ int wend = 0, wcur = 0;
+ int n = zmult;
+ int *wstarts;
+ int tmpsz;
+
+ if (n < 1 || 2*n > zlell + 1)
+ return 1;
+
+ /* if used from emacs mode enable the region */
+ if (!invicmdmode()) {
+ region_active = 1;
+ mark = zlecs;
+ }
+
+ wstarts = (int *) zhalloc(n * sizeof(int));
+ memset(wstarts, 0, n * sizeof(int));
+
+ addedx = 0;
+ noerrs = 1;
+ zcontext_save();
+ lexflags = LEXFLAGS_ACTIVE;
+ linein = zlegetline(&ll, &cs);
+ zlemetall = ll;
+ zlemetacs = cs;
+
+ if (!isfirstln && chline) {
+ p = (char *) zhalloc(hptr - chline + zlemetall + 2);
+ memcpy(p, chline, hptr - chline);
+ memcpy(p + (hptr - chline), linein, ll);
+ p[(hptr - chline) + ll] = '\0';
+ inpush(p, 0, NULL);
+ zlemetacs += hptr - chline;
+ } else {
+ p = (char *) zhalloc(ll + 1);
+ memcpy(p, linein, ll);
+ p[ll] = '\0';
+ inpush(p, 0, NULL);
+ }
+ if (zlemetacs)
+ zlemetacs--;
+ strinbeg(0);
+ noaliases = 1;
+ do {
+ wstarts[wcur++] = wend;
+ wcur %= n;
+ ctxtlex();
+ if (tok == ENDINPUT || tok == LEXERR)
+ break;
+ wend = zlemetall - inbufct;
+ } while (tok != ENDINPUT && tok != LEXERR && wend <= zlemetacs);
+ noaliases = ona;
+ strinend();
+ inpop();
+ errflag &= ~ERRFLAG_ERROR;
+ noerrs = ne;
+ zcontext_restore();
+ zlemetacs = ocs;
+ wb = owb;
+ we = owe;
+ addedx = oadx;
+
+ /* convert offsets for mark and zlecs back to ZLE internal format */
+ linein[wend] = '\0'; /* a bit of a hack to get two offsets */
+ free(stringaszleline(linein, wstarts[wcur], &zlecs, &tmpsz, &mark));
+ free(linein);
+
+ if (bindk == t_selectinshellword) {
+ ZLE_CHAR_T *match = ZWS("`\'\"");
+ ZLE_CHAR_T *lmatch = ZWS("\'({"), *rmatch = ZWS("\')}");
+ ZLE_CHAR_T *ematch = match, *found;
+ int start, end = zlecs;
+ /* for 'in' widget, don't include initial blanks ... */
+ while (mark < zlecs && ZC_iblank(zleline[mark]))
+ INCPOS(mark);
+ /* ... or a matching pair of quotes */
+ start = mark;
+ if (zleline[start] == ZWC('$')) {
+ match = lmatch;
+ ematch = rmatch;
+ INCPOS(start);
+ }
+ found = ZS_strchr(match, zleline[start]);
+ if (found) {
+ DECPOS(end);
+ if (zleline[end] == ematch[found-match]) {
+ zlecs = end;
+ INCPOS(start);
+ mark = start;
+ }
+ }
+ }
+
+ /* Adjustment: vi operators don't include the cursor position */
+ if (!virangeflag)
+ DECCS();
+
+ return 0;
+}
diff --git a/Src/Zle/zle.h b/Src/Zle/zle.h
index 870e2149d..3c652909e 100644
--- a/Src/Zle/zle.h
+++ b/Src/Zle/zle.h
@@ -203,13 +203,16 @@ struct widget {
#define WIDGET_INT (1<<0) /* widget is internally implemented */
#define WIDGET_NCOMP (1<<1) /* new style completion widget */
#define ZLE_MENUCMP (1<<2) /* DON'T invalidate completion list */
-#define ZLE_YANK (1<<3)
-#define ZLE_LINEMOVE (1<<4) /* command is a line-oriented movement */
-#define ZLE_LASTCOL (1<<5) /* command maintains lastcol correctly */
-#define ZLE_KILL (1<<6)
-#define ZLE_KEEPSUFFIX (1<<7) /* DON'T remove added suffix */
-#define ZLE_NOTCOMMAND (1<<8) /* widget should not alter lastcmd */
-#define ZLE_ISCOMP (1<<9) /* usable for new style completion */
+#define ZLE_YANKAFTER (1<<3)
+#define ZLE_YANKBEFORE (1<<4)
+#define ZLE_YANK (ZLE_YANKAFTER | ZLE_YANKBEFORE)
+#define ZLE_LINEMOVE (1<<5) /* command is a line-oriented movement */
+#define ZLE_VIOPER (1<<6) /* widget reads further keys so wait if prefix */
+#define ZLE_LASTCOL (1<<7) /* command maintains lastcol correctly */
+#define ZLE_KILL (1<<8)
+#define ZLE_KEEPSUFFIX (1<<9) /* DON'T remove added suffix */
+#define ZLE_NOTCOMMAND (1<<10) /* widget should not alter lastcmd */
+#define ZLE_ISCOMP (1<<11) /* usable for new style completion */
/* thingies */
@@ -240,6 +243,9 @@ struct modifier {
#define MOD_VIBUF (1<<2) /* a vi cut buffer has been selected */
#define MOD_VIAPP (1<<3) /* appending to the vi cut buffer */
#define MOD_NEG (1<<4) /* last command was negate argument */
+#define MOD_NULL (1<<5) /* throw away text for the vi cut buffer */
+#define MOD_CHAR (1<<6) /* force character-wise movement */
+#define MOD_LINE (1<<7) /* force line-wise movement */
/* current modifier status */
@@ -256,6 +262,7 @@ struct modifier {
* of visible characters directly input by
* the user.
*/
+#define CUT_YANK (1<<3) /* vi yank: use register 0 instead of 1-9 */
/* undo system */
diff --git a/Src/Zle/zle.mdd b/Src/Zle/zle.mdd
index c6e4d11c2..dd69eff2c 100644
--- a/Src/Zle/zle.mdd
+++ b/Src/Zle/zle.mdd
@@ -7,7 +7,8 @@ autofeatures="b:bindkey b:vared b:zle"
objects="zle_bindings.o zle_hist.o zle_keymap.o zle_main.o \
zle_misc.o zle_move.o zle_params.o zle_refresh.o \
-zle_thingy.o zle_tricky.o zle_utils.o zle_vi.o zle_word.o"
+zle_thingy.o zle_tricky.o zle_utils.o zle_vi.o zle_word.o \
+textobjects.o"
headers="zle.h zle_things.h"
diff --git a/Src/Zle/zle_bindings.c b/Src/Zle/zle_bindings.c
index 682691347..2ae8c8764 100644
--- a/Src/Zle/zle_bindings.c
+++ b/Src/Zle/zle_bindings.c
@@ -278,7 +278,7 @@ int viinsbind[32] = {
/* ^U */ z_vikillline,
/* ^V */ z_viquotedinsert,
/* ^W */ z_vibackwardkillword,
- /* ^X */ z_selfinsert,
+ /* ^X */ z_undefinedkey,
/* ^Y */ z_selfinsert,
/* ^Z */ z_selfinsert,
/* ^[ */ z_vicmdmode,
@@ -308,7 +308,7 @@ int vicmdbind[128] = {
/* ^O */ z_undefinedkey,
/* ^P */ z_uphistory,
/* ^Q */ z_undefinedkey,
- /* ^R */ z_redisplay,
+ /* ^R */ z_redo,
/* ^S */ z_undefinedkey,
/* ^T */ z_undefinedkey,
/* ^U */ z_undefinedkey,
@@ -376,7 +376,7 @@ int vicmdbind[128] = {
/* S */ z_vichangewholeline,
/* T */ z_vifindprevcharskip,
/* U */ z_undefinedkey,
- /* V */ z_undefinedkey,
+ /* V */ z_visuallinemode,
/* W */ z_viforwardblankword,
/* X */ z_vibackwarddeletechar,
/* Y */ z_viyankwholeline,
@@ -407,8 +407,8 @@ int vicmdbind[128] = {
/* r */ z_vireplacechars,
/* s */ z_visubstitute,
/* t */ z_vifindnextcharskip,
- /* u */ z_viundochange,
- /* v */ z_undefinedkey,
+ /* u */ z_undo,
+ /* v */ z_visualmode,
/* w */ z_viforwardword,
/* x */ z_videletechar,
/* y */ z_viyank,
diff --git a/Src/Zle/zle_hist.c b/Src/Zle/zle_hist.c
index 44b39d186..cc66f99ae 100644
--- a/Src/Zle/zle_hist.c
+++ b/Src/Zle/zle_hist.c
@@ -227,14 +227,14 @@ uphistory(UNUSED(char **args))
}
/**/
-static int
-upline(void)
+int
+upline(char **args)
{
int n = zmult;
if (n < 0) {
zmult = -zmult;
- n = -downline();
+ n = -downline(args);
zmult = -zmult;
return n;
}
@@ -270,7 +270,7 @@ int
uplineorhistory(char **args)
{
int ocs = zlecs;
- int n = upline();
+ int n = upline(args);
if (n) {
int m = zmult, ret;
@@ -300,7 +300,7 @@ int
uplineorsearch(char **args)
{
int ocs = zlecs;
- int n = upline();
+ int n = upline(args);
if (n) {
int m = zmult, ret;
@@ -316,14 +316,14 @@ uplineorsearch(char **args)
}
/**/
-static int
-downline(void)
+int
+downline(char **args)
{
int n = zmult;
if (n < 0) {
zmult = -zmult;
- n = -upline();
+ n = -upline(args);
zmult = -zmult;
return n;
}
@@ -358,7 +358,7 @@ int
downlineorhistory(char **args)
{
int ocs = zlecs;
- int n = downline();
+ int n = downline(args);
if (n) {
int m = zmult, ret;
@@ -388,7 +388,7 @@ int
downlineorsearch(char **args)
{
int ocs = zlecs;
- int n = downline();
+ int n = downline(args);
if (n) {
int m = zmult, ret;
@@ -821,6 +821,8 @@ pushline(UNUSED(char **args))
zpushnode(bufstack, zlelineasstring(zleline, zlell, 0, NULL, NULL, 0));
while (--n)
zpushnode(bufstack, ztrdup(""));
+ if (invicmdmode())
+ INCCS();
stackcs = zlecs;
*zleline = ZWC('\0');
zlell = zlecs = 0;
@@ -851,8 +853,10 @@ pushlineoredit(char **args)
free(zhline);
}
ret = pushline(args);
- if (!isfirstln)
- errflag = done = 1;
+ if (!isfirstln) {
+ errflag |= ERRFLAG_ERROR|ERRFLAG_INT;
+ done = 1;
+ }
clearlist = 1;
return ret;
}
diff --git a/Src/Zle/zle_keymap.c b/Src/Zle/zle_keymap.c
index e21e769bd..c6fae251d 100644
--- a/Src/Zle/zle_keymap.c
+++ b/Src/Zle/zle_keymap.c
@@ -503,7 +503,18 @@ selectkeymap(char *name, int fb)
mod_export void
selectlocalmap(Keymap m)
{
+ Keymap oldm = localkeymap;
localkeymap = m;
+ if (oldm && !m)
+ {
+ /*
+ * No local keymap; so we are returning to the global map. If
+ * the user ^Ced in the local map, they probably just want to go
+ * back to normal editing. So remove the interrupt error
+ * status.
+ */
+ errflag &= ~ERRFLAG_INT;
+ }
}
/* Reopen the currently selected keymap, in case it got deleted. This *
@@ -1191,7 +1202,7 @@ init_keymaps(void)
{
createkeymapnamtab();
default_bindings();
- keybuf = (char *)zalloc(keybufsz);
+ keybuf = (char *)zshcalloc(keybufsz);
lastnamed = refthingy(t_undefinedkey);
}
@@ -1277,8 +1288,10 @@ default_bindings(void)
Keymap vmap = newkeymap(NULL, "viins");
Keymap emap = newkeymap(NULL, "emacs");
Keymap amap = newkeymap(NULL, "vicmd");
+ Keymap oppmap = newkeymap(NULL, "viopp");
+ Keymap vismap = newkeymap(NULL, "visual");
Keymap smap = newkeymap(NULL, ".safe");
- Keymap vimaps[2], kptr;
+ Keymap vimaps[2], vilmaps[2], kptr;
char buf[3], *ed;
int i;
@@ -1332,6 +1345,36 @@ default_bindings(void)
add_cursor_key(kptr, TCLEFTCURSOR, t_vibackwardchar, 'D');
add_cursor_key(kptr, TCRIGHTCURSOR, t_viforwardchar, 'C');
}
+ vilmaps[0] = oppmap;
+ vilmaps[1] = vismap;
+ for (i = 0; i < 2; i++) {
+ /* vi visual selection and operator pending local maps */
+ kptr = vilmaps[i];
+ add_cursor_key(kptr, TCUPCURSOR, t_upline, 'A');
+ add_cursor_key(kptr, TCDOWNCURSOR, t_downline, 'B');
+ bindkey(kptr, "k", refthingy(t_upline), NULL);
+ bindkey(kptr, "j", refthingy(t_downline), NULL);
+ bindkey(kptr, "aa", refthingy(t_selectashellword), NULL);
+ bindkey(kptr, "ia", refthingy(t_selectinshellword), NULL);
+ bindkey(kptr, "aw", refthingy(t_selectaword), NULL);
+ bindkey(kptr, "iw", refthingy(t_selectinword), NULL);
+ bindkey(kptr, "aW", refthingy(t_selectablankword), NULL);
+ bindkey(kptr, "iW", refthingy(t_selectinblankword), NULL);
+ }
+ /* escape in operator pending cancels the operation */
+ bindkey(oppmap, "\33", refthingy(t_vicmdmode), NULL);
+ bindkey(vismap, "o", refthingy(t_exchangepointandmark), NULL);
+ bindkey(vismap, "p", refthingy(t_putreplaceselection), NULL);
+ bindkey(vismap, "x", refthingy(t_videlete), NULL);
+ bindkey(vismap, "~", refthingy(t_vioperswapcase), NULL);
+
+ /* vi mode: some common vim bindings */
+ bindkey(amap, "ga", refthingy(t_whatcursorposition), NULL);
+ bindkey(amap, "ge", refthingy(t_vibackwardwordend), NULL);
+ bindkey(amap, "gE", refthingy(t_vibackwardblankwordend), NULL);
+ bindkey(amap, "gg", refthingy(t_beginningofbufferorhistory), NULL);
+ bindkey(amap, "g~", refthingy(t_vioperswapcase), NULL);
+ bindkey(amap, "g~~", NULL, "g~g~");
/* emacs mode: arrow keys */
add_cursor_key(emap, TCUPCURSOR, t_uplineorhistory, 'A');
@@ -1373,6 +1416,8 @@ default_bindings(void)
linkkeymap(vmap, "viins", 0);
linkkeymap(emap, "emacs", 0);
linkkeymap(amap, "vicmd", 0);
+ linkkeymap(oppmap, "viopp", 0);
+ linkkeymap(vismap, "visual", 0);
linkkeymap(smap, ".safe", 1);
if (((ed = zgetenv("VISUAL")) && strstr(ed, "vi")) ||
((ed = zgetenv("EDITOR")) && strstr(ed, "vi")))
@@ -1408,6 +1453,7 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp)
Thingy func = t_undefinedkey;
char *str = NULL;
int lastlen = 0, lastc = lastchar;
+ int timeout = 0;
keybuflen = 0;
keybuf[0] = 0;
@@ -1425,7 +1471,7 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp)
* argument to bindkey is in the correct form for the locale.
* That's beyond our control.
*/
- while(getkeybuf(!!lastlen) != EOF) {
+ while(getkeybuf(timeout) != EOF) {
char *s;
Thingy f;
int loc = !!localkeymap;
@@ -1435,7 +1481,7 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp)
loc = ((f = keybind(localkeymap, keybuf, &s)) != t_undefinedkey);
ispfx = keyisprefix(localkeymap, keybuf);
}
- if (!loc)
+ if (!loc && !ispfx)
f = keybind(km, keybuf, &s);
ispfx |= keyisprefix(km, keybuf);
@@ -1444,6 +1490,11 @@ getkeymapcmd(Keymap km, Thingy *funcp, char **strp)
func = f;
str = s;
lastc = lastchar;
+
+ /* can be patient with vi commands that need a motion operator: *
+ * they wait till a key is pressed for the movement anyway */
+ timeout = !(!virangeflag && !region_active && f && f->widget &&
+ f->widget->flags & ZLE_VIOPER);
}
if (!ispfx)
break;
diff --git a/Src/Zle/zle_main.c b/Src/Zle/zle_main.c
index 442c31995..cec44c0ed 100644
--- a/Src/Zle/zle_main.c
+++ b/Src/Zle/zle_main.c
@@ -187,10 +187,6 @@ mod_export char *zlenoargs[1] = { NULL };
static char **raw_lp, **raw_rp;
-#ifdef FIONREAD
-static int delayzsetterm;
-#endif
-
/*
* File descriptors we are watching as well as the terminal fd.
* These are all for reading; we don't watch for writes or exceptions.
@@ -210,9 +206,6 @@ mod_export void
zsetterm(void)
{
struct ttyinfo ti;
-#if defined(FIONREAD)
- int val;
-#endif
if (fetchttyinfo) {
/*
@@ -224,30 +217,6 @@ zsetterm(void)
fetchttyinfo = 0;
}
-#if defined(FIONREAD)
- ioctl(SHTTY, FIONREAD, (char *)&val);
- if (val) {
- /*
- * Problems can occur on some systems when switching from
- * canonical to non-canonical input. The former is usually
- * set while running programmes, but the latter is necessary
- * for zle. If there is input in canonical mode, then we
- * need to read it without setting up the terminal. Furthermore,
- * while that input gets processed there may be more input
- * being typed (i.e. further typeahead). This means that
- * we can't set up the terminal for zle *at all* until
- * we are sure there is no more typeahead to come. So
- * if there is typeahead, we set the flag delayzsetterm.
- * Then getbyte() performs another FIONREAD call; if that is
- * 0, we have finally used up all the typeahead, and it is
- * safe to alter the terminal, which we do at that point.
- */
- delayzsetterm = 1;
- return;
- } else
- delayzsetterm = 0;
-#endif
-
/* sanitize the tty */
#ifdef HAS_TIO
shttyinfo.tio.c_lflag |= ICANON | ECHO;
@@ -343,7 +312,7 @@ zsetterm(void)
ti.ltchars.t_dsuspc = ti.ltchars.t_lnextc = -1;
#endif
-#if defined(TTY_NEEDS_DRAINING) && defined(TIOCOUTQ) && defined(HAVE_SELECT)
+#if defined(TIOCOUTQ) && defined(HAVE_SELECT)
if (baud) { /**/
int n = 0;
@@ -541,11 +510,7 @@ raw_getbyte(long do_keytmout, char *cptr)
* timeouts may be external, so we may have both a permanent watched
* fd and a long-term timeout.
*/
- if ((nwatch || tmout.tp != ZTM_NONE)
-#ifdef FIONREAD
- && ! delayzsetterm
-#endif
- ) {
+ if ((nwatch || tmout.tp != ZTM_NONE)) {
#if defined(HAVE_SELECT) || defined(HAVE_POLL)
int i, errtry = 0, selret;
# ifdef HAVE_POLL
@@ -779,7 +744,7 @@ raw_getbyte(long do_keytmout, char *cptr)
}
if (errflag) {
/* No sensible way of handling errors here */
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
/*
* Paranoia: don't run the hooks again this
* time.
@@ -883,14 +848,6 @@ getbyte(long do_keytmout, int *timeout)
if (kungetct)
ret = STOUC(kungetbuf[--kungetct]);
else {
-#ifdef FIONREAD
- if (delayzsetterm) {
- int val;
- ioctl(SHTTY, FIONREAD, (char *)&val);
- if (!val)
- zsetterm();
- }
-#endif
for (;;) {
int q = queue_signal_level();
dont_queue_signals();
@@ -925,7 +882,7 @@ getbyte(long do_keytmout, int *timeout)
die = 0;
if (!errflag && !retflag && !breaks && !exit_pending)
continue;
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
breaks = obreaks;
errno = old_errno;
return lastchar = EOF;
@@ -1067,6 +1024,7 @@ getrestchar(int inchar)
void
zlecore(void)
{
+ Keymap km;
#if !defined(HAVE_POLL) && defined(HAVE_SELECT)
struct timeval tv;
fd_set foofd;
@@ -1088,8 +1046,10 @@ zlecore(void)
statusline = NULL;
vilinerange = 0;
reselectkeymap();
- selectlocalmap(NULL);
+ selectlocalmap(invicmdmode() && region_active && (km = openkeymap("visual"))
+ ? km : NULL);
bindk = getkeycmd();
+ selectlocalmap(NULL);
if (bindk) {
if (!zlell && isfirstln && !(zlereadflags & ZLRF_IGNOREEOF) &&
lastchar == eofchar) {
@@ -1115,7 +1075,7 @@ zlecore(void)
DECCS();
handleundo();
} else {
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
break;
}
#ifdef HAVE_POLL
@@ -1273,6 +1233,10 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
zleactive = 1;
resetneeded = 1;
+ /*
+ * Start of the main zle read.
+ * Fully reset error conditions, including user interrupt.
+ */
errflag = retflag = 0;
lastcol = -1;
initmodifier(&zmod);
@@ -1289,7 +1253,9 @@ zleread(char **lp, char **rp, int flags, int context, char *init, char *finish)
zlecore();
if (errflag)
- setsparam("ZLE_LINE_ABORTED", zlegetline(NULL, NULL));
+ setsparam((zlecontext == ZLCON_VARED) ?
+ "ZLE_VARED_ABORTED" :
+ "ZLE_LINE_ABORTED", zlegetline(NULL, NULL));
if (done && !exit_pending && !errflag)
zlecallhook(finish, NULL);
@@ -1698,7 +1664,7 @@ bin_vared(char *name, char **args, Options ops, UNUSED(int func))
}
if (!t || errflag) {
/* error in editing */
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
breaks = obreaks;
if (t)
zsfree(t);
@@ -1818,7 +1784,7 @@ recursiveedit(UNUSED(char **args))
zrefresh();
zlecore();
- locerror = errflag;
+ locerror = errflag ? 1 : 0;
errflag = done = eofsent = 0;
return locerror;
@@ -2128,7 +2094,7 @@ finish_(UNUSED(Module m))
free(kring[i].buf);
zfree(kring, kringsize * sizeof(struct cutbuffer));
}
- for(i = 35; i--; )
+ for(i = 36; i--; )
zfree(vibuf[i].buf, vibuf[i].len);
/* editor entry points */
diff --git a/Src/Zle/zle_misc.c b/Src/Zle/zle_misc.c
index 9bc1cf6f5..4669ef2ad 100644
--- a/Src/Zle/zle_misc.c
+++ b/Src/Zle/zle_misc.c
@@ -47,13 +47,13 @@ doinsert(ZLE_STRING_T zstr, int len)
iremovesuffix(c1, 0);
invalidatelist();
- if (insmode)
+ /* In overwrite mode, don't replace newlines. */
+ if (insmode || zleline[zlecs] == ZWC('\n'))
spaceinline(m * len);
else
-#ifdef MULTIBYTE_SUPPORT
{
int pos = zlecs, diff, i;
-
+#ifdef MULTIBYTE_SUPPORT
/*
* Calculate the number of character positions we are
* going to be using. The algorithm is that
@@ -68,15 +68,18 @@ doinsert(ZLE_STRING_T zstr, int len)
* useful there anyway and this doesn't cause any
* particular harm.
*/
- for (i = 0, count = 0; i < len; i++) {
+ for (i = 0, count = 0; i < len * m; i++) {
if (!IS_COMBINING(zstr[i]))
count++;
}
+#else
+ count = len * m;
+#endif
/*
- * Ensure we replace a complete combining character
- * for each character we overwrite.
+ * Ensure we replace a complete combining characterfor each
+ * character we overwrite. Switch to inserting at first newline.
*/
- for (i = count; pos < zlell && i--; ) {
+ for (i = count; pos < zlell && zleline[pos] != ZWC('\n') && i--; ) {
INCPOS(pos);
}
/*
@@ -96,10 +99,6 @@ doinsert(ZLE_STRING_T zstr, int len)
shiftchars(zlecs, diff);
}
}
-#else
- if (zlecs + m * len > zlell)
- spaceinline(zlecs + m * len - zlell);
-#endif
while (m--)
for (s = zstr, count = len; count; s++, count--)
zleline[zlecs++] = *s;
@@ -440,15 +439,52 @@ killline(char **args)
}
/**/
+void
+regionlines(int *start, int *end)
+{
+ int origcs = zlecs;
+
+ UNMETACHECK();
+ if (zlecs < mark) {
+ *start = findbol();
+ zlecs = (mark > zlell) ? zlell : mark;
+ *end = findeol();
+ } else {
+ *end = findeol();
+ zlecs = mark;
+ *start = findbol();
+ }
+ zlecs = origcs;
+}
+
+/**/
int
killregion(UNUSED(char **args))
{
if (mark > zlell)
mark = zlell;
- if (mark > zlecs)
+ if (region_active == 2) {
+ int a, b;
+ regionlines(&a, &b);
+ zlecs = a;
+ region_active = 0;
+ cut(zlecs, b - zlecs, CUT_RAW);
+ shiftchars(zlecs, b - zlecs);
+ if (zlell) {
+ if (zlecs == zlell)
+ DECCS();
+ foredel(1, 0);
+ vifirstnonblank(zlenoargs);
+ }
+ } else if (mark > zlecs) {
+ if (invicmdmode())
+ INCPOS(mark);
forekill(mark - zlecs, CUT_RAW);
- else
+ } else {
+ if (invicmdmode())
+ INCCS();
backkill(zlecs - mark, CUT_FRONT|CUT_RAW);
+ }
return 0;
}
@@ -456,6 +492,7 @@ killregion(UNUSED(char **args))
int
copyregionaskill(char **args)
{
+ int start, end;
if (*args) {
int len;
ZLE_STRING_T line = stringaszleline(*args, 0, &len, NULL, NULL);
@@ -464,10 +501,16 @@ copyregionaskill(char **args)
} else {
if (mark > zlell)
mark = zlell;
- if (mark > zlecs)
- cut(zlecs, mark - zlecs, 0);
- else
- cut(mark, zlecs - mark, CUT_FRONT);
+ if (mark > zlecs) {
+ start = zlecs;
+ end = mark;
+ } else {
+ start = mark;
+ end = zlecs;
+ }
+ if (invicmdmode())
+ INCPOS(end);
+ cut(start, end - start, mark > zlecs ? 0 : CUT_FRONT);
}
return 0;
}
@@ -475,8 +518,10 @@ copyregionaskill(char **args)
/*
* kct: index into kill ring, or -1 for original cutbuffer of yank.
* yankb, yanke: mark the start and end of last yank in editing buffer.
+ * yankcs marks the cursor position preceding the last yank
*/
-static int kct, yankb, yanke;
+static int kct, yankb, yanke, yankcs;
+
/* The original cutbuffer, either cutbuf or one of the vi buffers. */
static Cutbuffer kctbuf;
@@ -494,8 +539,7 @@ yank(UNUSED(char **args))
kctbuf = &cutbuf;
if (!kctbuf->buf)
return 1;
- mark = zlecs;
- yankb = zlecs;
+ yankb = yankcs = mark = zlecs;
while (n--) {
kct = -1;
spaceinline(kctbuf->len);
@@ -506,11 +550,140 @@ yank(UNUSED(char **args))
return 0;
}
+/* position: 0 is before, 1 after, 2 split the line */
+static void pastebuf(Cutbuffer buf, int mult, int position)
+{
+ int cc;
+ if (buf->flags & CUTBUFFER_LINE) {
+ if (position == 2) {
+ if (!zlecs)
+ position = 0;
+ else if (zlecs == zlell)
+ position = 1;
+ }
+ if (position == 2) {
+ yankb = zlecs;
+ spaceinline(buf->len + 2);
+ zleline[zlecs++] = ZWC('\n');
+ ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
+ zlecs += buf->len;
+ zleline[zlecs] = ZWC('\n');
+ yanke = zlecs + 1;
+ } else if (position != 0) {
+ yankb = zlecs = findeol();
+ spaceinline(buf->len + 1);
+ zleline[zlecs++] = ZWC('\n');
+ yanke = zlecs + buf->len;
+ ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
+ } else {
+ yankb = zlecs = findbol();
+ spaceinline(buf->len + 1);
+ ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
+ yanke = zlecs + buf->len + 1;
+ zleline[zlecs + buf->len] = ZWC('\n');
+ }
+ vifirstnonblank(zlenoargs);
+ } else {
+ if (position == 1 && zlecs != findeol())
+ INCCS();
+ yankb = zlecs;
+ cc = buf->len;
+ while (mult--) {
+ spaceinline(cc);
+ ZS_memcpy(zleline + zlecs, buf->buf, cc);
+ zlecs += cc;
+ }
+ yanke = zlecs;
+ if (zlecs)
+ DECCS();
+ }
+}
+
+/**/
+int
+viputbefore(UNUSED(char **args))
+{
+ int n = zmult;
+
+ startvichange(-1);
+ if (n < 0 || zmod.flags & MOD_NULL)
+ return 1;
+ if (zmod.flags & MOD_VIBUF)
+ kctbuf = &vibuf[zmod.vibuf];
+ else
+ kctbuf = &cutbuf;
+ if (!kctbuf->buf)
+ return 1;
+ kct = -1;
+ yankcs = zlecs;
+ pastebuf(kctbuf, n, 0);
+ return 0;
+}
+
+/**/
+int
+viputafter(UNUSED(char **args))
+{
+ int n = zmult;
+
+ startvichange(-1);
+ if (n < 0 || zmod.flags & MOD_NULL)
+ return 1;
+ if (zmod.flags & MOD_VIBUF)
+ kctbuf = &vibuf[zmod.vibuf];
+ else
+ kctbuf = &cutbuf;
+ if (!kctbuf->buf)
+ return 1;
+ kct = -1;
+ yankcs = zlecs;
+ pastebuf(kctbuf, n, 1);
+ return 0;
+}
+
+/**/
+int
+putreplaceselection(UNUSED(char **args))
+{
+ int n = zmult;
+ struct cutbuffer prevbuf;
+ Cutbuffer putbuf;
+ int clear = 0;
+ int pos = 2;
+
+ startvichange(-1);
+ if (n < 0 || zmod.flags & MOD_NULL)
+ return 1;
+ putbuf = (zmod.flags & MOD_VIBUF) ? &vibuf[zmod.vibuf] : &cutbuf;
+ if (!putbuf->buf)
+ return 1;
+ memcpy(&prevbuf, putbuf, sizeof(prevbuf));
+
+ /* if "9 was specified, prevent killregion from freeing it */
+ if (zmod.vibuf == 35) {
+ putbuf->buf = 0;
+ clear = 1;
+ }
+
+ zmod.flags = 0; /* flags apply to paste not kill */
+ if (region_active == 2 && prevbuf.flags & CUTBUFFER_LINE) {
+ int a, b;
+ regionlines(&a, &b);
+ pos = (b == zlell);
+ }
+ killregion(zlenoargs);
+
+ pastebuf(&prevbuf, n, pos);
+ if (clear)
+ free(prevbuf.buf);
+ return 0;
+}
+
/**/
int
yankpop(UNUSED(char **args))
{
- int cc, kctstart = kct;
+ int kctstart = kct;
Cutbuffer buf;
if (!(lastcmd & ZLE_YANK) || !kring || !kctbuf) {
@@ -557,11 +730,8 @@ yankpop(UNUSED(char **args))
zlecs = yankb;
foredel(yanke - yankb, CUT_RAW);
- cc = buf->len;
- spaceinline(cc);
- ZS_memcpy(zleline + zlecs, buf->buf, cc);
- zlecs += cc;
- yanke = zlecs;
+ zlecs = yankcs;
+ pastebuf(buf, 1, !!(lastcmd & ZLE_YANKAFTER));
return 0;
}
@@ -871,7 +1041,7 @@ copyprevshellword(UNUSED(char **args))
int
sendbreak(UNUSED(char **args))
{
- errflag = 1;
+ errflag |= ERRFLAG_ERROR|ERRFLAG_INT;
return 1;
}
@@ -881,15 +1051,25 @@ quoteregion(UNUSED(char **args))
{
ZLE_STRING_T str;
size_t len;
+ int extra = invicmdmode();
if (mark > zlell)
mark = zlell;
- if (mark < zlecs) {
+ if (region_active == 2) {
+ int a, b;
+ regionlines(&a, &b);
+ zlecs = a;
+ mark = b;
+ extra = 0;
+ } else if (mark < zlecs) {
int tmp = mark;
mark = zlecs;
zlecs = tmp;
}
- str = (ZLE_STRING_T)hcalloc((len = mark - zlecs) * ZLE_CHAR_SIZE);
+ if (extra)
+ INCPOS(mark);
+ str = (ZLE_STRING_T)hcalloc((len = mark - zlecs) *
+ ZLE_CHAR_SIZE);
ZS_memcpy(str, zleline + zlecs, len);
foredel(len, CUT_RAW);
str = makequote(str, &len);
diff --git a/Src/Zle/zle_move.c b/Src/Zle/zle_move.c
index 7312b3f20..d751c4333 100644
--- a/Src/Zle/zle_move.c
+++ b/Src/Zle/zle_move.c
@@ -509,6 +509,55 @@ exchangepointandmark(UNUSED(char **args))
/**/
int
+visualmode(UNUSED(char **args))
+{
+ if (virangeflag) {
+ prefixflag = 1;
+ zmod.flags &= ~MOD_LINE;
+ zmod.flags |= MOD_CHAR;
+ return 0;
+ }
+ switch (region_active) {
+ case 1:
+ region_active = 0;
+ break;
+ case 0:
+ mark = zlecs;
+ /* fall through */
+ case 2:
+ region_active = 1;
+ break;
+ }
+ return 0;
+}
+
+/**/
+int
+visuallinemode(UNUSED(char **args))
+{
+ if (virangeflag) {
+ prefixflag = 1;
+ zmod.flags &= ~MOD_CHAR;
+ zmod.flags |= MOD_LINE;
+ return 0;
+ }
+ switch (region_active) {
+ case 2:
+ region_active = 0;
+ break;
+ case 0:
+ mark = zlecs;
+ /* fall through */
+ case 1:
+ region_active = 2;
+ break;
+ }
+ return 0;
+}
+
+
+/**/
+int
vigotocolumn(UNUSED(char **args))
{
int x, y, n = zmult;
@@ -538,7 +587,8 @@ vimatchbracket(UNUSED(char **args))
if ((zlecs == zlell || zleline[zlecs] == '\n') && zlecs > 0)
DECCS();
-
+ if (virangeflag)
+ mark = zlecs;
otog:
if (zlecs == zlell || zleline[zlecs] == '\n') {
zlecs = ocs;
@@ -550,7 +600,6 @@ vimatchbracket(UNUSED(char **args))
oth = '}';
break;
case /*{*/ '}':
- virangeflag = -virangeflag;
dir = -1;
oth = '{'; /*}*/
break;
@@ -559,7 +608,6 @@ vimatchbracket(UNUSED(char **args))
oth = ')';
break;
case ')':
- virangeflag = -virangeflag;
dir = -1;
oth = '(';
break;
@@ -568,7 +616,6 @@ vimatchbracket(UNUSED(char **args))
oth = ']';
break;
case ']':
- virangeflag = -virangeflag;
dir = -1;
oth = '[';
break;
@@ -576,6 +623,8 @@ vimatchbracket(UNUSED(char **args))
INCCS();
goto otog;
}
+ if (virangeflag && dir < 0)
+ INCPOS(mark); /* include starting position when going backwards */
ct = 1;
while (zlecs >= 0 && zlecs < zlell && ct) {
if (dir < 0)
@@ -599,7 +648,7 @@ vimatchbracket(UNUSED(char **args))
int
viforwardchar(char **args)
{
- int lim = findeol() - invicmdmode();
+ int lim = findeol();
int n = zmult;
if (n < 0) {
@@ -609,6 +658,8 @@ viforwardchar(char **args)
zmult = n;
return ret;
}
+ if (invicmdmode() && !virangeflag)
+ DECPOS(lim);
if (zlecs >= lim)
return 1;
while (n-- && zlecs < lim)
diff --git a/Src/Zle/zle_params.c b/Src/Zle/zle_params.c
index 5845207fa..dc5fed4ce 100644
--- a/Src/Zle/zle_params.c
+++ b/Src/Zle/zle_params.c
@@ -198,7 +198,7 @@ set_buffer(UNUSED(Param pm), char *x)
setline(x, 0);
zsfree(x);
} else
- zlecs = zlell = 0;
+ viinsbegin = zlecs = zlell = 0;
fixsuffix();
menucmp = 0;
}
diff --git a/Src/Zle/zle_refresh.c b/Src/Zle/zle_refresh.c
index 684ac13a2..fe337993f 100644
--- a/Src/Zle/zle_refresh.c
+++ b/Src/Zle/zle_refresh.c
@@ -396,8 +396,10 @@ get_region_highlight(UNUSED(Param pm))
struct region_highlight *rhp;
/* region_highlights may not have been set yet */
- if (arrsize)
- arrsize -= N_SPECIAL_HIGHLIGHTS;
+ if (!arrsize)
+ return hmkarray(NULL);
+ arrsize -= N_SPECIAL_HIGHLIGHTS;
+ DPUTS(arrsize < 0, "arrsize is negative from n_region_highlights");
arrp = retarr = (char **)zhalloc((arrsize+1)*sizeof(char *));
/* ignore special highlighting */
@@ -449,10 +451,15 @@ set_region_highlight(UNUSED(Param pm), char **aval)
len = aval ? arrlen(aval) : 0;
if (n_region_highlights != len + N_SPECIAL_HIGHLIGHTS) {
/* no null termination, but include special highlighting at start */
- n_region_highlights = len + N_SPECIAL_HIGHLIGHTS;
+ int newsize = len + N_SPECIAL_HIGHLIGHTS;
+ int diffsize = newsize - n_region_highlights;
region_highlights = (struct region_highlight *)
zrealloc(region_highlights,
- sizeof(struct region_highlight) * n_region_highlights);
+ sizeof(struct region_highlight) * newsize);
+ if (diffsize > 0)
+ memset(region_highlights + newsize - diffsize, 0,
+ sizeof(struct region_highlight) * diffsize);
+ n_region_highlights = newsize;
}
if (!aval)
@@ -1028,6 +1035,8 @@ zrefresh(void)
/* this will create region_highlights if it's still NULL */
zle_set_highlight();
+ DPUTS(!region_highlights, "region_highlights not created");
+
/* check for region between point ($CURSOR) and mark ($MARK) */
if (region_active) {
if (zlecs <= mark) {
@@ -1037,6 +1046,15 @@ zrefresh(void)
region_highlights[0].start = mark;
region_highlights[0].end = zlecs;
}
+ if (region_active == 2) {
+ int origcs = zlecs;
+ zlecs = region_highlights[0].end;
+ region_highlights[0].end = findeol();
+ zlecs = region_highlights[0].start;
+ region_highlights[0].start = findbol();
+ zlecs = origcs;
+ } else if (invicmdmode())
+ INCPOS(region_highlights[0].end);
} else {
region_highlights[0].start = region_highlights[0].end = -1;
}
diff --git a/Src/Zle/zle_tricky.c b/Src/Zle/zle_tricky.c
index 499c4ae77..f18ad170e 100644
--- a/Src/Zle/zle_tricky.c
+++ b/Src/Zle/zle_tricky.c
@@ -634,7 +634,8 @@ docomplete(int lst)
metafy_line();
ocs = zlemetacs;
- origline = dupstring(zlemetaline);
+ zsfree(origline);
+ origline = ztrdup(zlemetaline);
origcs = zlemetacs;
origll = zlemetall;
if (!isfirstln && (chline != NULL || zle_chline != NULL)) {
@@ -662,8 +663,9 @@ docomplete(int lst)
* NOTE: get_comp_string() calls pushheap(), but not popheap(). */
noerrs = 1;
s = get_comp_string();
- DPUTS(wb < 0 || zlemetacs < wb || zlemetacs > we,
- "BUG: 0 <= wb <= zlemetacs <= we is not true!");
+ DPUTS3(wb < 0 || zlemetacs < wb || zlemetacs > we,
+ "BUG: 0 <= wb (%d) <= zlemetacs (%d) <= we (%d) is not true!",
+ wb, zlemetacs, we);
noerrs = ne;
/* For vi mode, reset the start-of-insertion pointer to the beginning *
* of the word being completed, if it is currently later. Vi itself *
@@ -696,7 +698,7 @@ docomplete(int lst)
freeheap();
/* Save the lexer state, in case the completion code uses the lexer *
* somewhere (e.g. when processing a compctl -s flag). */
- lexsave();
+ zcontext_save();
if (inwhat == IN_ENV)
lincmd = 0;
if (s) {
@@ -828,7 +830,7 @@ docomplete(int lst)
if (olst == COMP_EXPAND_COMPLETE &&
!strcmp(ol, zlemetaline)) {
zlemetacs = ocs;
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
if (!compfunc) {
char *p;
@@ -866,7 +868,7 @@ docomplete(int lst)
} else
ret = 1;
/* Reset the lexer state, pop the heap. */
- lexrestore();
+ zcontext_restore();
popheap();
dat[0] = lst;
@@ -876,6 +878,19 @@ docomplete(int lst)
active = 0;
makecommaspecial(0);
+
+ /*
+ * As a special case, we reset user interrupts here.
+ * That's because completion is an intensive piece of
+ * computation that the user might want to interrupt separately
+ * from anything else going on. If they do, they probably
+ * want to keep the line edit buffer intact.
+ *
+ * There's a race here that the user might hit ^C just
+ * after completion exited anyway, but that's inevitable.
+ */
+ errflag &= ~ERRFLAG_INT;
+
return dat[1];
}
@@ -1149,7 +1164,7 @@ get_comp_string(void)
varname = NULL;
insubscr = 0;
clwpos = -1;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
inpush(dupstrspace(linptr), 0, NULL);
strinbeg(0);
@@ -1393,7 +1408,8 @@ get_comp_string(void)
}
strinend();
inpop();
- errflag = lexflags = 0;
+ lexflags = 0;
+ errflag &= ~ERRFLAG_ERROR;
if (parbegin != -1) {
/* We are in command or process substitution if we are not in
* a $((...)). */
@@ -1406,7 +1422,7 @@ get_comp_string(void)
zlemetall -= parend;
zlemetaline[zlemetall + addedx] = '\0';
}
- lexrestore();
+ zcontext_restore();
tt = NULL;
goto start;
}
@@ -1480,12 +1496,12 @@ get_comp_string(void)
if (tmp) {
tmp = NULL;
linptr = zlemetaline;
- lexrestore();
+ zcontext_restore();
addedx = 0;
goto start;
}
noaliases = ona;
- lexrestore();
+ zcontext_restore();
return NULL;
}
@@ -1720,9 +1736,11 @@ get_comp_string(void)
for (pe = p + 2; *pe && *pe != Snull && i + (pe - p) < zlemetacs;
pe++)
;
- if (!*pe) {
+ if (*pe != Snull) {
/* no terminating Snull, can't substitute */
skipchars = 2;
+ if (*pe)
+ j = 1;
} else {
/*
* Try and substitute the $'...' expression.
@@ -1795,6 +1813,10 @@ get_comp_string(void)
* first clue how the completion system actually works.
*/
skipchars = 2;
+ /*
+ * Also pretend we're in single quotes.
+ */
+ j = 1;
}
}
}
@@ -1817,7 +1839,7 @@ get_comp_string(void)
ocs = zlemetacs;
zlemetacs = i;
foredel(skipchars, CUT_RAW);
- if ((zlemetacs = ocs) > (i -= skipchars))
+ if ((zlemetacs = ocs) > --i)
zlemetacs -= skipchars;
we -= skipchars;
}
@@ -2129,7 +2151,7 @@ get_comp_string(void)
offs = boffs;
}
}
- lexrestore();
+ zcontext_restore();
return (char *)s;
}
@@ -2769,7 +2791,7 @@ doexpandhist(void)
expanding = 1;
excs = zlemetacs;
zlemetall = zlemetacs = 0;
- lexsave();
+ zcontext_save();
/* We push ol as it will remain unchanged */
inpush(ol, 0, NULL);
strinbeg(1);
@@ -2781,7 +2803,7 @@ doexpandhist(void)
} while (tok != ENDINPUT && tok != LEXERR);
while (!lexstop)
hgetc();
- /* We have to save errflags because it's reset in lexrestore. Since *
+ /* We have to save errflags because it's reset in zcontext_restore. Since *
* noerrs was set to 1 errflag is true if there was a habort() which *
* means that the expanded string is unusable. */
err = errflag;
@@ -2789,7 +2811,7 @@ doexpandhist(void)
noaliases = ona;
strinend();
inpop();
- lexrestore();
+ zcontext_restore();
expanding = 0;
if (!err) {
@@ -2888,7 +2910,7 @@ getcurcmd(void)
int curlincmd;
char *s = NULL;
- lexsave();
+ zcontext_save();
lexflags = LEXFLAGS_ZLE;
metafy_line();
inpush(dupstrspace(zlemetaline), 0, NULL);
@@ -2910,9 +2932,9 @@ getcurcmd(void)
popheap();
strinend();
inpop();
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
unmetafy_line();
- lexrestore();
+ zcontext_restore();
return s;
}
diff --git a/Src/Zle/zle_utils.c b/Src/Zle/zle_utils.c
index 1089e274f..e4ab97a54 100644
--- a/Src/Zle/zle_utils.c
+++ b/Src/Zle/zle_utils.c
@@ -43,10 +43,10 @@ struct cutbuffer *kring;
int kringsize, kringnum;
/* Vi named cut buffers. 0-25 are the named buffers "a to "z, and *
- * 26-34 are the numbered buffer stack "1 to "9. */
+ * 26-35 are the numbered buffer stack "0 to "9. */
/**/
-struct cutbuffer vibuf[35];
+struct cutbuffer vibuf[36];
/* the line before last mod (for undo purposes) */
@@ -117,7 +117,7 @@ int
zlecharasstring(ZLE_CHAR_T inchar, char *buf)
{
#ifdef MULTIBYTE_SUPPORT
- size_t ret;
+ int ret;
char *ptr;
#ifdef __STDC_ISO_10646__
@@ -675,35 +675,42 @@ zle_restore_positions(void)
zlell = oldpos->ll;
}
- /* Count number of regions and see if the array needs resizing */
- for (nreg = 0, oldrhp = oldpos->regions;
- oldrhp;
- nreg++, oldrhp = oldrhp->next)
- ;
- if (nreg + N_SPECIAL_HIGHLIGHTS != n_region_highlights) {
- n_region_highlights = nreg + N_SPECIAL_HIGHLIGHTS;
- region_highlights = (struct region_highlight *)
- zrealloc(region_highlights,
- sizeof(struct region_highlight) * n_region_highlights);
- }
- oldrhp = oldpos->regions;
- rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
- while (oldrhp) {
- struct zle_region *nextrhp = oldrhp->next;
-
- rhp->atr = oldrhp->atr;
- rhp->flags = oldrhp->flags;
- if (zlemetaline) {
- rhp->start_meta = oldrhp->start;
- rhp->end_meta = oldrhp->end;
- } else {
- rhp->start = oldrhp->start;
- rhp->end = oldrhp->end;
+ if (oldpos->regions) {
+ /* Count number of regions and see if the array needs resizing */
+ for (nreg = 0, oldrhp = oldpos->regions;
+ oldrhp;
+ nreg++, oldrhp = oldrhp->next)
+ ;
+ if (nreg + N_SPECIAL_HIGHLIGHTS != n_region_highlights) {
+ n_region_highlights = nreg + N_SPECIAL_HIGHLIGHTS;
+ region_highlights = (struct region_highlight *)
+ zrealloc(region_highlights,
+ sizeof(struct region_highlight) * n_region_highlights);
}
+ oldrhp = oldpos->regions;
+ rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
+ while (oldrhp) {
+ struct zle_region *nextrhp = oldrhp->next;
- zfree(oldrhp, sizeof(*oldrhp));
- oldrhp = nextrhp;
- rhp++;
+ rhp->atr = oldrhp->atr;
+ rhp->flags = oldrhp->flags;
+ if (zlemetaline) {
+ rhp->start_meta = oldrhp->start;
+ rhp->end_meta = oldrhp->end;
+ } else {
+ rhp->start = oldrhp->start;
+ rhp->end = oldrhp->end;
+ }
+
+ zfree(oldrhp, sizeof(*oldrhp));
+ oldrhp = nextrhp;
+ rhp++;
+ }
+ } else if (region_highlights) {
+ zfree(region_highlights, sizeof(struct region_highlight) *
+ n_region_highlights);
+ region_highlights = NULL;
+ n_region_highlights = 0;
}
zfree(oldpos, sizeof(*oldpos));
@@ -785,6 +792,8 @@ spaceinline(int ct)
if (mark > zlecs)
mark += ct;
+ if (viinsbegin > zlecs)
+ viinsbegin = 0;
if (region_highlights) {
for (rhp = region_highlights + N_SPECIAL_HIGHLIGHTS;
@@ -914,7 +923,7 @@ cut(int i, int ct, int flags)
void
cuttext(ZLE_STRING_T line, int ct, int flags)
{
- if (!ct)
+ if (!(ct || vilinerange) || zmod.flags & MOD_NULL)
return;
UNMETACHECK();
@@ -941,17 +950,23 @@ cuttext(ZLE_STRING_T line, int ct, int flags)
ZS_memcpy(b->buf + len, line, ct);
b->len = len + ct;
}
- return;
- } else {
- /* Save in "1, shifting "1-"8 along to "2-"9 */
- int n;
- free(vibuf[34].buf);
- for(n=34; n>26; n--)
- vibuf[n] = vibuf[n-1];
+ } else if (flags & CUT_YANK) {
+ /* Save in "0 */
+ free(vibuf[26].buf);
vibuf[26].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE);
ZS_memcpy(vibuf[26].buf, line, ct);
vibuf[26].len = ct;
vibuf[26].flags = vilinerange ? CUTBUFFER_LINE : 0;
+ } else {
+ /* Save in "1, shifting "1-"8 along to "2-"9 */
+ int n;
+ free(vibuf[35].buf);
+ for(n=35; n>27; n--)
+ vibuf[n] = vibuf[n-1];
+ vibuf[27].buf = (ZLE_STRING_T)zalloc(ct * ZLE_CHAR_SIZE);
+ ZS_memcpy(vibuf[27].buf, line, ct);
+ vibuf[27].len = ct;
+ vibuf[27].flags = vilinerange ? CUTBUFFER_LINE : 0;
}
if (!cutbuf.buf) {
cutbuf.buf = (ZLE_STRING_T)zalloc(ZLE_CHAR_SIZE);
@@ -981,8 +996,9 @@ cuttext(ZLE_STRING_T line, int ct, int flags)
cutbuf.buf = s;
cutbuf.len += ct;
} else {
+ /* don't alloc 0 bytes; length 0 occurs for blank lines in vi mode */
cutbuf.buf = realloc((char *)cutbuf.buf,
- (cutbuf.len + ct) * ZLE_CHAR_SIZE);
+ (cutbuf.len + (ct ? ct : 1)) * ZLE_CHAR_SIZE);
ZS_memcpy(cutbuf.buf + cutbuf.len, line, ct);
cutbuf.len += ct;
}
@@ -1098,6 +1114,7 @@ setline(char *s, int flags)
*/
free(zleline);
+ viinsbegin = 0;
zleline = stringaszleline(scp, 0, &zlell, &linesz, NULL);
if ((flags & ZSL_TOEND) && (zlecs = zlell) && invicmdmode())
@@ -1356,7 +1373,6 @@ int
handlefeep(UNUSED(char **args))
{
zbeep();
- region_active = 0;
return 0;
}
@@ -1386,7 +1402,8 @@ static struct change *nextchanges, *endnextchanges;
/* incremented to provide a unique change number */
-static zlong undo_changeno;
+/**/
+zlong undo_changeno;
/* If non-zero, the last increment to undo_changeno was for the variable */
@@ -1659,8 +1676,7 @@ splitundo(char **args)
{
if (vistartchange >= 0) {
mergeundo();
- vistartchange = (curchange && curchange->prev) ?
- curchange->prev->changeno : 0;
+ vistartchange = undo_changeno;
}
handleundo();
return 0;
@@ -1706,7 +1722,8 @@ zlecallhook(char *name, char *arg)
execzlefunc(thingy, args, 1);
unrefthingy(thingy);
- errflag = saverrflag;
+ /* Retain any user interrupt error status */
+ errflag = saverrflag | (errflag & ERRFLAG_INT);
retflag = savretflag;
}
diff --git a/Src/Zle/zle_vi.c b/Src/Zle/zle_vi.c
index 9e39143d0..1a11ca7d5 100644
--- a/Src/Zle/zle_vi.c
+++ b/Src/Zle/zle_vi.c
@@ -75,7 +75,7 @@ static int inrepeat, vichgrepeat;
*/
/**/
-static void
+void
startvichange(int im)
{
if (im != -1) {
@@ -109,7 +109,7 @@ startvitext(int im)
{
startvichange(im);
selectkeymap("main", 1);
- vistartchange = (curchange && curchange->prev) ? curchange->prev->changeno : 0;
+ vistartchange = undo_changeno;
viinsbegin = zlecs;
}
@@ -161,75 +161,87 @@ vigetkey(void)
static int
getvirange(int wf)
{
- int pos = zlecs, ret = 0;
+ int pos = zlecs, mpos = mark, ret = 0;
+ int visual = region_active; /* movement command might set it */
int mult1 = zmult, hist1 = histline;
Thingy k2;
- virangeflag = 1;
- wordflag = wf;
- /* Now we need to execute the movement command, to see where it *
- * actually goes. virangeflag here indicates to the movement *
- * function that it should place the cursor at the end of the *
- * range, rather than where the cursor would actually go if it *
- * were executed normally. This makes a difference to some *
- * commands, but not all. For example, if searching forward *
- * for a character, under normal circumstances the cursor lands *
- * on the character. For a range, the range must include the *
- * character, so the cursor gets placed after the character if *
- * virangeflag is set. vi-match-bracket needs to change the *
- * value of virangeflag under some circumstances, meaning that *
- * we need to change the *starting* position. */
- zmod.flags &= ~MOD_TMULT;
- do {
- vilinerange = 0;
- prefixflag = 0;
- if (!(k2 = getkeycmd()) || (k2->flags & DISABLED) ||
- k2 == Th(z_sendbreak)) {
- wordflag = 0;
- virangeflag = 0;
+ if (visual) {
+ if (!zlell)
+ return -1;
+ pos = mark;
+ vilinerange = (visual == 2);
+ region_active = 0;
+ } else {
+ virangeflag = 1;
+ wordflag = wf;
+ mark = -1;
+ /* use operator-pending keymap if one exists */
+ Keymap km = openkeymap("viopp");
+ if (km)
+ selectlocalmap(km);
+ /* Now we need to execute the movement command, to see where it *
+ * actually goes. virangeflag here indicates to the movement *
+ * function that it should place the cursor at the end of the *
+ * range, rather than where the cursor would actually go if it *
+ * were executed normally. This makes a difference to some *
+ * commands, but not all. For example, if searching forward *
+ * for a character, under normal circumstances the cursor lands *
+ * on the character. For a range, the range must include the *
+ * character, so the cursor gets placed after the character if *
+ * virangeflag is set. */
+ zmod.flags &= ~MOD_TMULT;
+ do {
+ vilinerange = 0;
+ prefixflag = 0;
+ if (!(k2 = getkeycmd()) || (k2->flags & DISABLED) ||
+ k2 == Th(z_sendbreak)) {
+ wordflag = 0;
+ virangeflag = 0;
+ mark = mpos;
+ return -1;
+ }
+ /*
+ * With k2 == bindk, the command key is repeated:
+ * a number of lines is used. If the function used
+ * returns 1, we fail.
+ */
+ if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs, 1))
+ ret = -1;
+ if(vichgrepeat)
+ zmult = mult1;
+ else
+ zmult = mult1 * zmod.tmult;
+ } while(prefixflag && !ret);
+ wordflag = 0;
+ selectlocalmap(NULL);
+
+ /* It is an error to use a non-movement command to delimit the *
+ * range. We here reject the case where the command modified *
+ * the line, or selected a different history line. */
+ if (histline != hist1 || zlell != lastll || memcmp(zleline, lastline, zlell)) {
+ histline = hist1;
+ ZS_memcpy(zleline, lastline, zlell = lastll);
+ zlecs = pos;
+ mark = mpos;
return -1;
}
- /*
- * With k2 == bindk, the command key is repeated:
- * a number of lines is used. If the function used
- * returns 1, we fail.
- */
- if ((k2 == bindk) ? dovilinerange() : execzlefunc(k2, zlenoargs, 1))
- ret = -1;
- if(vichgrepeat)
- zmult = mult1;
- else
- zmult = mult1 * zmod.tmult;
- } while(prefixflag && !ret);
- wordflag = 0;
- virangeflag = 0;
-
- /* It is an error to use a non-movement command to delimit the *
- * range. We here reject the case where the command modified *
- * the line, or selected a different history line. */
- if (histline != hist1 || zlell != lastll || memcmp(zleline, lastline, zlell)) {
- histline = hist1;
- ZS_memcpy(zleline, lastline, zlell = lastll);
- zlecs = pos;
- return -1;
- }
- /* Can't handle an empty file. Also, if the movement command *
- * failed, or didn't move, it is an error. */
- if (!zlell || (zlecs == pos && virangeflag != 2) || ret == -1)
- return -1;
+ /* Can't handle an empty file. Also, if the movement command *
+ * failed, or didn't move, it is an error. */
+ if (!zlell || (zlecs == pos && (mark == -1 || mark == zlecs) &&
+ virangeflag != 2) || ret == -1) {
+ mark = mpos;
+ return -1;
+ }
+ virangeflag = 0;
- /* vi-match-bracket changes the value of virangeflag when *
- * moving to the opening bracket, meaning that we need to *
- * change the *starting* position. */
- if(virangeflag == -1)
- {
- int origcs = zlecs;
- zlecs = pos;
- INCCS();
- pos = zlecs;
- zlecs = origcs;
+ /* if the mark has moved, ignore the original cursor position *
+ * and use the mark. */
+ if (mark != -1)
+ pos = mark;
}
+ mark = mpos;
/* Get the range the right way round. zlecs is placed at the *
* start of the range, and pos (the return value of this *
@@ -240,17 +252,31 @@ getvirange(int wf)
pos = tmp;
}
+ /* visual selection mode needs to include additional position */
+ if (visual == 1 && invicmdmode())
+ INCPOS(pos);
+
/* Was it a line-oriented move? If so, the command will have set *
* the vilinerange flag. In this case, entire lines are taken, *
* rather than just the sequence of characters delimited by pos *
- * and zlecs. The terminating newline is left out of the range, *
+ * and zlecs. The terminating newline is left out of the range, *
* which the real command must deal with appropriately. At this *
* point we just need to make the range encompass entire lines. */
- if(vilinerange) {
+ vilinerange = (zmod.flags & MOD_LINE) ||
+ (vilinerange && !(zmod.flags & MOD_CHAR));
+ if (vilinerange) {
int newcs = findbol();
+ lastcol = zlecs - newcs;
zlecs = pos;
pos = findeol();
zlecs = newcs;
+ } else if (!visual) {
+ /* for a character-wise move don't include a newline at the *
+ * end of the range */
+ int prev = pos;
+ DECPOS(prev);
+ if (zleline[prev] == ZWC('\n'))
+ pos = prev;
}
return pos;
}
@@ -348,6 +374,7 @@ videlete(UNUSED(char **args))
forekill(c2 - zlecs, CUT_RAW);
ret = 0;
if (vilinerange && zlell) {
+ lastcol = -1;
if (zlecs == zlell)
DECCS();
foredel(1, 0);
@@ -365,6 +392,7 @@ videletechar(char **args)
int n = zmult;
startvichange(-1);
+
/* handle negative argument */
if (n < 0) {
int ret;
@@ -401,7 +429,7 @@ vichange(UNUSED(char **args))
forekill(c2 - zlecs, CUT_RAW);
selectkeymap("main", 1);
viinsbegin = zlecs;
- vistartchange = (curchange && curchange->prev) ? curchange->prev->changeno : 0;
+ vistartchange = undo_changeno;
}
return ret;
}
@@ -418,12 +446,16 @@ visubstitute(UNUSED(char **args))
/* it is an error to be on the end of line */
if (zlecs == zlell || zleline[zlecs] == '\n')
return 1;
- /* Put argument into the acceptable range -- it is not an error to *
- * specify a greater count than the number of available characters. */
- if (n > findeol() - zlecs)
- n = findeol() - zlecs;
- /* do the substitution */
- forekill(n, CUT_RAW);
+ if (region_active) {
+ killregion(zlenoargs);
+ } else {
+ /* Put argument into the acceptable range -- it is not an error to *
+ * specify a greater count than the number of available characters. */
+ if (n > findeol() - zlecs)
+ n = findeol() - zlecs;
+ /* do the substitution */
+ forekill(n, CUT_RAW);
+ }
startvitext(1);
return 0;
}
@@ -432,7 +464,15 @@ visubstitute(UNUSED(char **args))
int
vichangeeol(UNUSED(char **args))
{
- forekill(findeol() - zlecs, CUT_RAW);
+ int a, b;
+ if (region_active) {
+ regionlines(&a, &b);
+ zlecs = a;
+ region_active = 0;
+ cut(zlecs, b - zlecs, CUT_RAW);
+ shiftchars(zlecs, b - zlecs);
+ } else
+ forekill(findeol() - zlecs, CUT_RAW);
startvitext(1);
return 0;
}
@@ -449,15 +489,30 @@ vichangewholeline(char **args)
int
viyank(UNUSED(char **args))
{
- int oldcs = zlecs, c2, ret = 1;
+ int c2, ret = 1;
startvichange(1);
if ((c2 = getvirange(0)) != -1) {
- cut(zlecs, c2 - zlecs, 0);
+ cut(zlecs, c2 - zlecs, CUT_YANK);
ret = 0;
}
vichgflag = 0;
- zlecs = oldcs;
+ /* cursor now at the start of the range yanked. For line mode
+ * restore the column position */
+ if (vilinerange && lastcol != -1) {
+ int x = findeol();
+
+ if ((zlecs += lastcol) >= x) {
+ zlecs = x;
+ if (zlecs > findbol() && invicmdmode())
+ DECCS();
+ }
+#ifdef MULTIBYTE_SUPPORT
+ else
+ CCRIGHT();
+#endif
+ lastcol = -1;
+ }
return ret;
}
@@ -470,7 +525,7 @@ viyankeol(UNUSED(char **args))
startvichange(-1);
if (x == zlecs)
return 1;
- cut(zlecs, x - zlecs, 0);
+ cut(zlecs, x - zlecs, CUT_YANK);
return 0;
}
@@ -492,7 +547,7 @@ viyankwholeline(UNUSED(char **args))
zlecs = findeol() + 1;
}
vilinerange = 1;
- cut(bol, zlecs - bol - 1, 0);
+ cut(bol, zlecs - bol - 1, CUT_YANK);
zlecs = oldcs;
return 0;
}
@@ -526,16 +581,40 @@ vireplacechars(UNUSED(char **args))
int n = zmult, fail = 0, newchars = 0;
if (n > 0) {
- int pos = zlecs;
- while (n-- > 0) {
- if (pos == zlell || zleline[pos] == ZWC('\n')) {
- fail = 1;
- break;
+ if (region_active) {
+ int a, b;
+ if (region_active == 1) {
+ if (mark > zlecs) {
+ a = zlecs;
+ b = mark;
+ } else {
+ a = mark;
+ b = zlecs;
+ }
+ INCPOS(b);
+ } else
+ regionlines(&a, &b);
+ zlecs = a;
+ if (b > zlell)
+ b = zlell;
+ n = b - a;
+ while (a < b) {
+ newchars++;
+ INCPOS(a);
+ }
+ region_active = 0;
+ } else {
+ int pos = zlecs;
+ while (n-- > 0) {
+ if (pos == zlell || zleline[pos] == ZWC('\n')) {
+ fail = 1;
+ break;
+ }
+ newchars++;
+ INCPOS(pos);
}
- newchars++;
- INCPOS(pos);
+ n = pos - zlecs;
}
- n = pos - zlecs;
}
startvichange(1);
/* check argument range */
@@ -567,6 +646,8 @@ vireplacechars(UNUSED(char **args))
* buffer offset.
* Use shiftchars so as not to adjust the cursor position;
* we are overwriting anything that remains directly.
+ * With a selection this will replace newlines which vim
+ * doesn't do but this simplifies things a lot.
*/
if (n > newchars)
shiftchars(zlecs, n - newchars);
@@ -675,8 +756,11 @@ viindent(UNUSED(char **args))
{
int oldcs = zlecs, c2;
- /* get the range */
startvichange(1);
+ /* force line range */
+ if (region_active == 1)
+ region_active = 2;
+ /* get the range */
if ((c2 = getvirange(0)) == -1) {
vichgflag = 0;
return 1;
@@ -689,10 +773,14 @@ viindent(UNUSED(char **args))
}
oldcs = zlecs;
/* add a tab to the beginning of each line within range */
- while (zlecs < c2) {
- spaceinline(1);
- zleline[zlecs] = '\t';
- zlecs = findeol() + 1;
+ while (zlecs <= c2 + 1) {
+ if (zleline[zlecs] == '\n') { /* leave blank lines alone */
+ ++zlecs;
+ } else {
+ spaceinline(1);
+ zleline[zlecs] = '\t';
+ zlecs = findeol() + 1;
+ }
}
/* go back to the first line of the range */
zlecs = oldcs;
@@ -706,8 +794,11 @@ viunindent(UNUSED(char **args))
{
int oldcs = zlecs, c2;
- /* get the range */
startvichange(1);
+ /* force line range */
+ if (region_active == 1)
+ region_active = 2;
+ /* get the range */
if ((c2 = getvirange(0)) == -1) {
vichgflag = 0;
return 1;
@@ -739,6 +830,7 @@ vibackwarddeletechar(char **args)
if (invicmdmode())
startvichange(-1);
+
/* handle negative argument */
if (n < 0) {
int ret;
@@ -776,95 +868,44 @@ vikillline(UNUSED(char **args))
/**/
int
-viputbefore(UNUSED(char **args))
+vijoin(UNUSED(char **args))
{
- Cutbuffer buf = &cutbuf;
+ int x, pos;
int n = zmult;
+ int visual = region_active;
startvichange(-1);
- if (n < 0)
- return 1;
- if (zmod.flags & MOD_VIBUF)
- buf = &vibuf[zmod.vibuf];
- if (!buf->buf)
+ if (n < 1)
return 1;
- if(buf->flags & CUTBUFFER_LINE) {
- zlecs = findbol();
- spaceinline(buf->len + 1);
- ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
- zleline[zlecs + buf->len] = ZWC('\n');
- vifirstnonblank(zlenoargs);
- } else {
- while (n--) {
- spaceinline(buf->len);
- ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
- zlecs += buf->len;
+ if (visual && zlecs > mark) {
+ exchangepointandmark(zlenoargs);
+ x = findeol();
+ if (x >= mark) {
+ exchangepointandmark(zlenoargs);
+ return 1;
}
- if (zlecs)
- DECCS();
- }
- return 0;
-}
-
-/**/
-int
-viputafter(UNUSED(char **args))
-{
- Cutbuffer buf = &cutbuf;
- int n = zmult;
-
- startvichange(-1);
- if (n < 0)
- return 1;
- if (zmod.flags & MOD_VIBUF)
- buf = &vibuf[zmod.vibuf];
- if (!buf->buf)
+ } else if ((x = findeol()) == zlell || (visual && x >= mark))
return 1;
- if(buf->flags & CUTBUFFER_LINE) {
- zlecs = findeol();
- spaceinline(buf->len + 1);
- zleline[zlecs++] = ZWC('\n');
- ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
- vifirstnonblank(zlenoargs);
- } else {
- if (zlecs != findeol())
- INCCS();
- while (n--) {
- spaceinline(buf->len);
- ZS_memcpy(zleline + zlecs, buf->buf, buf->len);
- zlecs += buf->len;
- }
- if (zlecs)
- DECCS();
- }
- return 0;
-}
-
-/**/
-int
-vijoin(UNUSED(char **args))
-{
- int x, pos;
- startvichange(-1);
- if ((x = findeol()) == zlell)
- return 1;
- zlecs = x + 1;
- pos = zlecs;
- for (; zlecs != zlell && ZC_iblank(zleline[zlecs]); INCPOS(zlecs))
- ;
- x = 1 + (zlecs - pos);
- backdel(x, CUT_RAW);
- if (zlecs) {
- int pos = zlecs;
- DECPOS(pos);
- if (ZC_iblank(zleline[pos])) {
- zlecs = pos;
- return 0;
+ do {
+ zlecs = x + 1;
+ pos = zlecs;
+ for (; zlecs != zlell && ZC_iblank(zleline[zlecs]); INCPOS(zlecs))
+ ;
+ x = 1 + (zlecs - pos);
+ backdel(x, CUT_RAW);
+ if (zlecs) {
+ int pos = zlecs;
+ DECPOS(pos);
+ if (ZC_iblank(zleline[pos])) {
+ zlecs = pos;
+ continue;
+ }
}
- }
- spaceinline(1);
- zleline[zlecs] = ZWC(' ');
+ spaceinline(1);
+ zleline[zlecs] = ZWC(' ');
+ } while (!((!visual && --n < 2) || (x = findeol()) == zlell || (visual && x >= mark)));
+
return 0;
}
@@ -878,6 +919,8 @@ viswapcase(UNUSED(char **args))
if (n < 1)
return 1;
eol = findeol();
+ if (zlecs == eol)
+ return 1;
while (zlecs < eol && n--) {
if (ZC_ilower(zleline[zlecs]))
zleline[zlecs] = ZC_toupper(zleline[zlecs]);
@@ -905,14 +948,26 @@ vicapslockpanic(UNUSED(char **args))
/**/
int
-visetbuffer(UNUSED(char **args))
+visetbuffer(char **args)
{
ZLE_INT_T ch;
- if ((zmod.flags & MOD_VIBUF) ||
- (((ch = getfullchar(0)) < ZWC('1') || ch > ZWC('9')) &&
+ if (*args) {
+ ch = **args;
+ if (args[1] || (ch && (*args)[1]))
+ return 1;
+ } else {
+ ch = getfullchar(0);
+ }
+ if (ch == ZWC('_')) {
+ zmod.flags |= MOD_NULL;
+ prefixflag = 1;
+ return 0;
+ } else
+ zmod.flags &= ~MOD_NULL;
+ if ((ch < ZWC('0') || ch > ZWC('9')) &&
(ch < ZWC('a') || ch > ZWC('z')) &&
- (ch < ZWC('A') || ch > ZWC('Z'))))
+ (ch < ZWC('A') || ch > ZWC('Z')))
return 1;
if (ch >= ZWC('A') && ch <= ZWC('Z')) /* needed in cut() */
zmod.flags |= MOD_VIAPP;
@@ -920,8 +975,8 @@ visetbuffer(UNUSED(char **args))
zmod.flags &= ~MOD_VIAPP;
/* FIXME how portable is it for multibyte encoding? */
zmod.vibuf = ZC_tolower(ch);
- if (ch >= ZWC('1') && ch <= ZWC('9'))
- zmod.vibuf += - (int)ZWC('1') + 26;
+ if (ch >= ZWC('0') && ch <= ZWC('9'))
+ zmod.vibuf += - (int)ZWC('0') + 26;
else
zmod.vibuf += - (int)ZWC('a');
zmod.flags |= MOD_VIBUF;
diff --git a/Src/Zle/zle_word.c b/Src/Zle/zle_word.c
index e59304ecd..2e6d75e86 100644
--- a/Src/Zle/zle_word.c
+++ b/Src/Zle/zle_word.c
@@ -80,16 +80,21 @@ viforwardword(char **args)
return ret;
}
while (n--) {
+ int nl;
if (Z_vialnum(zleline[zlecs]))
while (zlecs != zlell && Z_vialnum(zleline[zlecs]))
INCCS();
else
- while (zlecs != zlell && !Z_vialnum(zleline[zlecs]) && !ZC_iblank(zleline[zlecs]))
+ while (zlecs != zlell && !Z_vialnum(zleline[zlecs]) &&
+ !ZC_inblank(zleline[zlecs]))
INCCS();
if (wordflag && !n)
return 0;
- while (zlecs != zlell && ZC_inblank(zleline[zlecs]))
+ nl = (zleline[zlecs] == ZWC('\n'));
+ while (zlecs != zlell && nl < 2 && ZC_inblank(zleline[zlecs])) {
INCCS();
+ nl += (zleline[zlecs] == ZWC('\n'));
+ }
}
return 0;
}
@@ -108,12 +113,16 @@ viforwardblankword(char **args)
return ret;
}
while (n--) {
- while (zlecs != zlell && !ZC_iblank(zleline[zlecs]))
+ int nl;
+ while (zlecs != zlell && !ZC_inblank(zleline[zlecs]))
INCCS();
if (wordflag && !n)
return 0;
- while (zlecs != zlell && ZC_iblank(zleline[zlecs]))
+ nl = (zleline[zlecs] == ZWC('\n'));
+ while (zlecs != zlell && nl < 2 && ZC_inblank(zleline[zlecs])) {
INCCS();
+ nl += (zleline[zlecs] == ZWC('\n'));
+ }
}
return 0;
}
@@ -148,20 +157,25 @@ viforwardblankwordend(UNUSED(char **args))
{
int n = zmult;
- if (n < 0)
- return 1;
+ if (n < 0) {
+ int ret;
+ zmult = -n;
+ ret = viforwardblankwordend(args);
+ zmult = n;
+ return ret;
+ }
while (n--) {
while (zlecs != zlell) {
int pos = zlecs;
INCPOS(pos);
- if (!ZC_iblank(zleline[pos]))
+ if (!ZC_inblank(zleline[pos]))
break;
zlecs = pos;
}
while (zlecs != zlell) {
int pos = zlecs;
INCPOS(pos);
- if (ZC_iblank(zleline[pos]))
+ if (ZC_inblank(zleline[pos]))
break;
zlecs = pos;
}
@@ -180,7 +194,7 @@ viforwardwordend(char **args)
if (n < 0) {
int ret;
zmult = -n;
- ret = backwardword(args);
+ ret = vibackwardwordend(args);
zmult = n;
return ret;
}
@@ -211,7 +225,7 @@ viforwardwordend(char **args)
if (zlecs == zlell)
break;
INCPOS(pos);
- if (Z_vialnum(zleline[pos]) || ZC_iblank(zleline[pos]))
+ if (Z_vialnum(zleline[pos]) || ZC_inblank(zleline[pos]))
break;
}
}
@@ -268,16 +282,19 @@ vibackwardword(char **args)
return ret;
}
while (n--) {
+ int nl = 0;
while (zlecs) {
- int pos = zlecs;
- DECPOS(pos);
- if (!ZC_iblank(zleline[pos]))
+ DECCS();
+ if (!ZC_inblank(zleline[zlecs]))
break;
- zlecs = pos;
+ nl += (zleline[zlecs] == ZWC('\n'));
+ if (nl == 2) {
+ INCCS();
+ break;
+ }
}
if (zlecs) {
int pos = zlecs;
- DECPOS(pos);
if (Z_vialnum(zleline[pos])) {
for (;;) {
zlecs = pos;
@@ -293,7 +310,7 @@ vibackwardword(char **args)
if (zlecs == 0)
break;
DECPOS(pos);
- if (Z_vialnum(zleline[pos]) || ZC_iblank(zleline[pos]))
+ if (Z_vialnum(zleline[pos]) || ZC_inblank(zleline[pos]))
break;
}
}
@@ -316,17 +333,20 @@ vibackwardblankword(char **args)
return ret;
}
while (n--) {
+ int nl = 0;
while (zlecs) {
int pos = zlecs;
DECPOS(pos);
- if (!ZC_iblank(zleline[pos]))
+ if (!ZC_inblank(zleline[pos]))
break;
+ nl += (zleline[pos] == ZWC('\n'));
+ if (nl == 2) break;
zlecs = pos;
}
while (zlecs) {
int pos = zlecs;
DECPOS(pos);
- if (ZC_iblank(zleline[pos]))
+ if (ZC_inblank(zleline[pos]))
break;
zlecs = pos;
}
@@ -336,6 +356,62 @@ vibackwardblankword(char **args)
/**/
int
+vibackwardwordend(char **args)
+{
+ int n = zmult;
+
+ if (n < 0) {
+ int ret;
+ zmult = -n;
+ ret = viforwardwordend(args);
+ zmult = n;
+ return ret;
+ }
+ while (n-- && zlecs > 1) {
+ int start = 0;
+ if (Z_vialnum(zleline[zlecs]))
+ start = 1;
+ else if (!ZC_inblank(zleline[zlecs]))
+ start = 2;
+ DECCS();
+ while (zlecs) {
+ int same = (start != 1) && ZC_iblank(zleline[zlecs]);
+ if (start)
+ same |= Z_vialnum(zleline[zlecs]);
+ if (same == (start == 2))
+ break;
+ DECCS();
+ }
+ while (zlecs && ZC_iblank(zleline[zlecs]))
+ DECCS();
+ }
+ return 0;
+}
+
+/**/
+int
+vibackwardblankwordend(char **args)
+{
+ int n = zmult;
+
+ if (n < 0) {
+ int ret;
+ zmult = -n;
+ ret = viforwardblankwordend(args);
+ zmult = n;
+ return ret;
+ }
+ while (n--) {
+ while (zlecs && !ZC_inblank(zleline[zlecs]))
+ DECCS();
+ while (zlecs && ZC_inblank(zleline[zlecs]))
+ DECCS();
+ }
+ return 0;
+}
+
+/**/
+int
emacsbackwardword(char **args)
{
int n = zmult;
@@ -629,7 +705,6 @@ transposewords(UNUSED(char **args))
DECPOS(pos);
if (zleline[pos] == ZWC('\n'))
return 1;
- x = pos;
}
for (p4 = x; p4 != zlell && ZC_iword(zleline[p4]); INCPOS(p4))
;
diff --git a/Src/builtin.c b/Src/builtin.c
index 4a10c7dd1..ffde5c916 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -119,7 +119,7 @@ static struct builtin builtins[] =
BUILTIN("times", BINF_PSPECIAL, bin_times, 0, 0, 0, NULL, NULL),
BUILTIN("trap", BINF_PSPECIAL | BINF_HANDLES_OPTS, bin_trap, 0, -1, 0, NULL, NULL),
BUILTIN("true", 0, bin_true, 0, -1, 0, NULL, NULL),
- BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsw", "v"),
+ BUILTIN("type", 0, bin_whence, 0, -1, 0, "ampfsSw", "v"),
BUILTIN("typeset", BINF_PLUSOPTS | BINF_MAGICEQUALS | BINF_PSPECIAL, bin_typeset, 0, -1, 0, "AE:%F:%HL:%R:%TUZ:%afghi:%klprtuxmz", NULL),
BUILTIN("umask", 0, bin_umask, 0, 1, 0, "S", NULL),
BUILTIN("unalias", 0, bin_unhash, 1, -1, 0, "ms", "a"),
@@ -128,9 +128,9 @@ static struct builtin builtins[] =
BUILTIN("unset", BINF_PSPECIAL, bin_unset, 1, -1, 0, "fmv", NULL),
BUILTIN("unsetopt", 0, bin_setopt, 0, -1, BIN_UNSETOPT, NULL, NULL),
BUILTIN("wait", 0, bin_fg, 0, -1, BIN_WAIT, NULL, NULL),
- BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsw", NULL),
- BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsw", "ca"),
- BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsw", "c"),
+ BUILTIN("whence", 0, bin_whence, 0, -1, 0, "acmpvfsSw", NULL),
+ BUILTIN("where", 0, bin_whence, 0, -1, 0, "pmsSw", "ca"),
+ BUILTIN("which", 0, bin_whence, 0, -1, 0, "ampsSw", "c"),
BUILTIN("zmodload", 0, bin_zmodload, 0, -1, 0, "AFRILP:abcfdilmpue", NULL),
BUILTIN("zcompile", 0, bin_zcompile, 0, -1, 0, "tUMRcmzka", NULL),
};
@@ -422,7 +422,7 @@ execbuiltin(LinkList args, Builtin bn)
argc -= argv - argarr;
if (errflag) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
return 1;
}
@@ -719,7 +719,7 @@ bin_dirs(UNUSED(char *name), char **argv, Options ops, UNUSED(int func))
for (node = firstnode(dirstack); node; incnode(node)) {
printf(fmt, pos++);
if (OPT_ISSET(ops,'l'))
- fputs(getdata(node), stdout);
+ zputs(getdata(node), stdout);
else
fprintdir(getdata(node), stdout);
@@ -1093,9 +1093,11 @@ cd_try_chdir(char *pfix, char *dest, int hard)
} else {
int pfl = strlen(pfix);
dlen = strlen(pwd);
-
+ if (dlen == 1 && *pwd == '/')
+ dlen = 0;
buf = zalloc(dlen + pfl + strlen(dest) + 3);
- strcpy(buf, pwd);
+ if (dlen)
+ strcpy(buf, pwd);
buf[dlen] = '/';
strcpy(buf + dlen + 1, pfix);
buf[dlen + 1 + pfl] = '/';
@@ -1156,9 +1158,11 @@ cd_new_pwd(int func, LinkNode dir, int quiet)
zsfree(getlinknode(dirstack));
if (chasinglinks) {
- s = new_pwd;
- new_pwd = findpwd(s);
- zsfree(s);
+ s = findpwd(new_pwd);
+ if (s) {
+ zsfree(new_pwd);
+ new_pwd = s;
+ }
}
if (isset(PUSHDIGNOREDUPS)) {
LinkNode n;
@@ -1363,10 +1367,19 @@ bin_fc(char *nam, char **argv, Options ops, int func)
if (*argv) {
hf = *argv++;
if (*argv) {
- hs = zstrtol(*argv++, NULL, 10);
- if (*argv)
- shs = zstrtol(*argv++, NULL, 10);
- else
+ char *check;
+ hs = zstrtol(*argv++, &check, 10);
+ if (*check) {
+ zwarnnam("fc", "HISTSIZE must be an integer");
+ return 1;
+ }
+ if (*argv) {
+ shs = zstrtol(*argv++, &check, 10);
+ if (*check) {
+ zwarnnam("fc", "SAVEHIST must be an integer");
+ return 1;
+ }
+ } else
shs = hs;
if (*argv) {
zwarnnam("fc", "too many arguments");
@@ -1855,7 +1868,7 @@ typeset_setbase(const char *name, Param pm, Options ops, int on, int always)
if (arg) {
char *eptr;
- pm->base = (int)zstrtol(arg, &eptr, 10);
+ int base = (int)zstrtol(arg, &eptr, 10);
if (*eptr) {
if (on & PM_INTEGER)
zwarnnam(name, "bad base value: %s", arg);
@@ -1863,11 +1876,12 @@ typeset_setbase(const char *name, Param pm, Options ops, int on, int always)
zwarnnam(name, "bad precision value: %s", arg);
return 1;
}
- if (pm->base < 2 || pm->base > 36) {
+ if ((on & PM_INTEGER) && (base < 2 || base > 36)) {
zwarnnam(name, "invalid base (must be 2 to 36 inclusive): %d",
- pm->base);
+ base);
return 1;
}
+ pm->base = base;
} else if (always)
pm->base = 0;
@@ -1918,15 +1932,19 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
* locallevel as an unset one we use the pm struct anyway: that's
* handled in createparam(). Here we just avoid using it for the
* present tests if it's unset.
+ *
+ * POSIXBUILTINS horror: we need to retain the 'readonly' flag
+ * of an unset parameter.
*/
- usepm = pm && !(pm->node.flags & PM_UNSET);
+ usepm = pm && (!(pm->node.flags & PM_UNSET) ||
+ (isset(POSIXBUILTINS) && (pm->node.flags & PM_READONLY)));
/*
* We need to compare types with an existing pm if special,
* even if that's unset
*/
- if (pm && (pm->node.flags & PM_SPECIAL))
- usepm = 1;
+ if (!usepm && pm && (pm->node.flags & PM_SPECIAL))
+ usepm = 2; /* indicate that we preserve the PM_UNSET flag */
/*
* Don't use an existing param if
@@ -2019,6 +2037,20 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
else if (newspecial != NS_NONE && strcmp(pname, "SECONDS") == 0)
newspecial = NS_SECONDS;
+ if (isset(POSIXBUILTINS)) {
+ /*
+ * Stricter rules about retaining readonly attribute in this case.
+ */
+ if ((on & PM_READONLY) && (!usepm || (pm->node.flags & PM_UNSET)) &&
+ !value)
+ on |= PM_UNSET;
+ else if (usepm && (pm->node.flags & PM_READONLY) &&
+ !(on & PM_READONLY)) {
+ zerr("read-only variable: %s", pm->node.nam);
+ return NULL;
+ }
+ }
+
/*
* A parameter will be local if
* 1. we are re-using an existing local parameter
@@ -2063,7 +2095,17 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
arrfixenv(pm->node.nam, x);
}
}
- pm->node.flags = (pm->node.flags | (on & ~PM_READONLY)) & ~(off | PM_UNSET);
+ if (usepm == 2) /* do not change the PM_UNSET flag */
+ pm->node.flags = (pm->node.flags | (on & ~PM_READONLY)) & ~off;
+ else {
+ /*
+ * Keep unset if using readonly in POSIX mode.
+ */
+ if (!(on & PM_READONLY) || !isset(POSIXBUILTINS))
+ off |= PM_UNSET;
+ pm->node.flags = (pm->node.flags |
+ (on & ~PM_READONLY)) & ~off;
+ }
if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) {
if (typeset_setwidth(cname, pm, ops, on, 0))
return NULL;
@@ -2239,7 +2281,12 @@ typeset_single(char *cname, char *pname, Param pm, UNUSED(int func),
* readonly flag
*/
pm = createparam(pname, on & ~PM_READONLY);
- DPUTS(!pm, "BUG: parameter not created");
+ if (!pm) {
+ if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z |
+ PM_INTEGER | PM_EFLOAT | PM_FFLOAT))
+ zerrnam(cname, "can't change variable attribute: %s", pname);
+ return NULL;
+ }
if (on & (PM_LEFT | PM_RIGHT_B | PM_RIGHT_Z)) {
if (typeset_setwidth(cname, pm, ops, on, 0))
return NULL;
@@ -2501,6 +2548,8 @@ bin_typeset(char *name, char **argv, Options ops, int func)
asg->name),
func, (on | PM_ARRAY) & ~PM_EXPORTED,
off, roff, asg->value, NULL, ops, 0))) {
+ if (oldval)
+ zsfree(oldval);
unqueue_signals();
return 1;
}
@@ -3127,7 +3176,7 @@ bin_unset(char *name, char **argv, Options ops, int func)
}
}
returnval = errflag;
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
} else {
zerrnam(name, "%s: invalid element for unset", s);
returnval = 1;
@@ -3145,6 +3194,15 @@ bin_unset(char *name, char **argv, Options ops, int func)
/* type, whence, which, command */
+static LinkList matchednodes;
+
+static void
+fetchcmdnamnode(HashNode hn, UNUSED(int printflags))
+{
+ Cmdnam cn = (Cmdnam) hn;
+ addlinknode(matchednodes, cn->node.nam);
+}
+
/**/
int
bin_whence(char *nam, char **argv, Options ops, int func)
@@ -3155,8 +3213,8 @@ bin_whence(char *nam, char **argv, Options ops, int func)
int printflags = 0;
int aliasflags;
int csh, all, v, wd;
- int informed;
- char *cnam;
+ int informed = 0;
+ char *cnam, **allmatched = 0;
/* Check some option information */
csh = OPT_ISSET(ops,'c');
@@ -3189,6 +3247,11 @@ bin_whence(char *nam, char **argv, Options ops, int func)
/* With -m option -- treat arguments as a glob patterns */
if (OPT_ISSET(ops,'m')) {
+ cmdnamtab->filltable(cmdnamtab);
+ if (all) {
+ pushheap();
+ matchednodes = newlinklist();
+ }
for (; *argv; argv++) {
/* parse the pattern */
tokenize(*argv);
@@ -3204,97 +3267,105 @@ bin_whence(char *nam, char **argv, Options ops, int func)
* We're not using it, so search for ... */
/* aliases ... */
+ informed +=
scanmatchtable(aliastab, pprog, 1, 0, DISABLED,
aliastab->printnode, printflags);
/* and reserved words ... */
+ informed +=
scanmatchtable(reswdtab, pprog, 1, 0, DISABLED,
reswdtab->printnode, printflags);
/* and shell functions... */
+ informed +=
scanmatchtable(shfunctab, pprog, 1, 0, DISABLED,
shfunctab->printnode, printflags);
/* and builtins. */
+ informed +=
scanmatchtable(builtintab, pprog, 1, 0, DISABLED,
builtintab->printnode, printflags);
}
/* Done search for `internal' commands, if the -p option *
* was not used. Now search the path. */
- cmdnamtab->filltable(cmdnamtab);
+ informed +=
scanmatchtable(cmdnamtab, pprog, 1, 0, 0,
- cmdnamtab->printnode, printflags);
+ (all ? fetchcmdnamnode : cmdnamtab->printnode),
+ printflags);
unqueue_signals();
}
- return returnval;
+ if (all) {
+ allmatched = argv = zlinklist2array(matchednodes);
+ matchednodes = NULL;
+ popheap();
+ } else
+ return returnval || !informed;
}
/* Take arguments literally -- do not glob */
queue_signals();
for (; *argv; argv++) {
- informed = 0;
-
- if (!OPT_ISSET(ops,'p')) {
+ if (!OPT_ISSET(ops,'p') && !allmatched) {
char *suf;
/* Look for alias */
if ((hn = aliastab->getnode(aliastab, *argv))) {
aliastab->printnode(hn, aliasflags);
+ informed = 1;
if (!all)
continue;
- informed = 1;
}
/* Look for suffix alias */
if ((suf = strrchr(*argv, '.')) && suf[1] &&
suf > *argv && suf[-1] != Meta &&
(hn = sufaliastab->getnode(sufaliastab, suf+1))) {
sufaliastab->printnode(hn, printflags);
+ informed = 1;
if (!all)
continue;
- informed = 1;
}
/* Look for reserved word */
if ((hn = reswdtab->getnode(reswdtab, *argv))) {
reswdtab->printnode(hn, printflags);
+ informed = 1;
if (!all)
continue;
- informed = 1;
}
/* Look for shell function */
if ((hn = shfunctab->getnode(shfunctab, *argv))) {
shfunctab->printnode(hn, printflags);
+ informed = 1;
if (!all)
continue;
- informed = 1;
}
/* Look for builtin command */
if ((hn = builtintab->getnode(builtintab, *argv))) {
builtintab->printnode(hn, printflags);
+ informed = 1;
if (!all)
continue;
- informed = 1;
}
/* Look for commands that have been added to the *
* cmdnamtab with the builtin `hash foo=bar'. */
if ((hn = cmdnamtab->getnode(cmdnamtab, *argv)) && (hn->flags & HASHED)) {
cmdnamtab->printnode(hn, printflags);
+ informed = 1;
if (!all)
continue;
- informed = 1;
}
}
/* Option -a is to search the entire path, *
* rather than just looking for one match. */
- if (all) {
+ if (all && **argv != '/') {
char **pp, *buf;
pushheap();
for (pp = path; *pp; pp++) {
if (**pp) {
buf = zhtricat(*pp, "/", *argv);
- } else buf = ztrdup(*argv);
+ } else buf = dupstring(*argv);
if (iscom(buf)) {
if (wd) {
@@ -3303,8 +3374,8 @@ bin_whence(char *nam, char **argv, Options ops, int func)
if (v && !csh)
zputs(*argv, stdout), fputs(" is ", stdout);
zputs(buf, stdout);
- if (OPT_ISSET(ops,'s'))
- print_if_link(buf);
+ if (OPT_ISSET(ops,'s') || OPT_ISSET(ops, 'S'))
+ print_if_link(buf, OPT_ISSET(ops, 'S'));
fputc('\n', stdout);
}
informed = 1;
@@ -3324,10 +3395,11 @@ bin_whence(char *nam, char **argv, Options ops, int func)
if (v && !csh)
zputs(*argv, stdout), fputs(" is ", stdout);
zputs(cnam, stdout);
- if (OPT_ISSET(ops,'s'))
- print_if_link(cnam);
+ if (OPT_ISSET(ops,'s') || OPT_ISSET(ops,'S'))
+ print_if_link(cnam, OPT_ISSET(ops,'S'));
fputc('\n', stdout);
}
+ informed = 1;
} else {
/* Not found at all. */
if (v || csh || wd)
@@ -3335,8 +3407,11 @@ bin_whence(char *nam, char **argv, Options ops, int func)
returnval = 1;
}
}
+ if (allmatched)
+ freearray(allmatched);
+
unqueue_signals();
- return returnval;
+ return returnval || !informed;
}
/**** command & named directory hash table builtins ****/
@@ -3689,9 +3764,9 @@ int
bin_print(char *name, char **args, Options ops, int func)
{
int flen, width, prec, type, argc, n, narg, curlen = 0;
- int nnl = 0, fmttrunc = 0, ret = 0, maxarg = 0;
+ int nnl = 0, fmttrunc = 0, ret = 0, maxarg = 0, nc = 0;
int flags[5], *len;
- char *start, *endptr, *c, *d, *flag, *buf, spec[13], *fmt = NULL;
+ char *start, *endptr, *c, *d, *flag, *buf = NULL, spec[13], *fmt = NULL;
char **first, **argp, *curarg, *flagch = "0+- #", save = '\0', nullstr = '\0';
size_t rcount, count = 0;
#ifdef HAVE_OPEN_MEMSTREAM
@@ -3749,7 +3824,7 @@ bin_print(char *name, char **args, Options ops, int func)
/* compute lengths, and interpret according to -P, -D, -e, etc. */
argc = arrlen(args);
len = (int *) hcalloc(argc * sizeof(int));
- for(n = 0; n < argc; n++) {
+ for (n = 0; n < argc; n++) {
/* first \ sequences */
if (fmt ||
(!OPT_ISSET(ops,'e') &&
@@ -3802,8 +3877,38 @@ bin_print(char *name, char **args, Options ops, int func)
}
}
+ /* -o and -O -- sort the arguments */
+ if (OPT_ISSET(ops,'o') || OPT_ISSET(ops,'O')) {
+ int flags;
+
+ if (fmt && !*args)
+ return 0;
+ flags = OPT_ISSET(ops,'i') ? SORTIT_IGNORING_CASE : 0;
+ if (OPT_ISSET(ops,'O'))
+ flags |= SORTIT_BACKWARDS;
+ strmetasort(args, flags, len);
+ }
+
+ /* -C -- number of columns */
+ if (!fmt && OPT_ISSET(ops,'C')) {
+ char *eptr, *argptr = OPT_ARG(ops,'C');
+ nc = (int)zstrtol(argptr, &eptr, 10);
+ if (*eptr) {
+ zwarnnam(name, "number expected after -%c: %s", 'C', argptr);
+ return 1;
+ }
+ if (nc <= 0) {
+ zwarnnam(name, "invalid number of columns: %s", argptr);
+ return 1;
+ }
+ }
+
/* -u and -p -- output to other than standard output */
- if (OPT_HASARG(ops,'u') || OPT_ISSET(ops,'p')) {
+ if ((OPT_HASARG(ops,'u') || OPT_ISSET(ops,'p')) &&
+ /* rule out conflicting options -- historical precedence */
+ ((!fmt && (OPT_ISSET(ops,'c') || OPT_ISSET(ops,'C'))) ||
+ !(OPT_ISSET(ops, 'z') ||
+ OPT_ISSET(ops, 's') || OPT_ISSET(ops, 'S')))) {
int fdarg, fd;
if (OPT_ISSET(ops, 'p')) {
@@ -3816,7 +3921,7 @@ bin_print(char *name, char **args, Options ops, int func)
char *argptr = OPT_ARG(ops,'u'), *eptr;
/* Handle undocumented feature that -up worked */
if (!strcmp(argptr, "p")) {
- fdarg= coprocout;
+ fdarg = coprocout;
if (fdarg < 0) {
zwarnnam(name, "-p: no coprocess");
return 1;
@@ -3842,24 +3947,9 @@ bin_print(char *name, char **args, Options ops, int func)
}
}
- /* -o and -O -- sort the arguments */
- if (OPT_ISSET(ops,'o') || OPT_ISSET(ops,'O')) {
- int flags;
-
- if (fmt && !*args) {
- if (fout != stdout)
- fclose(fout);
- return 0;
- }
- flags = OPT_ISSET(ops,'i') ? SORTIT_IGNORING_CASE : 0;
- if (OPT_ISSET(ops,'O'))
- flags |= SORTIT_BACKWARDS;
- strmetasort(args, flags, len);
- }
-
/* -c -- output in columns */
if (!fmt && (OPT_ISSET(ops,'c') || OPT_ISSET(ops,'C'))) {
- int l, nc, nr, sc, n, t, i;
+ int l, nr, sc, n, t, i;
#ifdef MULTIBYTE_SUPPORT
int *widths;
@@ -3930,19 +4020,9 @@ bin_print(char *name, char **args, Options ops, int func)
#endif
if (OPT_ISSET(ops,'C')) {
- char *eptr, *argptr = OPT_ARG(ops,'C');
- nc = (int)zstrtol(argptr, &eptr, 10);
- if (*eptr) {
- zwarnnam(name, "number expcted after -%c: %s", 'C', argptr);
- return 1;
- }
- if (nc <= 0) {
- zwarnnam(name, "invalid number of columns: %s", argptr);
- return 1;
- }
/*
* n: number of elements
- * nc: number of columns
+ * nc: number of columns (above)
* nr: number of rows
*/
n = arrlen(args);
@@ -4168,6 +4248,10 @@ bin_print(char *name, char **args, Options ops, int func)
narg);
if (fout != stdout)
fclose(fout);
+#ifdef HAVE_OPEN_MEMSTREAM
+ if (buf)
+ free(buf);
+#endif
return 1;
} else {
if (narg > maxarg) maxarg = narg;
@@ -4201,6 +4285,10 @@ bin_print(char *name, char **args, Options ops, int func)
narg);
if (fout != stdout)
fclose(fout);
+#ifdef HAVE_OPEN_MEMSTREAM
+ if (buf)
+ free(buf);
+#endif
return 1;
} else {
if (narg > maxarg) maxarg = narg;
@@ -4211,7 +4299,7 @@ bin_print(char *name, char **args, Options ops, int func)
if (*argp) {
width = (int)mathevali(*argp++);
if (errflag) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
ret = 1;
}
}
@@ -4230,6 +4318,10 @@ bin_print(char *name, char **args, Options ops, int func)
narg);
if (fout != stdout)
fclose(fout);
+#ifdef HAVE_OPEN_MEMSTREAM
+ if (buf)
+ free(buf);
+#endif
return 1;
} else {
if (narg > maxarg) maxarg = narg;
@@ -4241,7 +4333,7 @@ bin_print(char *name, char **args, Options ops, int func)
if (*argp) {
prec = (int)mathevali(*argp++);
if (errflag) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
ret = 1;
}
}
@@ -4385,6 +4477,10 @@ bin_print(char *name, char **args, Options ops, int func)
(fflush(fout) != 0 && errno != EBADF)) {
zwarnnam(name, "write error: %e", errno);
}
+#ifdef HAVE_OPEN_MEMSTREAM
+ if (buf)
+ free(buf);
+#endif
return 1;
}
@@ -4421,7 +4517,7 @@ bin_print(char *name, char **args, Options ops, int func)
zlongval = (curarg) ? mathevali(curarg) : 0;
if (errflag) {
zlongval = 0;
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
ret = 1;
}
print_val(zlongval)
@@ -4450,7 +4546,7 @@ bin_print(char *name, char **args, Options ops, int func)
} else doubleval = 0;
if (errflag) {
doubleval = 0;
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
ret = 1;
}
print_val(doubleval)
@@ -4463,7 +4559,7 @@ bin_print(char *name, char **args, Options ops, int func)
zulongval = (curarg) ? mathevali(curarg) : 0;
if (errflag) {
zulongval = 0;
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
ret = 1;
}
print_val(zulongval)
@@ -4481,7 +4577,8 @@ bin_print(char *name, char **args, Options ops, int func)
if (OPT_ISSET(ops,'z') || OPT_ISSET(ops,'s')) {
#ifdef HAVE_OPEN_MEMSTREAM
putc(0, fout);
- fflush(fout);
+ fclose(fout);
+ fout = NULL;
#else
rewind(fout);
buf = (char *)zalloc(count + 1);
@@ -4502,11 +4599,16 @@ bin_print(char *name, char **args, Options ops, int func)
unqueue_signals();
}
- /* Testing EBADF special-cases >&- redirections */
- if ((fout != stdout) ? (fclose(fout) != 0) :
- (fflush(fout) != 0 && errno != EBADF)) {
- zwarnnam(name, "write error: %e", errno);
- ret = 1;
+#ifdef HAVE_OPEN_MEMSTREAM
+ if (fout)
+#endif
+ {
+ /* Testing EBADF special-cases >&- redirections */
+ if ((fout != stdout) ? (fclose(fout) != 0) :
+ (fflush(fout) != 0 && errno != EBADF)) {
+ zwarnnam(name, "write error: %e", errno);
+ ret = 1;
+ }
}
return ret;
}
@@ -4840,7 +4942,7 @@ zexit(int val, int from_where)
in_exit = -1;
/*
* We want to do all remaining processing regardless of preceding
- * errors.
+ * errors, even user interrupts.
*/
errflag = 0;
@@ -5043,7 +5145,7 @@ eval(char **argv)
if (fpushed)
funcstack = funcstack->prev;
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
scriptname = oscriptname;
ineval = oineval;
@@ -5140,7 +5242,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
if (cmd) {
if (opt_L) {
zwarnnam("emulate", "option -L incompatible with -c");
- goto restore;
+ goto restore2;
}
*--argv = cmd; /* on stack, never free()d, see execbuiltin() */
} else
@@ -5178,6 +5280,7 @@ bin_emulate(UNUSED(char *nam), char **argv, Options ops, UNUSED(int func))
}
ret = eval(argv);
sticky = save_sticky;
+restore2:
emulation = saveemulation;
memcpy(opts, saveopts, sizeof(opts));
restorepatterndisables(savepatterns);
@@ -6061,7 +6164,7 @@ bin_test(char *name, char **argv, UNUSED(Options ops), int func)
}
}
- lexsave();
+ zcontext_save();
testargs = argv;
tok = NULLTOK;
condlex = testlex;
@@ -6070,17 +6173,17 @@ bin_test(char *name, char **argv, UNUSED(Options ops), int func)
condlex = zshlex;
if (errflag) {
- errflag = 0;
- lexrestore();
+ errflag &= ~ERRFLAG_ERROR;
+ zcontext_restore();
return 1;
}
if (!prog || tok == LEXERR) {
zwarnnam(name, tokstr ? "parse error" : "argument expected");
- lexrestore();
+ zcontext_restore();
return 1;
}
- lexrestore();
+ zcontext_restore();
if (*curtestarg) {
zwarnnam(name, "too many arguments");
@@ -6247,7 +6350,7 @@ bin_let(UNUSED(char *name), char **argv, UNUSED(Options ops), UNUSED(int func))
while (*argv)
val = matheval(*argv++);
/* Errors in math evaluation in let are non-fatal. */
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
/* should test for fabs(val.u.d) < epsilon? */
return (val.type == MN_INTEGER) ? val.u.l == 0 : val.u.d == 0.0;
}
diff --git a/Src/compat.c b/Src/compat.c
index b0bcb6265..b3a8b063c 100644
--- a/Src/compat.c
+++ b/Src/compat.c
@@ -443,7 +443,7 @@ zgetcwd(void)
ret = getcwd(cwdbuf, PATH_MAX);
if (ret)
ret = dupstring(ret);
- free(cwdbuf);
+ zfree(cwdbuf, PATH_MAX);
#endif /* GETCWD_CALLS_MALLOC */
}
#endif /* HAVE_GETCWD */
@@ -951,3 +951,18 @@ int mk_wcswidth_cjk(const wchar_t *pwcs, size_t n)
/**/
#endif /* BROKEN_WCWIDTH && (__STDC_ISO_10646__ || __APPLE__) */
+/**/
+#if defined(__APPLE__) && defined(BROKEN_ISPRINT)
+
+/**/
+int
+isprint_ascii(int c)
+{
+ if (!strcmp(nl_langinfo(CODESET), "UTF-8"))
+ return (c >= 0x20 && c <= 0x7e);
+ else
+ return isprint(c);
+}
+
+/**/
+#endif /* __APPLE__ && BROKEN_ISPRINT */
diff --git a/Src/context.c b/Src/context.c
new file mode 100644
index 000000000..1b8741f46
--- /dev/null
+++ b/Src/context.c
@@ -0,0 +1,116 @@
+/*
+ * context.c - context save and restore
+ *
+ * This file is part of zsh, the Z shell.
+ *
+ * Copyright (c) 2015 Peter Stephenson
+ * All rights reserved.
+ *
+ * Permission is hereby granted, without written agreement and without
+ * license or royalty fees, to use, copy, modify, and distribute this
+ * software and to distribute modified versions of this software for any
+ * purpose, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * In no event shall Peter Stephenson or the Zsh Development Group be liable
+ * to any party for direct, indirect, special, incidental, or consequential
+ * damages arising out of the use of this software and its documentation,
+ * even if Peter Stephenson and the Zsh Development Group have been advised of
+ * the possibility of such damage.
+ *
+ * Peter Stephenson and the Zsh Development Group specifically disclaim any
+ * warranties, including, but not limited to, the implied warranties of
+ * merchantability and fitness for a particular purpose. The software
+ * provided hereunder is on an "as is" basis, and Peter Stephenson and the
+ * Zsh Development Group have no obligation to provide maintenance,
+ * support, updates, enhancements, or modifications.
+ *
+ */
+/*
+ * This short file provides a home for the stack of saved contexts.
+ * The actions for saving and restoring are encapsulated within
+ * individual modules.
+ */
+
+#include "zsh.mdh"
+#include "context.pro"
+
+struct context_stack {
+ struct context_stack *next;
+
+ struct hist_stack hist_stack;
+ struct lex_stack lex_stack;
+ struct parse_stack parse_stack;
+};
+
+static struct context_stack *cstack;
+
+/* save some or all of current context */
+
+/**/
+mod_export void
+zcontext_save_partial(int parts)
+{
+ struct context_stack *cs;
+
+ cs = (struct context_stack *)malloc(sizeof(struct context_stack));
+
+ if (parts & ZCONTEXT_HIST) {
+ hist_context_save(&cs->hist_stack, !cstack);
+ }
+ if (parts & ZCONTEXT_LEX) {
+ lex_context_save(&cs->lex_stack, !cstack);
+ }
+ if (parts & ZCONTEXT_PARSE) {
+ parse_context_save(&cs->parse_stack, !cstack);
+ }
+
+ cs->next = cstack;
+ cstack = cs;
+}
+
+/* save context in full */
+
+/**/
+mod_export void
+zcontext_save(void)
+{
+ zcontext_save_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
+}
+
+/* restore context or part thereof */
+
+/**/
+mod_export void
+zcontext_restore_partial(int parts)
+{
+ struct context_stack *cs = cstack;
+
+ DPUTS(!cstack, "BUG: zcontext_restore() without zcontext_save()");
+
+ queue_signals();
+ cstack = cstack->next;
+
+ if (parts & ZCONTEXT_HIST) {
+ hist_context_restore(&cs->hist_stack, !cstack);
+ }
+ if (parts & ZCONTEXT_LEX) {
+ lex_context_restore(&cs->lex_stack, !cstack);
+ }
+ if (parts & ZCONTEXT_PARSE) {
+ parse_context_restore(&cs->parse_stack, !cstack);
+ }
+
+ free(cs);
+
+ unqueue_signals();
+}
+
+/* restore full context */
+
+/**/
+mod_export void
+zcontext_restore(void)
+{
+ zcontext_restore_partial(ZCONTEXT_HIST|ZCONTEXT_LEX|ZCONTEXT_PARSE);
+}
diff --git a/Src/exec.c b/Src/exec.c
index d0fadd69a..6a8b35a36 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -59,7 +59,7 @@ mod_export int noerrs;
/**/
int nohistsave;
-/* error/break flag */
+/* error flag: bits from enum errflag_bits */
/**/
mod_export int errflag;
@@ -217,7 +217,7 @@ parse_string(char *s, int reset_lineno)
Eprog p;
zlong oldlineno;
- lexsave();
+ zcontext_save();
inpush(s, INP_LINENO, NULL);
strinbeg(0);
oldlineno = lineno;
@@ -229,7 +229,7 @@ parse_string(char *s, int reset_lineno)
lastval = 1;
strinend();
inpop();
- lexrestore();
+ zcontext_restore();
return p;
}
@@ -250,6 +250,7 @@ zsetlimit(int limnum, char *nam)
if (setrlimit(limnum, limits + limnum)) {
if (nam)
zwarnnam(nam, "setrlimit failed: %e", errno);
+ limits[limnum] = current_limits[limnum];
return -1;
}
current_limits[limnum] = limits[limnum];
@@ -1145,7 +1146,8 @@ execlist(Estate state, int dont_change_job, int exiting)
Wordcode next;
wordcode code;
int ret, cj, csp, ltype;
- int old_pline_level, old_list_pipe;
+ int old_pline_level, old_list_pipe, old_list_pipe_job;
+ char *old_list_pipe_text;
zlong oldlineno;
/*
* ERREXIT only forces the shell to exit if the last command in a &&
@@ -1158,10 +1160,17 @@ execlist(Estate state, int dont_change_job, int exiting)
cj = thisjob;
old_pline_level = pline_level;
old_list_pipe = list_pipe;
+ old_list_pipe_job = list_pipe_job;
+ if (*list_pipe_text)
+ old_list_pipe_text = ztrdup(list_pipe_text);
+ else
+ old_list_pipe_text = NULL;
oldlineno = lineno;
- if (sourcelevel && unset(SHINSTDIN))
- pline_level = list_pipe = 0;
+ if (sourcelevel && unset(SHINSTDIN)) {
+ pline_level = list_pipe = list_pipe_job = 0;
+ *list_pipe_text = '\0';
+ }
/* Loop over all sets of comands separated by newline, *
* semi-colon or ampersand (`sublists'). */
@@ -1396,6 +1405,13 @@ sublist_done:
}
pline_level = old_pline_level;
list_pipe = old_list_pipe;
+ list_pipe_job = old_list_pipe_job;
+ if (old_list_pipe_text) {
+ strcpy(list_pipe_text, old_list_pipe_text);
+ zsfree(old_list_pipe_text);
+ } else {
+ *list_pipe_text = '\0';
+ }
lineno = oldlineno;
if (dont_change_job)
thisjob = cj;
@@ -1600,7 +1616,8 @@ execpline(Estate state, wordcode slcode, int how, int last1)
(killpg(jobtab[list_pipe_job].gleader, 0) == -1 ? 2 : 1);
list_pipe_pid = pid;
list_pipe_start = bgtime;
- nowait = errflag = 1;
+ nowait = 1;
+ errflag |= ERRFLAG_ERROR;
breaks = loops;
close(synch[1]);
read_loop(synch[0], &dummy, 1);
@@ -1633,7 +1650,10 @@ execpline(Estate state, wordcode slcode, int how, int last1)
list_pipe_child = 1;
opts[INTERACTIVE] = 0;
if (errbrk_saved) {
- errflag = prev_errflag;
+ /*
+ * Keep any user interrupt bit in errflag.
+ */
+ errflag = prev_errflag | (errflag & ERRFLAG_INT);
breaks = prev_breaks;
}
break;
@@ -1718,12 +1738,14 @@ execpline2(Estate state, wordcode pcode,
if (pipe(synch) < 0) {
zerr("pipe failed: %e", errno);
- lastval = errflag = 1;
+ lastval = 1;
+ errflag |= ERRFLAG_ERROR;
return;
} else if ((pid = zfork(&bgtime)) == -1) {
close(synch[0]);
close(synch[1]);
- lastval = errflag = 1;
+ lastval = 1;
+ errflag |= ERRFLAG_ERROR;
return;
} else if (pid) {
char dummy, *text;
@@ -2242,8 +2264,16 @@ addvars(Estate state, Wordcode pc, int addflags)
state->pc = opc;
return;
}
- if (isset(GLOBASSIGN) || !isstr)
+ if (!isstr || (isset(GLOBASSIGN) &&
+ haswilds((char *)getdata(firstnode(vl))))) {
globlist(vl, 0);
+ /* Unset the parameter to force it to be recreated
+ * as either scalar or array depending on how many
+ * matches were found for the glob.
+ */
+ if (isset(GLOBASSIGN))
+ unsetparam(name);
+ }
if (errflag) {
state->pc = opc;
return;
@@ -2279,6 +2309,8 @@ addvars(Estate state, Wordcode pc, int addflags)
}
allexp = opts[ALLEXPORT];
opts[ALLEXPORT] = 1;
+ if (isset(KSHARRAYS))
+ unsetparam(name);
pm = assignsparam(name, val, myflags);
opts[ALLEXPORT] = allexp;
} else
@@ -2290,13 +2322,13 @@ addvars(Estate state, Wordcode pc, int addflags)
continue;
}
if (vl) {
- ptr = arr = (char **) zalloc(sizeof(char **) *
+ ptr = arr = (char **) zalloc(sizeof(char *) *
(countlinknodes(vl) + 1));
while (nonempty(vl))
*ptr++ = ztrdup((char *) ugetnode(vl));
} else
- ptr = arr = (char **) zalloc(sizeof(char **));
+ ptr = arr = (char **) zalloc(sizeof(char *));
*ptr = NULL;
if (xtr) {
@@ -2320,6 +2352,7 @@ addvars(Estate state, Wordcode pc, int addflags)
void
setunderscore(char *str)
{
+ queue_signals();
if (str && *str) {
int l = strlen(str) + 1, nl = (l + 31) & ~31;
@@ -2337,6 +2370,7 @@ setunderscore(char *str)
*zunderscore = '\0';
underscoreused = 1;
}
+ unqueue_signals();
}
/* These describe the type of expansions that need to be done on the words
@@ -2551,7 +2585,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
while (next && *next == '-' && strlen(next) >= 2) {
if (!firstnode(args)) {
zerr("exec requires a command to execute");
- errflag = lastval = 1;
+ lastval = 1;
+ errflag |= ERRFLAG_ERROR;
goto done;
}
uremnode(args, firstnode(args));
@@ -2568,12 +2603,14 @@ execcmd(Estate state, int input, int output, int how, int last1)
} else {
if (!firstnode(args)) {
zerr("exec requires a command to execute");
- errflag = lastval = 1;
+ lastval = 1;
+ errflag |= ERRFLAG_ERROR;
goto done;
}
if (!nextnode(firstnode(args))) {
zerr("exec flag -a requires a parameter");
- errflag = lastval = 1;
+ lastval = 1;
+ errflag |= ERRFLAG_ERROR;
goto done;
}
exec_argv0 = (char *)
@@ -2589,7 +2626,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
break;
default:
zerr("unknown exec flag -%c", *cmdopt);
- errflag = lastval = 1;
+ lastval = 1;
+ errflag |= ERRFLAG_ERROR;
return;
}
}
@@ -2613,6 +2651,10 @@ execcmd(Estate state, int input, int output, int how, int last1)
}
}
+ /* if we get this far, it is OK to pay attention to lastval again */
+ if (noerrexit == 2 && !is_shfunc)
+ noerrexit = 0;
+
/* Do prefork substitutions */
esprefork = (assign || isset(MAGICEQUALSUBST)) ? PREFORK_TYPESET : 0;
if (args && htok)
@@ -2652,7 +2694,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
} else if (!nullcmd || !*nullcmd || opts[CSHNULLCMD] ||
(cflags & BINF_PREFIX)) {
zerr("redirection with no command");
- errflag = lastval = 1;
+ lastval = 1;
+ errflag |= ERRFLAG_ERROR;
return;
} else if (!nullcmd || !*nullcmd || opts[SHNULLCMD]) {
if (!args)
@@ -2682,7 +2725,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
if (varspc)
addvars(state, varspc, 0);
if (errflag)
- lastval = errflag;
+ lastval = 1;
else
lastval = cmdoutval;
if (isset(XTRACE)) {
@@ -2758,9 +2801,14 @@ execcmd(Estate state, int input, int output, int how, int last1)
else
text = NULL;
- /* Set up special parameter $_ */
-
- setunderscore((args && nonempty(args)) ? ((char *) getdata(lastnode(args))) : "");
+ /*
+ * Set up special parameter $_
+ * For execfuncdef we may need to take account of an
+ * anonymous function with arguments.
+ */
+ if (type != WC_FUNCDEF)
+ setunderscore((args && nonempty(args)) ?
+ ((char *) getdata(lastnode(args))) : "");
/* Warn about "rm *" */
if (type == WC_SIMPLE && interact && unset(RMSTARSILENT) &&
@@ -2786,7 +2834,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
}
}
if (!nextnode(firstnode(args)))
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
}
if (type == WC_FUNCDEF) {
@@ -2882,6 +2930,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
* is a directory we should AUTOCD to. */
if (!hn && trycd && (s = cancd(peekfirst(args)))) {
peekfirst(args) = (void *) s;
+ pushnode(args, dupstring("--"));
pushnode(args, dupstring("cd"));
if ((hn = builtintab->getnode(builtintab, "cd")))
is_builtin = 1;
@@ -2931,7 +2980,8 @@ execcmd(Estate state, int input, int output, int how, int last1)
} else if ((pid = zfork(&bgtime)) == -1) {
close(synch[0]);
close(synch[1]);
- lastval = errflag = 1;
+ lastval = 1;
+ errflag |= ERRFLAG_ERROR;
goto fatal;
}
if (pid) {
@@ -2941,8 +2991,6 @@ execcmd(Estate state, int input, int output, int how, int last1)
close(synch[0]);
if (how & Z_ASYNC) {
lastpid = (zlong) pid;
- /* indicate it's possible to set status for lastpid */
- lastpid_status = -2L;
} else if (!jobtab[thisjob].stty_in_env && varspc) {
/* search for STTY=... */
Wordcode p = varspc;
@@ -2996,6 +3044,15 @@ execcmd(Estate state, int input, int output, int how, int last1)
* Note that any form of exec means that the subshell is fake *
* (but we may be in a subshell already). */
is_exec = 1;
+ /*
+ * If we are in a subshell environment anyway, say we're forked,
+ * even if we're actually not forked because we know the
+ * subshell is exiting. This ensures SHLVL reflects the current
+ * shell, and also optimises out any save/restore we'd need to
+ * do if we were returning to the main shell.
+ */
+ if (type == WC_SUBSH)
+ forked = 1;
}
if ((esglob = !(cflags & BINF_NOGLOB)) && args && htok) {
@@ -3169,7 +3226,12 @@ execcmd(Estate state, int input, int output, int how, int last1)
}
if (fn->fd1 < 10)
closemn(mfds, fn->fd1, REDIR_CLOSE);
- if (!closed && zclose(fn->fd1) < 0) {
+ /*
+ * Only report failures to close file descriptors
+ * if they're under user control as we don't know
+ * what the previous status of others was.
+ */
+ if (!closed && zclose(fn->fd1) < 0 && fn->varid) {
zwarn("failed to close file descriptor %d: %e",
fn->fd1, errno);
}
@@ -3259,6 +3321,20 @@ execcmd(Estate state, int input, int output, int how, int last1)
closemn(mfds, i, REDIR_CLOSE);
if (nullexec) {
+ /*
+ * If nullexec is 2, we have variables to add with the redirections
+ * in place. If nullexec is 1, we may have variables but they
+ * need the standard restore logic.
+ */
+ if (varspc) {
+ LinkList restorelist = 0, removelist = 0;
+ if (!isset(POSIXBUILTINS) && nullexec != 2)
+ save_params(state, varspc, &restorelist, &removelist);
+ addvars(state, varspc, 0);
+ if (restorelist)
+ restore_params(restorelist, removelist);
+ }
+ lastval = errflag ? errflag : cmdoutval;
if (nullexec == 1) {
/*
* If nullexec is 1 we specifically *don't* restore the original
@@ -3269,13 +3345,6 @@ execcmd(Estate state, int input, int output, int how, int last1)
zclose(save[i]);
goto done;
}
- /*
- * If nullexec is 2, we have variables to add with the redirections
- * in place.
- */
- if (varspc)
- addvars(state, varspc, 0);
- lastval = errflag ? errflag : cmdoutval;
if (isset(XTRACE)) {
fputc('\n', xtrerr);
fflush(xtrerr);
@@ -3315,14 +3384,14 @@ execcmd(Estate state, int input, int output, int how, int last1)
* The copy uses the wordcode parsing area, so save and
* restore state.
*/
- lexsave();
+ zcontext_save();
redir_prog = eccopyredirs(&s);
- lexrestore();
+ zcontext_restore();
} else
redir_prog = NULL;
-
+
lastval = execfuncdef(state, redir_prog);
- }
+ }
else if (type >= WC_CURSH) {
if (last1 == 1)
do_exec = 1;
@@ -3338,14 +3407,28 @@ execcmd(Estate state, int input, int output, int how, int last1)
LinkList restorelist = 0, removelist = 0;
/* builtin or shell function */
- if (!forked && ((cflags & BINF_COMMAND) ||
- (unset(POSIXBUILTINS) && !assign) ||
- (isset(POSIXBUILTINS) && !is_shfunc &&
- !(hn->flags & BINF_PSPECIAL)))) {
- if (varspc)
+ if (!forked && varspc) {
+ int do_save = 0;
+ if (isset(POSIXBUILTINS)) {
+ /*
+ * If it's a function or special builtin --- save
+ * if it's got "command" in front.
+ * If it's a normal command --- save.
+ */
+ if (is_shfunc || (hn->flags & BINF_PSPECIAL))
+ do_save = (orig_cflags & BINF_COMMAND);
+ else
+ do_save = 1;
+ } else {
+ /*
+ * Save if it's got "command" in front or it's
+ * not a magic-equals assignment.
+ */
+ if ((cflags & BINF_COMMAND) || !assign)
+ do_save = 1;
+ }
+ if (do_save)
save_params(state, varspc, &restorelist, &removelist);
- else
- restorelist = removelist = NULL;
}
if (varspc) {
/* Export this if the command is a shell function,
@@ -3513,7 +3596,7 @@ execcmd(Estate state, int input, int output, int how, int last1)
else
exit(1);
}
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
}
}
if (newxtrerr) {
@@ -3738,17 +3821,20 @@ gethere(char **strp, int typ)
*bptr++ = '\n';
}
*t = '\0';
+ s = buf;
+ buf = dupstring(buf);
+ zfree(s, bsiz);
if (!qt) {
int ef = errflag;
- parsestr(buf);
+ parsestr(&buf);
- if (!errflag)
- errflag = ef;
+ if (!errflag) {
+ /* Retain any user interrupt error */
+ errflag = ef | (errflag & ERRFLAG_INT);
+ }
}
- s = dupstring(buf);
- zfree(buf, bsiz);
- return s;
+ return buf;
}
/* open here string fd */
@@ -3832,13 +3918,13 @@ getoutput(char *cmd, int qt)
return NULL;
untokenize(s);
if ((stream = open(unmeta(s), O_RDONLY | O_NOCTTY)) == -1) {
- zerr("%e: %s", errno, s);
- return NULL;
+ zwarn("%e: %s", errno, s);
+ return newlinklist();
}
return readoutput(stream, qt);
}
if (mpipe(pipes) < 0) {
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
cmdoutpid = 0;
return NULL;
}
@@ -3848,7 +3934,7 @@ getoutput(char *cmd, int qt)
/* fork error */
zclose(pipes[0]);
zclose(pipes[1]);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
cmdoutpid = 0;
child_unblock();
return NULL;
@@ -4258,7 +4344,7 @@ execcond(Estate state, UNUSED(int do_exec))
* into a shell error.
*/
if (stat == 2)
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
cmdpop();
if (isset(XTRACE)) {
fprintf(xtrerr, " ]]\n");
@@ -4298,7 +4384,7 @@ execarith(Estate state, UNUSED(int do_exec))
fflush(xtrerr);
}
if (errflag) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
return 2;
}
/* should test for fabs(val.u.d) < epsilon? */
@@ -4332,7 +4418,7 @@ execfuncdef(Estate state, Eprog redir_prog)
Shfunc shf;
char *s = NULL;
int signum, nprg, sbeg, nstrs, npats, len, plen, i, htok = 0, ret = 0;
- int nfunc = 0;
+ int nfunc = 0, anon_func = 0;
Wordcode beg = state->pc, end;
Eprog prog;
Patprog *pp;
@@ -4414,10 +4500,12 @@ execfuncdef(Estate state, Eprog redir_prog)
if (!names) {
/*
* Anonymous function, execute immediately.
- * Function name is "(anon)", parameter list is empty.
+ * Function name is "(anon)".
*/
LinkList args;
+ anon_func = 1;
+
state->pc = end;
end += *state->pc++;
args = ecgetlist(state, *state->pc++, EC_DUPTOK, &htok);
@@ -4425,11 +4513,19 @@ execfuncdef(Estate state, Eprog redir_prog)
if (htok && args) {
execsubst(args);
if (errflag) {
+ freeeprog(shf->funcdef);
+ if (shf->redir) /* shouldn't be */
+ freeeprog(shf->redir);
+ zsfree(shf->filename);
+ zfree(shf, sizeof(*shf));
state->pc = end;
return 1;
}
}
+ setunderscore((args && nonempty(args)) ?
+ ((char *) getdata(lastnode(args))) : "");
+
if (!args)
args = newlinklist();
shf->node.nam = "(anon)";
@@ -4438,6 +4534,16 @@ execfuncdef(Estate state, Eprog redir_prog)
execshfunc(shf, args);
ret = lastval;
+ if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) &&
+ lastval) {
+#if defined(ZLONG_IS_LONG_LONG) && defined(PRINTF_HAS_LLD)
+ fprintf(stderr, "zsh: exit %lld\n", lastval);
+#else
+ fprintf(stderr, "zsh: exit %ld\n", (long)lastval);
+#endif
+ fflush(stderr);
+ }
+
freeeprog(shf->funcdef);
if (shf->redir) /* shouldn't be */
freeeprog(shf->redir);
@@ -4450,6 +4556,7 @@ execfuncdef(Estate state, Eprog redir_prog)
(signum = getsignum(s + 4)) != -1) {
if (settrap(signum, NULL, ZSIG_FUNC)) {
freeeprog(shf->funcdef);
+ zsfree(shf->filename);
zfree(shf, sizeof(*shf));
state->pc = end;
return 1;
@@ -4464,6 +4571,8 @@ execfuncdef(Estate state, Eprog redir_prog)
shfunctab->addnode(shfunctab, ztrdup(s), shf);
}
}
+ if (!anon_func)
+ setunderscore("");
if (!nfunc && redir_prog) {
/* For completeness, shouldn't happen */
freeeprog(redir_prog);
@@ -4547,6 +4656,7 @@ execshfunc(Shfunc shf, LinkList args)
fputc('\n', xtrerr);
fflush(xtrerr);
}
+ queue_signals();
ocs = cmdstack;
ocsp = cmdsp;
cmdstack = (unsigned char *) zalloc(CMDSTACKSZ);
@@ -4554,7 +4664,11 @@ execshfunc(Shfunc shf, LinkList args)
if ((osfc = sfcontext) == SFC_NONE)
sfcontext = SFC_DIRECT;
xtrerr = stderr;
+ unqueue_signals();
+
doshfunc(shf, args, 0);
+
+ queue_signals();
sfcontext = osfc;
free(cmdstack);
cmdstack = ocs;
@@ -4562,6 +4676,7 @@ execshfunc(Shfunc shf, LinkList args)
if (!list_pipe)
deletefilelist(last_file_list, 0);
+ unqueue_signals();
}
/*
@@ -4910,7 +5025,7 @@ doshfunc(Shfunc shfunc, LinkList doshargs, int noreturnval)
(name = fname)))) {
zwarn("%s: function not defined by file", name);
if (noreturnval)
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
else
lastval = 1;
goto doneshfunc;
@@ -5243,7 +5358,7 @@ execsave(void)
{
struct execstack *es;
- es = (struct execstack *) malloc(sizeof(struct execstack));
+ es = (struct execstack *) zalloc(sizeof(struct execstack));
es->list_pipe_pid = list_pipe_pid;
es->nowait = nowait;
es->pline_level = pline_level;
diff --git a/Src/glob.c b/Src/glob.c
index ca7bc4410..057d44a17 100644
--- a/Src/glob.c
+++ b/Src/glob.c
@@ -386,8 +386,8 @@ insert(char *s, int checked)
while (!inserts || (news = dupstring(*inserts++))) {
if (colonmod) {
/* Handle the remainder of the qualifier: e.g. (:r:s/foo/bar/). */
- s = colonmod;
- modify(&news, &s);
+ char *mod = colonmod;
+ modify(&news, &mod);
}
if (!statted && (gf_sorts & GS_NORMAL)) {
statfullpath(s, &buf, 1);
@@ -437,7 +437,7 @@ insert(char *s, int checked)
matchptr++;
if (++matchct == matchsz) {
- matchbuf = (Gmatch )realloc((char *)matchbuf,
+ matchbuf = (Gmatch)zrealloc((char *)matchbuf,
sizeof(struct gmatch) * (matchsz *= 2));
matchptr = matchbuf + matchct;
@@ -463,7 +463,7 @@ scanner(Complist q, int shortcircuit)
int errssofar = errsfound;
struct dirsav ds;
- if (!q)
+ if (!q || errflag)
return;
init_dirsav(&ds);
@@ -682,7 +682,7 @@ parsecomplist(char *instr)
/* Now get the next path component if there is one. */
l1 = (Complist) zhalloc(sizeof *l1);
if ((l1->next = parsecomplist(instr)) == NULL) {
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return NULL;
}
l1->pat = patcompile(NULL, compflags | PAT_ANY, NULL);
@@ -708,7 +708,8 @@ parsecomplist(char *instr)
}
l1 = (Complist) zhalloc(sizeof *l1);
l1->pat = p1;
- l1->closure = 1 + pdflag;
+ /* special case (/)# to avoid infinite recursion */
+ l1->closure = (*((char *)p1 + p1->startoff)) ? 1 + pdflag : 0;
l1->follow = 0;
l1->next = parsecomplist(instr);
return (l1->pat) ? l1 : NULL;
@@ -728,7 +729,7 @@ parsecomplist(char *instr)
return (ef && !l1->next) ? NULL : l1;
}
}
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return NULL;
}
@@ -1790,7 +1791,7 @@ zglob(LinkList list, LinkNode np, int nountok)
insertlinknode(list, node, ostr);
return;
}
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
zerr("bad pattern: %s", ostr);
return;
}
@@ -1817,7 +1818,7 @@ zglob(LinkList list, LinkNode np, int nountok)
badcshglob |= 1; /* at least one cmd. line expansion failed */
} else if (isset(NOMATCH)) {
zerr("no matches found: %s", ostr);
- free(matchbuf);
+ zfree(matchbuf, 0);
restore_globstate(saved);
return;
} else {
@@ -1873,7 +1874,8 @@ zglob(LinkList list, LinkNode np, int nountok)
tmpptr->sortstrs[iexec] = tmpptr->name;
}
- errflag = ef;
+ /* Retain any user interrupt error status */
+ errflag = ef | (errflag & ERRFLAG_INT);
lastval = lv;
} else {
/* Failed, let's be safe */
@@ -1921,7 +1923,7 @@ zglob(LinkList list, LinkNode np, int nountok)
} else if (!badcshglob && !isset(NOMATCH) && matchct == 1) {
insert_glob_match(list, node, (--matchptr)->name);
}
- free(matchbuf);
+ zfree(matchbuf, 0);
restore_globstate(saved);
}
@@ -3733,7 +3735,8 @@ qualsheval(char *name, UNUSED(struct stat *buf), UNUSED(off_t days), char *str)
execode(prog, 1, 0, "globqual");
ret = lastval;
- errflag = ef;
+ /* Retain any user interrupt error status */
+ errflag = ef | (errflag & ERRFLAG_INT);
lastval = lv;
if (!(inserts = getaparam("reply")) &&
diff --git a/Src/hashtable.c b/Src/hashtable.c
index 7a430629d..ab381cc6a 100644
--- a/Src/hashtable.c
+++ b/Src/hashtable.c
@@ -910,7 +910,7 @@ printshfuncnode(HashNode hn, int printflags)
{
Shfunc f = (Shfunc) hn;
char *t = 0;
-
+
if ((printflags & PRINT_NAMEONLY) ||
((printflags & PRINT_WHENCE_SIMPLE) &&
!(printflags & PRINT_WHENCE_FUNCDEF))) {
@@ -922,8 +922,16 @@ printshfuncnode(HashNode hn, int printflags)
if ((printflags & (PRINT_WHENCE_VERBOSE|PRINT_WHENCE_WORD)) &&
!(printflags & PRINT_WHENCE_FUNCDEF)) {
nicezputs(f->node.nam, stdout);
- printf((printflags & PRINT_WHENCE_WORD) ? ": function\n" :
- " is a shell function\n");
+ printf((printflags & PRINT_WHENCE_WORD) ? ": function" :
+ (f->node.flags & PM_UNDEFINED) ?
+ " is an autoload shell function" :
+ " is a shell function");
+ if (f->filename && (printflags & PRINT_WHENCE_VERBOSE) &&
+ strcmp(f->filename, f->node.nam) != 0) {
+ printf(" from ");
+ quotedzputs(f->filename, stdout);
+ }
+ putchar('\n');
return;
}
diff --git a/Src/hist.c b/Src/hist.c
index 4660fd073..bd03c4f11 100644
--- a/Src/hist.c
+++ b/Src/hist.c
@@ -134,6 +134,8 @@ mod_export int hist_skip_flags;
/* Bits of histactive variable */
#define HA_ACTIVE (1<<0) /* History mechanism is active */
#define HA_NOINC (1<<1) /* Don't store, curhist not incremented */
+#define HA_INWORD (1<<2) /* We're inside a word, don't add
+ start and end markers */
/* Array of word beginnings and endings in current history line. */
@@ -222,13 +224,119 @@ static int histsave_stack_pos = 0;
static zlong histfile_linect;
+/* save history context */
+
+/**/
+void
+hist_context_save(struct hist_stack *hs, int toplevel)
+{
+ if (toplevel) {
+ /* top level, make this version visible to ZLE */
+ zle_chline = chline;
+ /* ensure line stored is NULL-terminated */
+ if (hptr)
+ *hptr = '\0';
+ }
+ hs->histactive = histactive;
+ hs->histdone = histdone;
+ hs->stophist = stophist;
+ hs->hline = chline;
+ hs->hptr = hptr;
+ hs->chwords = chwords;
+ hs->chwordlen = chwordlen;
+ hs->chwordpos = chwordpos;
+ hs->hgetc = hgetc;
+ hs->hungetc = hungetc;
+ hs->hwaddc = hwaddc;
+ hs->hwbegin = hwbegin;
+ hs->hwend = hwend;
+ hs->addtoline = addtoline;
+ hs->hlinesz = hlinesz;
+ /*
+ * We save and restore the command stack with history
+ * as it's visible to the user interactively, so if
+ * we're preserving history state we'll continue to
+ * show the current set of commands from input.
+ */
+ hs->cstack = cmdstack;
+ hs->csp = cmdsp;
+
+ stophist = 0;
+ chline = NULL;
+ hptr = NULL;
+ histactive = 0;
+ cmdstack = (unsigned char *)zalloc(CMDSTACKSZ);
+ cmdsp = 0;
+}
+
+/* restore history context */
+
+/**/
+void
+hist_context_restore(const struct hist_stack *hs, int toplevel)
+{
+ if (toplevel) {
+ /* Back to top level: don't need special ZLE value */
+ DPUTS(hs->hline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
+ zle_chline = NULL;
+ }
+ histactive = hs->histactive;
+ histdone = hs->histdone;
+ stophist = hs->stophist;
+ chline = hs->hline;
+ hptr = hs->hptr;
+ chwords = hs->chwords;
+ chwordlen = hs->chwordlen;
+ chwordpos = hs->chwordpos;
+ hgetc = hs->hgetc;
+ hungetc = hs->hungetc;
+ hwaddc = hs->hwaddc;
+ hwbegin = hs->hwbegin;
+ hwend = hs->hwend;
+ addtoline = hs->addtoline;
+ hlinesz = hs->hlinesz;
+ if (cmdstack)
+ zfree(cmdstack, CMDSTACKSZ);
+ cmdstack = hs->cstack;
+ cmdsp = hs->csp;
+}
+
+/*
+ * Mark that the current level of history is within a word whatever
+ * characters turn up, or turn that mode off. This is used for nested
+ * parsing of substitutions.
+ *
+ * The caller takes care only to turn this on or off at the start
+ * or end of recursive use of the same mode, so a single flag is
+ * good enough here.
+ */
+
+/**/
+void
+hist_in_word(int yesno)
+{
+ if (yesno)
+ histactive |= HA_INWORD;
+ else
+ histactive &= ~HA_INWORD;
+}
+
/* add a character to the current history word */
static void
ihwaddc(int c)
{
/* Only if history line exists and lexing has not finished. */
- if (chline && !(errflag || lexstop)) {
+ if (chline && !(errflag || lexstop) &&
+ /*
+ * If we're reading inside a word for command substitution
+ * we allow the lexer to expand aliases but don't deal
+ * with them here. Note matching code in ihungetc().
+ * TBD: it might be neater to deal with all aliases in this
+ * fashion as we never need the expansion in the history
+ * line, only in the lexer and above.
+ */
+ (inbufflags & (INP_ALIAS|INP_HIST)) != INP_ALIAS) {
/* Quote un-expanded bangs in the history line. */
if (c == bangchar && stophist < 2 && qbang)
/* If qbang is not set, we do not escape this bangchar as it's *
@@ -287,7 +395,8 @@ ihgetc(void)
c = histsubchar(c);
if (c < 0) {
/* bad expansion */
- errflag = lexstop = 1;
+ lexstop = 1;
+ errflag |= ERRFLAG_ERROR;
return ' ';
}
}
@@ -366,6 +475,7 @@ getsubsargs(char *subline, int *gbalp, int *cflagp)
zsfree(hsubl);
hsubl = ptr1;
} else if (!hsubl) { /* fail silently on this */
+ zsfree(ptr1);
zsfree(ptr2);
return 0;
}
@@ -415,9 +525,20 @@ histsubchar(int c)
static zlong mev = -1;
char *buf, *ptr;
char *sline;
+ int lexraw_mark;
Histent ehist;
size_t buflen;
+ /*
+ * If accumulating raw input for use in command substitution,
+ * we don't want the history text, so mark it for later removal.
+ * It would be better to do this at a level above the history
+ * and below the lexer --- but there isn't one.
+ *
+ * Include the character we are attempting to substitute.
+ */
+ lexraw_mark = zshlex_raw_mark(-1);
+
/* look, no goto's */
if (isfirstch && c == hatchar) {
int gbal = 0;
@@ -721,7 +842,7 @@ histsubchar(int c)
noerrs = 1;
parse_subst_string(sline);
noerrs = one;
- errflag = oef;
+ errflag = oef | (errflag & ERRFLAG_INT);
remnulargs(sline);
untokenize(sline);
}
@@ -751,6 +872,8 @@ histsubchar(int c)
}
}
+ zshlex_raw_back_to_mark(lexraw_mark);
+
/*
* Push the expanded value onto the input stack,
* marking this as a history word for purposes of the alias stack.
@@ -789,11 +912,16 @@ ihungetc(int c)
zlemetall--;
exlast++;
}
- DPUTS(hptr <= chline, "BUG: hungetc attempted at buffer start");
- hptr--;
- DPUTS(*hptr != (char) c, "BUG: wrong character in hungetc() ");
- qbang = (c == bangchar && stophist < 2 &&
- hptr > chline && hptr[-1] == '\\');
+ if ((inbufflags & (INP_ALIAS|INP_HIST)) != INP_ALIAS) {
+ DPUTS(hptr <= chline, "BUG: hungetc attempted at buffer start");
+ hptr--;
+ DPUTS(*hptr != (char) c, "BUG: wrong character in hungetc() ");
+ qbang = (c == bangchar && stophist < 2 &&
+ hptr > chline && hptr[-1] == '\\');
+ } else {
+ /* No active bangs in aliases */
+ qbang = 0;
+ }
if (doit)
inungetc(c);
if (!qbang)
@@ -813,6 +941,11 @@ strinbeg(int dohist)
strin++;
hbegin(dohist);
lexinit();
+ /*
+ * Also initialise some variables owned by the parser but
+ * used for communication between the parser and lexer.
+ */
+ init_parse_status();
}
/* done reading a string */
@@ -880,7 +1013,8 @@ hbegin(int dohist)
char *hf;
isfirstln = isfirstch = 1;
- errflag = histdone = 0;
+ errflag &= ~ERRFLAG_ERROR;
+ histdone = 0;
if (!dohist)
stophist = 2;
else if (dohist != 2)
@@ -1110,8 +1244,11 @@ static void
putoldhistentryontop(short keep_going)
{
static Histent next = NULL;
- Histent he = keep_going? next : hist_ring->down;
- next = he->down;
+ Histent he = (keep_going || !hist_ring) ? next : hist_ring->down;
+ if (he)
+ next = he->down;
+ else
+ return;
if (isset(HISTEXPIREDUPSFIRST) && !(he->node.flags & HIST_DUP)) {
static zlong max_unique_ct = 0;
if (!keep_going)
@@ -1151,7 +1288,7 @@ prepnexthistent(void)
freehistnode(&hist_ring->node);
}
- if (histlinect < histsiz) {
+ if (histlinect < histsiz || !hist_ring) {
he = (Histent)zshcalloc(sizeof *he);
if (!hist_ring)
hist_ring = he->up = he->down = he;
@@ -1395,28 +1532,17 @@ hend(Eprog prog)
return !(flag & HISTFLAG_NOEXEC || errflag);
}
-/* Gives current expansion word if not last word before chwordpos. */
-
-/**/
-int hwgetword = -1;
-
/* begin a word */
/**/
void
ihwbegin(int offset)
{
- if (stophist == 2)
+ if (stophist == 2 || (histactive & HA_INWORD) ||
+ (inbufflags & (INP_ALIAS|INP_HIST)) == INP_ALIAS)
return;
if (chwordpos%2)
chwordpos--; /* make sure we're on a word start, not end */
- /* If we're expanding an alias, we should overwrite the expansion
- * in the history.
- */
- if ((inbufflags & INP_ALIAS) && !(inbufflags & INP_HIST))
- hwgetword = chwordpos;
- else
- hwgetword = -1;
chwords[chwordpos++] = hptr - chline + offset;
}
@@ -1426,7 +1552,8 @@ ihwbegin(int offset)
void
ihwend(void)
{
- if (stophist == 2)
+ if (stophist == 2 || (histactive & HA_INWORD) ||
+ (inbufflags & (INP_ALIAS|INP_HIST)) == INP_ALIAS)
return;
if (chwordpos%2 && chline) {
/* end of word reached and we've already begun a word */
@@ -1437,13 +1564,6 @@ ihwend(void)
(chwordlen += 32) *
sizeof(short));
}
- if (hwgetword > -1 &&
- (inbufflags & INP_ALIAS) && !(inbufflags & INP_HIST)) {
- /* We want to reuse the current word position */
- chwordpos = hwgetword;
- /* Start from where previous word ended, if possible */
- hptr = chline + chwords[chwordpos ? chwordpos - 1 : 0];
- }
} else {
/* scrub that last word, it doesn't exist */
chwordpos--;
@@ -1467,17 +1587,17 @@ histbackword(void)
static void
hwget(char **startptr)
{
- int pos = hwgetword > -1 ? hwgetword : chwordpos - 2;
+ int pos = chwordpos - 2;
#ifdef DEBUG
/* debugging only */
- if (hwgetword == -1 && !chwordpos) {
+ if (!chwordpos) {
/* no words available */
DPUTS(1, "BUG: hwget() called with no words");
*startptr = "";
return;
- }
- else if (hwgetword == -1 && chwordpos%2) {
+ }
+ else if (chwordpos%2) {
DPUTS(1, "BUG: hwget() called in middle of word");
*startptr = "";
return;
@@ -1499,9 +1619,9 @@ hwrep(char *rep)
if (!strcmp(rep, start))
return;
-
+
hptr = start;
- chwordpos = (hwgetword > -1) ? hwgetword : chwordpos - 2;
+ chwordpos = chwordpos - 2;
hwbegin(0);
qbang = 1;
while (*rep)
@@ -1529,7 +1649,6 @@ hgetline(void)
/* reset line */
hptr = chline;
chwordpos = 0;
- hwgetword = -1;
return ret;
}
@@ -1699,11 +1818,12 @@ int
chrealpath(char **junkptr)
{
char *str;
-#ifdef HAVE_CANONICALIZE_FILE_NAME
+#ifdef HAVE_REALPATH
+# ifdef REALPATH_ACCEPTS_NULL
char *lastpos, *nonreal, *real;
-#else
-# ifdef HAVE_REALPATH
- char *lastpos, *nonreal, real[PATH_MAX];
+# else
+ char *lastpos, *nonreal, pathbuf[PATH_MAX];
+ char *real = pathbuf;
# endif
#endif
@@ -1714,7 +1834,7 @@ chrealpath(char **junkptr)
if (!chabspath(junkptr))
return 0;
-#if !defined(HAVE_REALPATH) && !defined(HAVE_CANONICALIZE_FILE_NAME)
+#ifndef HAVE_REALPATH
return 1;
#else
/*
@@ -1730,29 +1850,21 @@ chrealpath(char **junkptr)
nonreal = lastpos + 1;
while (!
-#ifdef HAVE_CANONICALIZE_FILE_NAME
- /*
- * This is a GNU extension to realpath(); it's the
- * same as calling realpath() with a NULL second argument
- * which uses malloc() to get memory. The alternative
- * interface is easier to test for, however.
- */
- (real = canonicalize_file_name(*junkptr))
+#ifdef REALPATH_ACCEPTS_NULL
+ /* realpath() with a NULL second argument uses malloc() to get
+ * memory so we don't need to worry about overflowing PATH_MAX */
+ (real = realpath(*junkptr, NULL))
#else
realpath(*junkptr, real)
#endif
) {
- if (errno == EINVAL || errno == ELOOP ||
- errno == ENAMETOOLONG || errno == ENOMEM)
+ if (errno == EINVAL || errno == ENOMEM)
return 0;
-#ifdef HAVE_CANONICALIZE_FILE_NAME
- if (!real)
- return 0;
-#endif
-
if (nonreal == *junkptr) {
- *real = '\0';
+#ifndef REALPATH_ACCEPTS_NULL
+ real = NULL;
+#endif
break;
}
@@ -1768,11 +1880,15 @@ chrealpath(char **junkptr)
str++;
}
- *junkptr = metafy(str = bicat(real, nonreal), -1, META_HEAPDUP);
- zsfree(str);
-#ifdef HAVE_CANONICALIZE_FILE_NAME
- free(real);
+ if (real) {
+ *junkptr = metafy(str = bicat(real, nonreal), -1, META_HEAPDUP);
+ zsfree(str);
+#ifdef REALPATH_ACCEPTS_NULL
+ free(real);
#endif
+ } else {
+ *junkptr = metafy(nonreal, lastpos - nonreal + 1, META_HEAPDUP);
+ }
#endif
return 1;
@@ -2139,10 +2255,10 @@ getargs(Histent elist, int arg1, int arg2)
}
/**/
-int
+static int
quote(char **tr)
{
- char *ptr, *rptr, **str = (char **)tr;
+ char *ptr, *rptr, **str = tr;
int len = 3;
int inquotes = 0;
@@ -2176,7 +2292,6 @@ quote(char **tr)
*rptr++ = *ptr;
*rptr++ = '\'';
*rptr++ = 0;
- str[1] = NULL;
return 0;
}
@@ -2184,7 +2299,7 @@ quote(char **tr)
static int
quotebreak(char **tr)
{
- char *ptr, *rptr, **str = (char **)tr;
+ char *ptr, *rptr, **str = tr;
int len = 3;
for (ptr = *str; *ptr; ptr++, len++)
@@ -2378,12 +2493,40 @@ readhistfile(char *fn, int err, int readflags)
|| (hist_ignore_all_dups && newflags & hist_skip_flags))
newflags |= HIST_MAKEUNIQUE;
while (fpos = ftell(in), (l = readhistline(0, &buf, &bufsiz, in))) {
- char *pt = buf;
+ char *pt;
+ int remeta = 0;
if (l < 0) {
zerr("corrupt history file %s", fn);
break;
}
+
+ /*
+ * Handle the special case that we're reading from an
+ * old shell with fewer meta characters, so we need to
+ * metafy some more. (It's not clear why the history
+ * file is metafied at all; some would say this is plain
+ * stupid. But we're stuck with it now without some
+ * hairy workarounds for compatibility).
+ *
+ * This is rare so doesn't need to be that efficient; just
+ * allocate space off the heap.
+ */
+ for (pt = buf; *pt; pt++) {
+ if (*pt == Meta && pt[1])
+ pt++;
+ else if (imeta(*pt)) {
+ remeta = 1;
+ break;
+ }
+ }
+ if (remeta) {
+ unmetafy(buf, &remeta);
+ pt = metafy(buf, remeta, META_USEHEAP);
+ } else {
+ pt = buf;
+ }
+
if (*pt == ':') {
pt++;
stim = zstrtol(pt, NULL, 0);
@@ -2443,8 +2586,6 @@ readhistfile(char *fn, int err, int readflags)
start = pt;
uselex = isset(HISTLEXWORDS) && !(readflags & HFILE_FAST);
histsplitwords(pt, &words, &nwords, &nwordpos, uselex);
- if (uselex)
- freeheap();
he->nwords = nwordpos/2;
if (he->nwords) {
@@ -2457,6 +2598,14 @@ readhistfile(char *fn, int err, int readflags)
freehistnode(&he->node);
curhist--;
}
+ /*
+ * Do this last out of paranoia in case use of
+ * heap is disguised...
+ */
+ if (uselex || remeta)
+ freeheap();
+ if (errflag & ERRFLAG_INT)
+ break;
}
if (start && readflags & HFILE_USE_OPTIONS) {
zsfree(lasthist.text);
@@ -2488,7 +2637,8 @@ static int
flockhistfile(char *fn, int keep_trying)
{
struct flock lck;
- int ctr = keep_trying ? 9 : 0;
+ long sleep_us = 0x10000; /* about 67 ms */
+ time_t end_time;
if (flock_fd >= 0)
return 0; /* already locked */
@@ -2501,13 +2651,22 @@ flockhistfile(char *fn, int keep_trying)
lck.l_start = 0;
lck.l_len = 0; /* lock the whole file */
+ /*
+ * Timeout is ten seconds.
+ */
+ end_time = time(NULL) + (time_t)10;
while (fcntl(flock_fd, F_SETLKW, &lck) == -1) {
- if (--ctr < 0) {
+ if (!keep_trying || time(NULL) >= end_time ||
+ /*
+ * Randomise wait to minimise clashes with shells exiting at
+ * the same time.
+ */
+ !zsleep_random(sleep_us, end_time)) {
close(flock_fd);
flock_fd = -1;
return 1;
}
- sleep(1);
+ sleep_us <<= 1;
}
return 0;
@@ -2743,7 +2902,7 @@ savehistfile(char *fn, int err, int writeflags)
static int lockhistct;
static int
-checklocktime(char *lockfile, time_t then)
+checklocktime(char *lockfile, long *sleep_usp, time_t then)
{
time_t now = time(NULL);
@@ -2753,9 +2912,19 @@ checklocktime(char *lockfile, time_t then)
return -1;
}
- if (now - then < 10)
- sleep(1);
- else
+ if (now - then < 10) {
+ /*
+ * To give the effect of a gradually increasing backoff,
+ * we'll sleep a period based on the time we've spent so far.
+ */
+ DPUTS(now < then, "time flowing backwards through history");
+ /*
+ * Randomise to minimise clashes with shells exiting at the same
+ * time.
+ */
+ (void)zsleep_random(*sleep_usp, then + 10);
+ *sleep_usp <<= 1;
+ } else
unlink(lockfile);
return 0;
@@ -2772,6 +2941,7 @@ lockhistfile(char *fn, int keep_trying)
{
int ct = lockhistct;
int ret = 0;
+ long sleep_us = 0x10000; /* about 67 ms */
if (!fn && !(fn = getsparam("HISTFILE")))
return 1;
@@ -2799,7 +2969,8 @@ lockhistfile(char *fn, int keep_trying)
#ifdef HAVE_LINK
# ifdef HAVE_SYMLINK
sprintf(pidbuf, "/pid-%ld/host-", (long)mypid);
- lnk = bicat(pidbuf, getsparam("HOST"));
+ lnk = getsparam("HOST");
+ lnk = bicat(pidbuf, lnk ? lnk : "");
/* We'll abuse fd as our success flag. */
while ((fd = symlink(lnk, lockfile)) < 0) {
if (errno != EEXIST) {
@@ -2814,7 +2985,7 @@ lockhistfile(char *fn, int keep_trying)
continue;
break;
}
- if (checklocktime(lockfile, sb.st_mtime) < 0) {
+ if (checklocktime(lockfile, &sleep_us, sb.st_mtime) < 0) {
ret = 1;
break;
}
@@ -2842,7 +3013,7 @@ lockhistfile(char *fn, int keep_trying)
continue;
ret = 2;
} else {
- if (checklocktime(lockfile, sb.st_mtime) < 0) {
+ if (checklocktime(lockfile, &sleep_us, sb.st_mtime) < 0) {
ret = 1;
break;
}
@@ -2870,7 +3041,7 @@ lockhistfile(char *fn, int keep_trying)
ret = 2;
break;
}
- if (checklocktime(lockfile, sb.st_mtime) < 0) {
+ if (checklocktime(lockfile, &sleep_us, sb.st_mtime) < 0) {
ret = 1;
break;
}
@@ -2988,7 +3159,7 @@ bufferwords(LinkList list, char *buf, int *index, int flags)
opts[RCQUOTES] = 0;
addedx = 0;
noerrs = 1;
- lexsave();
+ zcontext_save();
lexflags = flags | LEXFLAGS_ACTIVE;
/*
* Are we handling comments?
@@ -3108,7 +3279,7 @@ bufferwords(LinkList list, char *buf, int *index, int flags)
* double quotes. Whitespace in the middle is
* similarly retained, so just add the parentheses back.
*/
- p = tricat("((", tokstr, "))");
+ p = zhtricat("((", tokstr, "))");
}
break;
@@ -3162,7 +3333,7 @@ bufferwords(LinkList list, char *buf, int *index, int flags)
got = 1;
cur = num - 1;
}
- } while (tok != ENDINPUT && tok != LEXERR);
+ } while (tok != ENDINPUT && tok != LEXERR && !(errflag & ERRFLAG_INT));
if (buf && tok == LEXERR && tokstr && *tokstr) {
int plen;
untokenize((p = dupstring(tokstr)));
@@ -3182,10 +3353,10 @@ bufferwords(LinkList list, char *buf, int *index, int flags)
noaliases = ona;
strinend();
inpop();
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
nocomments = onc;
noerrs = ne;
- lexrestore();
+ zcontext_restore();
zlemetacs = ocs;
zlemetall = oll;
wb = owb;
@@ -3233,11 +3404,14 @@ histsplitwords(char *lineptr, short **wordsp, int *nwordsp, int *nwordposp,
char *start = lineptr;
if (uselex) {
- LinkList wordlist = bufferwords(NULL, lineptr, NULL,
- LEXFLAGS_COMMENTS_KEEP);
+ LinkList wordlist;
LinkNode wordnode;
int nwords_max;
+ wordlist = bufferwords(NULL, lineptr, NULL,
+ LEXFLAGS_COMMENTS_KEEP);
+ if (errflag)
+ return;
nwords_max = 2 * countlinknodes(wordlist);
if (nwords_max > nwords) {
*nwordsp = nwords = nwords_max;
@@ -3329,7 +3503,8 @@ histsplitwords(char *lineptr, short **wordsp, int *nwordsp, int *nwordposp,
if (*lptr == *wptr ||
(*lptr == '!' && *wptr == '|')) {
lptr++;
- wptr++;
+ if (!*++wptr)
+ break;
} else if (lptr[0] == '\\' &&
lptr[1] == '\n') {
/*
diff --git a/Src/init.c b/Src/init.c
index 6d005dce7..102276a64 100644
--- a/Src/init.c
+++ b/Src/init.c
@@ -107,7 +107,7 @@ loop(int toplevel, int justonce)
pushheap();
if (!toplevel)
- lexsave();
+ zcontext_save();
for (;;) {
freeheap();
if (stophist == 3) /* re-entry via preprompt() */
@@ -118,18 +118,32 @@ loop(int toplevel, int justonce)
if (interact && toplevel) {
int hstop = stophist;
stophist = 3;
+ /*
+ * Reset all errors including the interrupt error status
+ * immediately, so preprompt runs regardless of what
+ * just happened. We'll reset again below as a
+ * precaution to ensure we get back to the command line
+ * no matter what.
+ */
+ errflag = 0;
preprompt();
if (stophist != 3)
hbegin(1);
else
stophist = hstop;
+ /*
+ * Reset all errors, including user interupts.
+ * This is what allows ^C in an interactive shell
+ * to return us to the command line.
+ */
errflag = 0;
}
}
use_exit_printed = 0;
intr(); /* interrupts on */
lexinit(); /* initialize lexical state */
- if (!(prog = parse_event())) { /* if we couldn't parse a list */
+ if (!(prog = parse_event(ENDINPUT))) {
+ /* if we couldn't parse a list */
hend(NULL);
if ((tok == ENDINPUT && !errflag) ||
(tok == LEXERR && (!isset(SHINSTDIN) || !toplevel)) ||
@@ -178,7 +192,15 @@ loop(int toplevel, int justonce)
/* The only permanent storage is from getpermtext() */
zsfree(cmdstr);
- errflag = 0;
+ /*
+ * Note this does *not* remove a user interrupt error
+ * condition, even though we're at the top level loop:
+ * that would be inconsistent with the case where
+ * we didn't execute a preexec function. This is
+ * an implementation detail that an interrupting user
+ * does't care about.
+ */
+ errflag &= ~ERRFLAG_ERROR;
}
if (stopmsg) /* unset 'you have stopped jobs' flag */
stopmsg--;
@@ -205,7 +227,7 @@ loop(int toplevel, int justonce)
}
err = errflag;
if (!toplevel)
- lexrestore();
+ zcontext_restore();
popheap();
if (err)
@@ -243,12 +265,24 @@ parseargs(char **argv, char **runscript)
*/
opts[MONITOR] = 2; /* may be unset in init_io() */
opts[HASHDIRS] = 2; /* same relationship to INTERACTIVE */
+ opts[USEZLE] = 1; /* see below, related to SHINSTDIN */
opts[SHINSTDIN] = 0;
opts[SINGLECOMMAND] = 0;
if (parseopts(NULL, &argv, opts, &cmd, NULL))
exit(1);
+ /*
+ * USEZLE remains set if the shell has access to a terminal and
+ * is not reading from some other source as indicated by SHINSTDIN.
+ * SHINSTDIN becomes set below if there is no command argument,
+ * but it is the explicit setting (or not) that matters to USEZLE.
+ * USEZLE may also become unset in init_io() if the shell is not
+ * interactive or the terminal cannot be re-opened read/write.
+ */
+ if (opts[SHINSTDIN])
+ opts[USEZLE] = (opts[USEZLE] && isatty(0));
+
paramlist = znewlinklist();
if (*argv) {
if (unset(SHINSTDIN)) {
@@ -603,7 +637,7 @@ init_shout(void)
if (SHTTY == -1)
{
- /* Since we're interative, it's nice to have somewhere to write. */
+ /* Since we're interactive, it's nice to have somewhere to write. */
shout = stderr;
return;
}
@@ -616,7 +650,8 @@ init_shout(void)
/* Associate terminal file descriptor with a FILE pointer */
shout = fdopen(SHTTY, "w");
#ifdef _IOFBF
- setvbuf(shout, shoutbuf, _IOFBF, BUFSIZ);
+ if (shout)
+ setvbuf(shout, shoutbuf, _IOFBF, BUFSIZ);
#endif
gettyinfo(&shttyinfo); /* get tty state */
@@ -676,7 +711,7 @@ init_term(void)
{
if (isset(INTERACTIVE))
zerr("can't find terminal definition for %s", term);
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
termflags |= TERM_BAD;
return 0;
} else {
@@ -1036,7 +1071,6 @@ setupvals(void)
bufstack = znewlinklist();
hsubl = hsubr = NULL;
lastpid = 0;
- lastpid_status = -1L;
get_usage();
@@ -1163,10 +1197,13 @@ run_init_scripts(void)
if (islogin)
sourcehome(".profile");
noerrs = 2;
- if (s && !parsestr(s)) {
- singsub(&s);
- noerrs = 0;
- source(s);
+ if (s) {
+ s = dupstring(s);
+ if (!parsestr(&s)) {
+ singsub(&s);
+ noerrs = 0;
+ source(s);
+ }
}
noerrs = 0;
} else
@@ -1324,7 +1361,7 @@ source(char *s)
if (prog) {
pushheap();
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
execode(prog, 1, 0, "filecode");
popheap();
if (errflag)
@@ -1367,12 +1404,12 @@ source(char *s)
lineno = oldlineno; /* our current lineno */
loops = oloops; /* the # of nested loops we are in */
dosetopt(SHINSTDIN, oldshst, 1, opts); /* SHINSTDIN option */
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
if (!exit_pending)
retflag = 0;
scriptname = old_scriptname;
scriptfilename = old_scriptfilename;
- free(cmdstack);
+ zfree(cmdstack, CMDSTACKSZ);
cmdstack = ocs;
cmdsp = ocsp;
@@ -1608,8 +1645,7 @@ zsh_main(UNUSED(int argc), char **argv)
emulate(zsh_name, 1, &emulation, opts); /* initialises most options */
opts[LOGINSHELL] = (**argv == '-');
opts[PRIVILEGED] = (getuid() != geteuid() || getgid() != getegid());
- opts[USEZLE] = 1; /* may be unset in init_io() */
- /* sets INTERACTIVE, SHINSTDIN and SINGLECOMMAND */
+ /* sets ZLE, INTERACTIVE, SHINSTDIN and SINGLECOMMAND */
parseargs(argv, &runscript);
SHTTY = -1;
diff --git a/Src/input.c b/Src/input.c
index 4ac7e6ec8..4a5bf89c6 100644
--- a/Src/input.c
+++ b/Src/input.c
@@ -56,8 +56,9 @@
* inpop(), which effectively flushes any unread input as well as restoring
* the previous input state.
*
- * The internal flag INP_ALCONT shows that the stack element was pushed
- * by an alias expansion; it should not be needed elsewhere.
+ * The internal flags INP_ALCONT and INP_HISTCONT show that the stack
+ * element was pushed by an alias or history expansion; they should not
+ * be needed elsewhere.
*
* The global variable inalmore is set to indicate aliases should
* continue to be expanded because the last alias expansion ended
@@ -179,12 +180,12 @@ shingetline(void)
/* Get the next character from the input.
* Will call inputline() to get a new line where necessary.
*/
-
+
/**/
int
ingetc(void)
{
- int lastc;
+ int lastc = ' ';
if (lexstop)
return ' ';
@@ -196,7 +197,7 @@ ingetc(void)
continue;
if (((inbufflags & INP_LINENO) || !strin) && lastc == '\n')
lineno++;
- return lastc;
+ break;
}
/*
@@ -208,7 +209,7 @@ ingetc(void)
*/
if (!inbufct && (strin || errflag)) {
lexstop = 1;
- return ' ';
+ break;
}
/* If the next element down the input stack is a continuation of
* this, use it.
@@ -219,8 +220,10 @@ ingetc(void)
}
/* As a last resort, get some more input */
if (inputline())
- return ' ';
+ break;
}
+ zshlex_raw_add(lastc);
+ return lastc;
}
/* Read a line from the current command stream and store it as input */
@@ -291,7 +294,8 @@ inputline(void)
}
if (errflag) {
free(ingetcline);
- return lexstop = errflag = 1;
+ errflag |= ERRFLAG_ERROR;
+ return lexstop = 1;
}
if (isset(VERBOSE)) {
/* Output the whole line read so far. */
@@ -327,8 +331,38 @@ inputline(void)
}
}
isfirstch = 1;
- /* Put this into the input channel. */
- inputsetline(ingetcline, INP_FREE);
+ if ((inbufflags & INP_APPEND) && inbuf) {
+ /*
+ * We need new input but need to be able to back up
+ * over the old input, so append this line.
+ * Pushing the line onto the stack doesn't have the right
+ * effect.
+ *
+ * This is quite a simple and inefficient fix, but currently
+ * we only need it when backing up over a multi-line $((...
+ * that turned out to be a command substitution rather than
+ * a math substitution, which is a very special case.
+ * So it's not worth rewriting.
+ */
+ char *oinbuf = inbuf;
+ int newlen = strlen(ingetcline);
+ int oldlen = (int)(inbufptr - inbuf) + inbufleft;
+ if (inbufflags & INP_FREE) {
+ inbuf = realloc(inbuf, oldlen + newlen + 1);
+ } else {
+ inbuf = zalloc(oldlen + newlen + 1);
+ memcpy(inbuf, oinbuf, oldlen);
+ }
+ inbufptr += inbuf - oinbuf;
+ strcpy(inbuf + oldlen, ingetcline);
+ free(ingetcline);
+ inbufleft += newlen;
+ inbufct += newlen;
+ inbufflags |= INP_FREE;
+ } else {
+ /* Put this into the input channel. */
+ inputsetline(ingetcline, INP_FREE);
+ }
return 0;
}
@@ -390,12 +424,14 @@ inungetc(int c)
if (((inbufflags & INP_LINENO) || !strin) && c == '\n')
lineno--;
}
-#ifdef DEBUG
else if (!(inbufflags & INP_CONT)) {
+#ifdef DEBUG
/* Just for debugging */
fprintf(stderr, "Attempt to inungetc() at start of input.\n");
- }
#endif
+ zerr("Garbled input at %c (binary file as commands?)", c);
+ return;
+ }
else {
/*
* The character is being backed up from a previous input stack
@@ -411,7 +447,8 @@ inungetc(int c)
* we may need to restore an alias popped from the stack.
* Note this may be a dummy (history expansion) entry.
*/
- if (inbufptr == inbufpush && inbufflags & INP_ALCONT) {
+ if (inbufptr == inbufpush &&
+ (inbufflags & (INP_ALCONT|INP_HISTCONT))) {
/*
* Go back up the stack over all entries which were alias
* expansions and were pushed with nothing remaining to read.
@@ -420,11 +457,16 @@ inungetc(int c)
if (instacktop->alias)
instacktop->alias->inuse = 1;
instacktop++;
- } while ((instacktop->flags & INP_ALCONT) && !instacktop->bufleft);
- inbufflags = INP_CONT|INP_ALIAS;
+ } while ((instacktop->flags & (INP_ALCONT|INP_HISTCONT))
+ && !instacktop->bufleft);
+ if (inbufflags & INP_HISTCONT)
+ inbufflags = INP_CONT|INP_ALIAS|INP_HIST;
+ else
+ inbufflags = INP_CONT|INP_ALIAS;
inbufleft = 0;
inbuf = inbufptr = "";
}
+ zshlex_raw_back();
}
}
@@ -486,7 +528,7 @@ inpush(char *str, int flags, Alias inalias)
instacktop->bufptr = inbufptr;
instacktop->bufleft = inbufleft;
instacktop->bufct = inbufct;
- inbufflags &= ~INP_ALCONT;
+ inbufflags &= ~(INP_ALCONT|INP_HISTCONT);
if (flags & (INP_ALIAS|INP_HIST)) {
/*
* Text is expansion for history or alias, so continue
@@ -495,7 +537,10 @@ inpush(char *str, int flags, Alias inalias)
* and mark alias as in use.
*/
flags |= INP_CONT|INP_ALIAS;
- instacktop->flags = inbufflags | INP_ALCONT;
+ if (flags & INP_HIST)
+ instacktop->flags = inbufflags | INP_HISTCONT;
+ else
+ instacktop->flags = inbufflags | INP_ALCONT;
if ((instacktop->alias = inalias))
inalias->inuse = 1;
} else {
@@ -533,6 +578,24 @@ inpush(char *str, int flags, Alias inalias)
static void
inpoptop(void)
{
+ if (!lexstop) {
+ inbufflags &= ~(INP_ALCONT|INP_HISTCONT);
+ while (inbufptr > inbuf) {
+ inbufptr--;
+ inbufct++;
+ inbufleft++;
+ /*
+ * As elsewhere in input and history mechanisms:
+ * unwinding aliases and unwinding history have different
+ * implications as aliases are after the lexer while
+ * history is before, but they're both pushed onto
+ * the input stack.
+ */
+ if ((inbufflags & (INP_ALIAS|INP_HIST)) == INP_ALIAS)
+ zshlex_raw_back();
+ }
+ }
+
if (inbuf && (inbufflags & INP_FREE))
free(inbuf);
@@ -544,7 +607,7 @@ inpoptop(void)
inbufct = instacktop->bufct;
inbufflags = instacktop->flags;
- if (!(inbufflags & INP_ALCONT))
+ if (!(inbufflags & (INP_ALCONT|INP_HISTCONT)))
return;
if (instacktop->alias) {
diff --git a/Src/jobs.c b/Src/jobs.c
index bd95afb7a..948f61b01 100644
--- a/Src/jobs.c
+++ b/Src/jobs.c
@@ -104,15 +104,6 @@ int prev_errflag, prev_breaks, errbrk_saved;
/**/
int numpipestats, pipestats[MAX_PIPESTATS];
-/*
- * The status associated with the process lastpid.
- * -1 if not set and no associated lastpid
- * -2 if lastpid is set and status isn't yet
- * else the value returned by wait().
- */
-/**/
-long lastpid_status;
-
/* Diff two timevals for elapsed-time computations */
/**/
@@ -430,8 +421,10 @@ update_job(Job jn)
for (pn = jn->procs; pn; pn = pn->next) {
#ifdef WIFCONTINUED
- if (WIFCONTINUED(pn->status))
+ if (WIFCONTINUED(pn->status)) {
+ jn->stat &= ~STAT_STOPPED;
pn->status = SP_RUNNING;
+ }
#endif
if (pn->status == SP_RUNNING) /* some processes in this job are running */
return; /* so no need to update job table entry */
@@ -518,7 +511,7 @@ update_job(Job jn)
prev_errflag = errflag;
}
breaks = loops;
- errflag = 1;
+ errflag |= ERRFLAG_INT;
inerrflush();
}
} else {
@@ -535,7 +528,7 @@ update_job(Job jn)
prev_errflag = errflag;
}
breaks = loops;
- errflag = 1;
+ errflag |= ERRFLAG_INT;
inerrflush();
}
if (somestopped && jn->stat & STAT_SUPERJOB)
@@ -590,7 +583,7 @@ update_job(Job jn)
breaks = loops;
} else {
breaks = loops;
- errflag = 1;
+ errflag |= ERRFLAG_INT;
}
check_cursh_sig(sig);
}
@@ -713,6 +706,8 @@ printtime(struct timeval *real, child_times_t *ti, char *desc)
queue_signals();
if (!(s = getsparam("TIMEFMT")))
s = DEFAULT_TIMEFMT;
+ else
+ s = unmetafy(s, NULL);
for (; *s; s++)
if (*s == '%')
@@ -1309,14 +1304,6 @@ addproc(pid_t pid, char *text, int aux, struct timeval *bgtime)
{
Process pn, *pnlist;
- if (pid == lastpid && lastpid_status != -2L) {
- /*
- * The status for the previous lastpid is invalid.
- * Presumably process numbers have wrapped.
- */
- lastpid_status = -1L;
- }
-
DPUTS(thisjob == -1, "No valid job in addproc.");
pn = (Process) zshcalloc(sizeof *pn);
pn->pid = pid;
@@ -1459,12 +1446,19 @@ zwaitjob(int job, int wait_cmd)
restore_queue_signals(q);
return 128 + last_signal;
}
- /* Commenting this out makes ^C-ing a job started by a function
- stop the whole function again. But I guess it will stop
- something else from working properly, we have to find out
- what this might be. --oberon
+ /* Commenting this out makes ^C-ing a job started by a function
+ stop the whole function again. But I guess it will stop
+ something else from working properly, we have to find out
+ what this might be. --oberon
+
+ When attempting to separate errors and interrupts, we
+ assumed because of the previous comment it would be OK
+ to remove ERRFLAG_ERROR and leave ERRFLAG_INT set, since
+ that's the one related to ^C. But that doesn't work.
+ There's something more here we don't understand. --pws
+
+ errflag = 0; */
- errflag = 0; */
if (subsh) {
killjb(jn, SIGCONT);
jn->stat &= ~STAT_STOPPED;
@@ -1828,7 +1822,9 @@ static int hackspace;
void
init_jobs(char **argv, char **envp)
{
+#ifndef HAVE_SETPROCTITLE
char *p, *q;
+#endif
size_t init_bytes = MAXJOBS_ALLOC*sizeof(struct job);
/*
@@ -1940,6 +1936,122 @@ maybeshrinkjobtab(void)
unqueue_signals();
}
+/*
+ * Definitions for the background process stuff recorded below.
+ * This would be more efficient as a hash, but
+ * - that's quite heavyweight for something not needed very often
+ * - we need some kind of ordering as POSIX allows us to limit
+ * the size of the list to the value of _SC_CHILD_MAX and clearly
+ * we want to clear the oldest first
+ * - cases with a long list of background jobs where the user doesn't
+ * wait for a large number, and then does wait for one (the only
+ * inefficient case) are rare
+ * - in the context of waiting for an external process, looping
+ * over a list isn't so very inefficient.
+ * Enough excuses already.
+ */
+
+/* Data in the link list, a key (process ID) / value (exit status) pair. */
+struct bgstatus {
+ pid_t pid;
+ int status;
+};
+typedef struct bgstatus *Bgstatus;
+/* The list of those entries */
+LinkList bgstatus_list;
+/* Count of entries. Reaches value of _SC_CHILD_MAX and stops. */
+long bgstatus_count;
+
+/*
+ * Remove and free a bgstatus entry.
+ */
+static void rembgstatus(LinkNode node)
+{
+ zfree(remnode(bgstatus_list, node), sizeof(struct bgstatus));
+ bgstatus_count--;
+}
+
+/*
+ * Record the status of a background process that exited so we
+ * can execute the builtin wait for it.
+ *
+ * We can't execute the wait builtin for something that exited in the
+ * foreground as it's not visible to the user, so don't bother recording.
+ */
+
+/**/
+void
+addbgstatus(pid_t pid, int status)
+{
+ static long child_max;
+ Bgstatus bgstatus_entry;
+
+ if (!child_max) {
+#ifdef _SC_CHILD_MAX
+ child_max = sysconf(_SC_CHILD_MAX);
+ if (!child_max) /* paranoia */
+#endif
+ {
+ /* Be inventive */
+ child_max = 1024L;
+ }
+ }
+
+ if (!bgstatus_list) {
+ bgstatus_list = znewlinklist();
+ /*
+ * We're not always robust about memory failures, but
+ * this is pretty deep in the shell basics to be failing owing
+ * to memory, and a failure to wait is reported loudly, so test
+ * and fail silently here.
+ */
+ if (!bgstatus_list)
+ return;
+ }
+ if (bgstatus_count == child_max) {
+ /* Overflow. List is in order, remove first */
+ rembgstatus(firstnode(bgstatus_list));
+ }
+ bgstatus_entry = (Bgstatus)zalloc(sizeof(*bgstatus_entry));
+ if (!bgstatus_entry) {
+ /* See note above */
+ return;
+ }
+ bgstatus_entry->pid = pid;
+ bgstatus_entry->status = status;
+ if (!zaddlinknode(bgstatus_list, bgstatus_entry)) {
+ zfree(bgstatus_entry, sizeof(*bgstatus_entry));
+ return;
+ }
+ bgstatus_count++;
+}
+
+/*
+ * See if pid has a recorded exit status.
+ * Note we make no guarantee that the PIDs haven't wrapped, so this
+ * may not be the right process.
+ *
+ * This is only used by wait, which must only work on each
+ * pid once, so we need to remove the entry if we find it.
+ */
+
+static int getbgstatus(pid_t pid)
+{
+ LinkNode node;
+ Bgstatus bgstatus_entry;
+
+ if (!bgstatus_list)
+ return -1;
+ for (node = firstnode(bgstatus_list); node; incnode(node)) {
+ bgstatus_entry = (Bgstatus)getdata(node);
+ if (bgstatus_entry->pid == pid) {
+ int status = bgstatus_entry->status;
+ rembgstatus(node);
+ return status;
+ }
+ }
+ return -1;
+}
/* bg, disown, fg, jobs, wait: most of the job control commands are *
* here. They all take the same type of argument. Exception: wait can *
@@ -2085,10 +2197,7 @@ bin_fg(char *name, char **argv, Options ops, int func)
}
if (retval == 0)
retval = lastval2;
- } else if (isset(POSIXJOBS) &&
- pid == lastpid && lastpid_status >= 0L) {
- retval = (int)lastpid_status;
- } else {
+ } else if ((retval = getbgstatus(pid)) < 0) {
zwarnnam(name, "pid %d is not a child of this shell", pid);
/* presumably lastval2 doesn't tell us a heck of a lot? */
retval = 1;
@@ -2611,7 +2720,7 @@ findjobnam(const char *s)
for (jobnum = maxjob; jobnum >= 0; jobnum--)
if (!(jobtab[jobnum].stat & (STAT_SUBJOB | STAT_NOPRINT)) &&
jobtab[jobnum].stat && jobtab[jobnum].procs && jobnum != thisjob &&
- jobtab[jobnum].procs->text && strpfx(s, jobtab[jobnum].procs->text))
+ jobtab[jobnum].procs->text[0] && strpfx(s, jobtab[jobnum].procs->text))
return jobnum;
return -1;
}
@@ -2627,7 +2736,7 @@ acquire_pgrp(void)
long ttpgrp;
sigset_t blockset, oldset;
- if ((mypgrp = GETPGRP()) > 0) {
+ if ((mypgrp = GETPGRP()) >= 0) {
long lastpgrp = mypgrp;
sigemptyset(&blockset);
sigaddset(&blockset, SIGTTIN);
@@ -2672,8 +2781,11 @@ void
release_pgrp(void)
{
if (origpgrp != mypgrp) {
- attachtty(origpgrp);
- setpgrp(0, origpgrp);
+ /* in linux pid namespaces, origpgrp may never have been set */
+ if (origpgrp) {
+ attachtty(origpgrp);
+ setpgrp(0, origpgrp);
+ }
mypgrp = origpgrp;
}
}
diff --git a/Src/lex.c b/Src/lex.c
index 1a854f52b..c929bb9ba 100644
--- a/Src/lex.c
+++ b/Src/lex.c
@@ -35,7 +35,7 @@
/* tokens */
/**/
-mod_export char ztokens[] = "#$^*()$=|{}[]`<>>?~`,'\"\\\\";
+mod_export char ztokens[] = "#$^*(())$=|{}[]`<>>?~`,'\"\\\\";
/* parts of the current token */
@@ -90,6 +90,12 @@ int inalmore;
int nocorrect;
/*
+ * TBD: the following exported variables are part of the non-interface
+ * with ZLE for completion. They are poorly named and the whole
+ * scheme is incredibly brittle. One piece of robustness is applied:
+ * the variables are only set if LEXFLAGS_ZLE is set. Improvements
+ * should therefore concentrate on areas with this flag set.
+ *
* Cursor position and line length in zle when the line is
* metafied for access from the main shell.
*/
@@ -113,6 +119,16 @@ mod_export int addedx;
/**/
mod_export int wb, we;
+/**/
+mod_export int wordbeg;
+
+/**/
+mod_export int parbegin;
+
+/**/
+mod_export int parend;
+
+
/* 1 if aliases should not be expanded */
/**/
@@ -134,19 +150,20 @@ mod_export int noaliases;
/**/
mod_export int lexflags;
-/**/
-mod_export int wordbeg;
+/* don't recognize comments */
/**/
-mod_export int parbegin;
+mod_export int nocomments;
+
+/* add raw input characters while parsing command substitution */
/**/
-mod_export int parend;
+static int lex_add_raw;
-/* don't recognize comments */
+/* variables associated with the above */
-/**/
-mod_export int nocomments;
+static char *tokstr_raw;
+static struct lexbufstate lexbuf_raw;
/* text of punctuation tokens */
@@ -190,205 +207,58 @@ mod_export char *tokstrings[WHILE + 1] = {
/* lexical state */
static int dbparens;
-static int len = 0, bsiz = 256;
-static char *bptr;
-
-struct lexstack {
- struct lexstack *next;
-
- int incmdpos;
- int incond;
- int incasepat;
- int dbparens;
- int isfirstln;
- int isfirstch;
- int histactive;
- int histdone;
- int lexflags;
- int stophist;
- int hlinesz;
- char *hline;
- char *hptr;
- enum lextok tok;
- int isnewlin;
- char *tokstr;
- char *zshlextext;
- char *bptr;
- int bsiz;
- int len;
- short *chwords;
- int chwordlen;
- int chwordpos;
- int hwgetword;
- int lexstop;
- struct heredocs *hdocs;
- int (*hgetc) _((void));
- void (*hungetc) _((int));
- void (*hwaddc) _((int));
- void (*hwbegin) _((int));
- void (*hwend) _((void));
- void (*addtoline) _((int));
-
- int eclen, ecused, ecnpats;
- Wordcode ecbuf;
- Eccstr ecstrs;
- int ecsoffs, ecssub, ecnfunc;
-
- unsigned char *cstack;
- int csp;
- zlong toklineno;
-};
-
-static struct lexstack *lstack = NULL;
+static struct lexbufstate lexbuf = { NULL, 256, 0 };
-/* save the lexical state */
-
-/* is this a hack or what? */
+/* save lexical context */
/**/
-mod_export void
-lexsave(void)
+void
+lex_context_save(struct lex_stack *ls, int toplevel)
{
- struct lexstack *ls;
+ (void)toplevel;
- ls = (struct lexstack *)malloc(sizeof(struct lexstack));
-
- ls->incmdpos = incmdpos;
- ls->incond = incond;
- ls->incasepat = incasepat;
ls->dbparens = dbparens;
ls->isfirstln = isfirstln;
ls->isfirstch = isfirstch;
- ls->histactive = histactive;
- ls->histdone = histdone;
ls->lexflags = lexflags;
- ls->stophist = stophist;
- stophist = 0;
- if (!lstack) {
- /* top level, make this version visible to ZLE */
- zle_chline = chline;
- /* ensure line stored is NULL-terminated */
- if (hptr)
- *hptr = '\0';
- }
- ls->hline = chline;
- chline = NULL;
- ls->hptr = hptr;
- hptr = NULL;
- ls->hlinesz = hlinesz;
- ls->cstack = cmdstack;
- ls->csp = cmdsp;
- cmdstack = (unsigned char *)zalloc(CMDSTACKSZ);
+
ls->tok = tok;
- ls->isnewlin = isnewlin;
ls->tokstr = tokstr;
ls->zshlextext = zshlextext;
- ls->bptr = bptr;
- tokstr = zshlextext = bptr = NULL;
- ls->bsiz = bsiz;
- bsiz = 256;
- ls->len = len;
- ls->chwords = chwords;
- ls->chwordlen = chwordlen;
- ls->chwordpos = chwordpos;
- ls->hwgetword = hwgetword;
+ ls->lexbuf = lexbuf;
+ ls->lex_add_raw = lex_add_raw;
+ ls->tokstr_raw = tokstr_raw;
+ ls->lexbuf_raw = lexbuf_raw;
ls->lexstop = lexstop;
- ls->hdocs = hdocs;
- ls->hgetc = hgetc;
- ls->hungetc = hungetc;
- ls->hwaddc = hwaddc;
- ls->hwbegin = hwbegin;
- ls->hwend = hwend;
- ls->addtoline = addtoline;
- ls->eclen = eclen;
- ls->ecused = ecused;
- ls->ecnpats = ecnpats;
- ls->ecbuf = ecbuf;
- ls->ecstrs = ecstrs;
- ls->ecsoffs = ecsoffs;
- ls->ecssub = ecssub;
- ls->ecnfunc = ecnfunc;
ls->toklineno = toklineno;
- cmdsp = 0;
- inredir = 0;
- hdocs = NULL;
- histactive = 0;
- ecbuf = NULL;
-
- ls->next = lstack;
- lstack = ls;
+
+ tokstr = zshlextext = lexbuf.ptr = NULL;
+ lexbuf.siz = 256;
+ tokstr_raw = lexbuf_raw.ptr = NULL;
+ lexbuf_raw.siz = lexbuf_raw.len = lex_add_raw = 0;
}
-/* restore lexical state */
+/* restore lexical context */
/**/
mod_export void
-lexrestore(void)
+lex_context_restore(const struct lex_stack *ls, int toplevel)
{
- struct lexstack *ln = lstack;
-
- DPUTS(!lstack, "BUG: lexrestore() without lexsave()");
-
- queue_signals();
- lstack = lstack->next;
-
- if (!lstack) {
- /* Back to top level: don't need special ZLE value */
- DPUTS(ln->hline != zle_chline, "BUG: Ouch, wrong chline for ZLE");
- zle_chline = NULL;
- }
-
- incmdpos = ln->incmdpos;
- incond = ln->incond;
- incasepat = ln->incasepat;
- dbparens = ln->dbparens;
- isfirstln = ln->isfirstln;
- isfirstch = ln->isfirstch;
- histactive = ln->histactive;
- histdone = ln->histdone;
- lexflags = ln->lexflags;
- stophist = ln->stophist;
- chline = ln->hline;
- hptr = ln->hptr;
- if (cmdstack)
- zfree(cmdstack, CMDSTACKSZ);
- cmdstack = ln->cstack;
- cmdsp = ln->csp;
- tok = ln->tok;
- isnewlin = ln->isnewlin;
- tokstr = ln->tokstr;
- zshlextext = ln->zshlextext;
- bptr = ln->bptr;
- bsiz = ln->bsiz;
- len = ln->len;
- chwords = ln->chwords;
- chwordlen = ln->chwordlen;
- chwordpos = ln->chwordpos;
- hwgetword = ln->hwgetword;
- lexstop = ln->lexstop;
- hdocs = ln->hdocs;
- hgetc = ln->hgetc;
- hungetc = ln->hungetc;
- hwaddc = ln->hwaddc;
- hwbegin = ln->hwbegin;
- hwend = ln->hwend;
- addtoline = ln->addtoline;
- if (ecbuf)
- zfree(ecbuf, eclen);
- eclen = ln->eclen;
- ecused = ln->ecused;
- ecnpats = ln->ecnpats;
- ecbuf = ln->ecbuf;
- ecstrs = ln->ecstrs;
- ecsoffs = ln->ecsoffs;
- ecssub = ln->ecssub;
- ecnfunc = ln->ecnfunc;
- hlinesz = ln->hlinesz;
- toklineno = ln->toklineno;
- errflag = 0;
- free(ln);
-
- unqueue_signals();
+ (void)toplevel;
+
+ dbparens = ls->dbparens;
+ isfirstln = ls->isfirstln;
+ isfirstch = ls->isfirstch;
+ lexflags = ls->lexflags;
+ tok = ls->tok;
+ tokstr = ls->tokstr;
+ zshlextext = ls->zshlextext;
+ lexbuf = ls->lexbuf;
+ lex_add_raw = ls->lex_add_raw;
+ tokstr_raw = ls->tokstr_raw;
+ lexbuf_raw = ls->lexbuf_raw;
+ lexstop = ls->lexstop;
+ toklineno = ls->toklineno;
}
/**/
@@ -563,9 +433,7 @@ initlextabs(void)
void
lexinit(void)
{
- incond = incasepat = nocorrect =
- infor = dbparens = lexstop = 0;
- incmdpos = 1;
+ nocorrect = dbparens = lexstop = 0;
tok = ENDINPUT;
}
@@ -575,17 +443,18 @@ lexinit(void)
void
add(int c)
{
- *bptr++ = c;
- if (bsiz == ++len) {
- int newbsiz = bsiz * 2;
+ *lexbuf.ptr++ = c;
+ if (lexbuf.siz == ++lexbuf.len) {
+ int newbsiz = lexbuf.siz * 2;
- if (newbsiz > inbufct && inbufct > bsiz)
+ if (newbsiz > inbufct && inbufct > lexbuf.siz)
newbsiz = inbufct;
- bptr = len + (tokstr = (char *)hrealloc(tokstr, bsiz, newbsiz));
+ tokstr = (char *)hrealloc(tokstr, lexbuf.siz, newbsiz);
+ lexbuf.ptr = tokstr + lexbuf.len;
/* len == bsiz, so bptr is at the start of newly allocated memory */
- memset(bptr, 0, newbsiz - bsiz);
- bsiz = newbsiz;
+ memset(lexbuf.ptr, 0, newbsiz - lexbuf.siz);
+ lexbuf.siz = newbsiz;
}
}
@@ -604,48 +473,61 @@ add(int c)
} \
}
+enum {
+ CMD_OR_MATH_CMD,
+ CMD_OR_MATH_MATH,
+ CMD_OR_MATH_ERR
+};
+
/*
- * Return 1 for math, 0 for a command, 2 for an error. If it couldn't be
+ * Return one of the above. If it couldn't be
* parsed as math, but there was no gross error, it's a command.
*/
static int
cmd_or_math(int cs_type)
{
- int oldlen = len;
+ int oldlen = lexbuf.len;
int c;
+ int oinflags = inbufflags;
cmdpush(cs_type);
+ inbufflags |= INP_APPEND;
c = dquote_parse(')', 0);
+ if (!(oinflags & INP_APPEND))
+ inbufflags &= ~INP_APPEND;
cmdpop();
- *bptr = '\0';
+ *lexbuf.ptr = '\0';
if (!c) {
/* Successfully parsed, see if it was math */
c = hgetc();
if (c == ')')
- return 1; /* yes */
+ return CMD_OR_MATH_MATH; /* yes */
hungetc(c);
lexstop = 0;
c = ')';
} else if (lexstop) {
/* we haven't got anything to unget */
- return 2;
+ return CMD_OR_MATH_ERR;
}
/* else unsuccessful: unget the whole thing */
hungetc(c);
lexstop = 0;
- while (len > oldlen) {
- len--;
- hungetc(itok(*--bptr) ? ztokens[*bptr - Pound] : *bptr);
+ while (lexbuf.len > oldlen && !(errflag & ERRFLAG_ERROR)) {
+ lexbuf.len--;
+ hungetc(itok(*--lexbuf.ptr) ?
+ ztokens[*lexbuf.ptr - Pound] : *lexbuf.ptr);
}
+ if (errflag)
+ return CMD_OR_MATH_ERR;
hungetc('(');
- return 0;
+ return errflag ? CMD_OR_MATH_ERR : CMD_OR_MATH_CMD;
}
/*
* Parse either a $(( ... )) or a $(...)
- * Return 0 on success, 1 on failure.
+ * Return the same as cmd_or_math().
*/
static int
cmd_or_math_sub(void)
@@ -653,21 +535,23 @@ cmd_or_math_sub(void)
int c = hgetc(), ret;
if (c == '(') {
+ int lexpos = (int)(lexbuf.ptr - tokstr);
add(Inpar);
add('(');
- if ((ret = cmd_or_math(CS_MATHSUBST)) == 1) {
+ if ((ret = cmd_or_math(CS_MATHSUBST)) == CMD_OR_MATH_MATH) {
+ tokstr[lexpos] = Inparmath;
add(')');
- return 0;
+ return CMD_OR_MATH_MATH;
}
- if (ret == 2)
- return 1;
- bptr -= 2;
- len -= 2;
+ if (ret == CMD_OR_MATH_ERR)
+ return CMD_OR_MATH_ERR;
+ lexbuf.ptr -= 2;
+ lexbuf.len -= 2;
} else {
hungetc(c);
lexstop = 0;
}
- return skipcomm();
+ return skipcomm() ? CMD_OR_MATH_ERR : CMD_OR_MATH_CMD;
}
/* Check whether we're looking at valid numeric globbing syntax *
@@ -722,17 +606,18 @@ gettok(void)
if (lexstop)
return (errflag) ? LEXERR : ENDINPUT;
isfirstln = 0;
- wordbeg = inbufct - (qbang && c == bangchar);
+ if ((lexflags & LEXFLAGS_ZLE))
+ wordbeg = inbufct - (qbang && c == bangchar);
hwbegin(-1-(qbang && c == bangchar));
/* word includes the last character read and possibly \ before ! */
if (dbparens) {
- len = 0;
- bptr = tokstr = (char *) hcalloc(bsiz = LEX_HEAP_SIZE);
+ lexbuf.len = 0;
+ lexbuf.ptr = tokstr = (char *) hcalloc(lexbuf.siz = LEX_HEAP_SIZE);
hungetc(c);
cmdpush(CS_MATH);
c = dquote_parse(infor ? ';' : ')', 0);
cmdpop();
- *bptr = '\0';
+ *lexbuf.ptr = '\0';
if (!c && infor) {
infor--;
return DINPAR;
@@ -780,8 +665,9 @@ gettok(void)
* newlines being inserted into the history. */
if (lexflags & LEXFLAGS_COMMENTS_KEEP) {
- len = 0;
- bptr = tokstr = (char *)hcalloc(bsiz = LEX_HEAP_SIZE);
+ lexbuf.len = 0;
+ lexbuf.ptr = tokstr =
+ (char *)hcalloc(lexbuf.siz = LEX_HEAP_SIZE);
add(c);
}
hwend();
@@ -796,7 +682,7 @@ gettok(void)
peek = LEXERR;
else {
if (lexflags & LEXFLAGS_COMMENTS_KEEP) {
- *bptr = '\0';
+ *lexbuf.ptr = '\0';
if (!lexstop)
hungetc(c);
peek = STRING;
@@ -882,13 +768,14 @@ gettok(void)
return DINPAR;
}
if (incmdpos || (isset(SHGLOB) && !isset(KSHGLOB))) {
- len = 0;
- bptr = tokstr = (char *) hcalloc(bsiz = LEX_HEAP_SIZE);
+ lexbuf.len = 0;
+ lexbuf.ptr = tokstr = (char *)
+ hcalloc(lexbuf.siz = LEX_HEAP_SIZE);
switch (cmd_or_math(CS_MATH)) {
- case 1:
+ case CMD_OR_MATH_MATH:
return DINPAR;
- case 0:
+ case CMD_OR_MATH_CMD:
/*
* Not math, so we don't return the contents
* as a string in this case.
@@ -1032,8 +919,8 @@ gettokstr(int c, int sub)
peek = STRING;
if (!sub) {
- len = 0;
- bptr = tokstr = (char *) hcalloc(bsiz = LEX_HEAP_SIZE);
+ lexbuf.len = 0;
+ lexbuf.ptr = tokstr = (char *) hcalloc(lexbuf.siz = LEX_HEAP_SIZE);
}
for (;;) {
int act;
@@ -1069,7 +956,7 @@ gettokstr(int c, int sub)
if (fdpar) {
/* this is a single word `( )', treat as INOUTPAR */
add(c);
- *bptr = '\0';
+ *lexbuf.ptr = '\0';
return INOUTPAR;
}
if ((sub || in_brace_param) && isset(SHGLOB))
@@ -1108,12 +995,19 @@ gettokstr(int c, int sub)
c = Outbrack;
} else if (e == '(') {
add(String);
- c = cmd_or_math_sub();
- if (c) {
+ switch (cmd_or_math_sub()) {
+ case CMD_OR_MATH_CMD:
+ c = Outpar;
+ break;
+
+ case CMD_OR_MATH_MATH:
+ c = Outparmath;
+ break;
+
+ default:
peek = LEXERR;
goto brk;
}
- c = Outpar;
} else {
if (e == '{') {
add(c);
@@ -1144,9 +1038,9 @@ gettokstr(int c, int sub)
if (isset(SHGLOB)) {
if (sub || in_brace_param)
break;
- if (incasepat && !len)
+ if (incasepat && !lexbuf.len)
return INPAR;
- if (!isset(KSHGLOB) && len)
+ if (!isset(KSHGLOB) && lexbuf.len)
goto brk;
}
if (!in_brace_param) {
@@ -1203,9 +1097,9 @@ gettokstr(int c, int sub)
if (isset(IGNOREBRACES) || sub)
c = '{';
else {
- if (!len && incmdpos) {
+ if (!lexbuf.len && incmdpos) {
add('{');
- *bptr = '\0';
+ *lexbuf.ptr = '\0';
return STRING;
}
if (in_brace_param) {
@@ -1291,23 +1185,23 @@ gettokstr(int c, int sub)
incmdpos && !bct && !brct) {
char *t = tokstr;
if (idigit(*t))
- while (++t < bptr && idigit(*t));
+ while (++t < lexbuf.ptr && idigit(*t));
else {
- int sav = *bptr;
- *bptr = '\0';
+ int sav = *lexbuf.ptr;
+ *lexbuf.ptr = '\0';
t = itype_end(t, IIDENT, 0);
- if (t < bptr) {
+ if (t < lexbuf.ptr) {
skipparens(Inbrack, Outbrack, &t);
} else {
- *bptr = sav;
+ *lexbuf.ptr = sav;
}
}
if (*t == '+')
t++;
- if (t == bptr) {
+ if (t == lexbuf.ptr) {
e = hgetc();
if (e == '(' && incmdpos) {
- *bptr = '\0';
+ *lexbuf.ptr = '\0';
return ENVARRAY;
}
hungetc(e);
@@ -1326,13 +1220,25 @@ gettokstr(int c, int sub)
c = hgetc();
if (!lexstop)
continue;
- } else
+ } else {
add(Bnull);
+ if (c == STOUC(Meta)) {
+ c = hgetc();
+#ifdef DEBUG
+ if (lexstop) {
+ fputs("BUG: input terminated by Meta\n", stderr);
+ fflush(stderr);
+ goto brk;
+ }
+#endif
+ add(Meta);
+ }
+ }
if (lexstop)
goto brk;
break;
case LX2_QUOTE: {
- int strquote = (len && bptr[-1] == String);
+ int strquote = (lexbuf.len && lexbuf.ptr[-1] == String);
add(Snull);
cmdpush(CS_QUOTE);
@@ -1355,8 +1261,8 @@ gettokstr(int c, int sub)
else
add('\\');
} else if (!sub && isset(CSHJUNKIEQUOTES) && c == '\n') {
- if (bptr[-1] == '\\')
- bptr--, len--;
+ if (lexbuf.ptr[-1] == '\\')
+ lexbuf.ptr--, lexbuf.len--;
else
break;
}
@@ -1439,6 +1345,8 @@ gettokstr(int c, int sub)
break;
}
brk:
+ if (errflag)
+ return LEXERR;
hungetc(c);
if (unmatched)
zerr("unmatched %c", unmatched);
@@ -1446,15 +1354,16 @@ gettokstr(int c, int sub)
while(bct-- >= in_brace_param)
cmdpop();
zerr("closing brace expected");
- } else if (unset(IGNOREBRACES) && !sub && len > 1 &&
- peek == STRING && bptr[-1] == '}' && bptr[-2] != Bnull) {
+ } else if (unset(IGNOREBRACES) && !sub && lexbuf.len > 1 &&
+ peek == STRING && lexbuf.ptr[-1] == '}' &&
+ lexbuf.ptr[-2] != Bnull) {
/* hack to get {foo} command syntax work */
- bptr--;
- len--;
+ lexbuf.ptr--;
+ lexbuf.len--;
lexstop = 0;
hungetc('}');
}
- *bptr = '\0';
+ *lexbuf.ptr = '\0';
DPUTS(cmdsp != ocmdsp, "BUG: gettok: cmdstack changed.");
return peek;
}
@@ -1508,8 +1417,19 @@ dquote_parse(char endchar, int sub)
c = hgetc();
if (c == '(') {
add(Qstring);
- err = cmd_or_math_sub();
- c = Outpar;
+ switch (cmd_or_math_sub()) {
+ case CMD_OR_MATH_CMD:
+ c = Outpar;
+ break;
+
+ case CMD_OR_MATH_MATH:
+ c = Outparmath;
+ break;
+
+ default:
+ err = 1;
+ break;
+ }
} else if (c == '[') {
add(String);
add(Inbrack);
@@ -1617,44 +1537,58 @@ dquote_parse(char endchar, int sub)
return err;
}
-/* Tokenize a string given in s. Parsing is done as in double *
- * quotes. This is usually called before singsub(). */
+/*
+ * Tokenize a string given in s. Parsing is done as in double
+ * quotes. This is usually called before singsub().
+ *
+ * parsestr() is noisier, reporting an error if the parse failed.
+ *
+ * On entry, *s must point to a string allocated from the stack of
+ * exactly the right length, i.e. strlen(*s) + 1, as the string
+ * is used as the lexical token string whose memory management
+ * demands this. Usually the input string will therefore be
+ * the result of an immediately preceding dupstring().
+ */
/**/
mod_export int
-parsestr(char *s)
+parsestr(char **s)
{
int err;
if ((err = parsestrnoerr(s))) {
- untokenize(s);
- if (err > 32 && err < 127)
- zerr("parse error near `%c'", err);
- else
- zerr("parse error");
+ untokenize(*s);
+ if (!(errflag & ERRFLAG_INT)) {
+ if (err > 32 && err < 127)
+ zerr("parse error near `%c'", err);
+ else
+ zerr("parse error");
+ }
}
return err;
}
/**/
mod_export int
-parsestrnoerr(char *s)
+parsestrnoerr(char **s)
{
- int l = strlen(s), err;
+ int l = strlen(*s), err;
- lexsave();
- untokenize(s);
- inpush(dupstring(s), 0, NULL);
+ zcontext_save();
+ untokenize(*s);
+ inpush(dupstring(*s), 0, NULL);
strinbeg(0);
- len = 0;
- bptr = tokstr = s;
- bsiz = l + 1;
+ lexbuf.len = 0;
+ lexbuf.ptr = tokstr = *s;
+ lexbuf.siz = l + 1;
err = dquote_parse('\0', 1);
- *bptr = '\0';
+ if (tokstr)
+ *s = tokstr;
+ *lexbuf.ptr = '\0';
strinend();
inpop();
DPUTS(cmdsp, "BUG: parsestr: cmdstack not empty.");
- lexrestore();
+ zcontext_restore();
return err;
}
@@ -1673,27 +1607,27 @@ parse_subscript(char *s, int sub, int endchar)
if (!*s || *s == endchar)
return 0;
- lexsave();
+ zcontext_save();
untokenize(t = dupstring(s));
inpush(t, 0, NULL);
strinbeg(0);
- len = 0;
- bptr = tokstr = s;
- bsiz = l + 1;
+ lexbuf.len = 0;
+ lexbuf.ptr = tokstr = s;
+ lexbuf.siz = l + 1;
err = dquote_parse(endchar, sub);
if (err) {
- err = *bptr;
- *bptr = '\0';
+ err = *lexbuf.ptr;
+ *lexbuf.ptr = '\0';
untokenize(s);
- *bptr = err;
+ *lexbuf.ptr = err;
s = NULL;
} else {
- s = bptr;
+ s = lexbuf.ptr;
}
strinend();
inpop();
DPUTS(cmdsp, "BUG: parse_subscript: cmdstack not empty.");
- lexrestore();
+ zcontext_restore();
return s;
}
@@ -1711,29 +1645,30 @@ parse_subst_string(char *s)
if (!*s || !strcmp(s, nulstring))
return 0;
- lexsave();
+ zcontext_save();
untokenize(s);
inpush(dupstring(s), 0, NULL);
strinbeg(0);
- len = 0;
- bptr = tokstr = s;
- bsiz = l + 1;
+ lexbuf.len = 0;
+ lexbuf.ptr = tokstr = s;
+ lexbuf.siz = l + 1;
c = hgetc();
ctok = gettokstr(c, 1);
err = errflag;
strinend();
inpop();
DPUTS(cmdsp, "BUG: parse_subst_string: cmdstack not empty.");
- lexrestore();
- errflag = err;
+ zcontext_restore();
+ /* Keep any interrupt error status */
+ errflag = err | (errflag & ERRFLAG_INT);
if (ctok == LEXERR) {
untokenize(s);
return 1;
}
#ifdef DEBUG
/*
- * Historical note: we used to check here for olen (the value of len
- * before lexrestore()) == l, but that's not necessarily the case if
+ * Historical note: we used to check here for olen (the value of lexbuf.len
+ * before zcontext_restore()) == l, but that's not necessarily the case if
* we stripped an RCQUOTE.
*/
if (ctok != STRING || (errflag && !noerrs)) {
@@ -1787,7 +1722,7 @@ parse_subst_string(char *s)
/* Called below to report word positions. */
/**/
-mod_export void
+static void
gotword(void)
{
we = zlemetall + 1 - inbufct + (addedx == 2 ? 1 : 0);
@@ -1797,13 +1732,62 @@ gotword(void)
}
}
+/* Check if current lex text matches an alias: 1 if so, else 0 */
+
+static int
+checkalias(void)
+{
+ Alias an;
+
+ if (!zshlextext)
+ return 0;
+
+ if (!noaliases && isset(ALIASESOPT) &&
+ (!isset(POSIXALIASES) ||
+ (tok == STRING && !reswdtab->getnode(reswdtab, zshlextext)))) {
+ char *suf;
+
+ an = (Alias) aliastab->getnode(aliastab, zshlextext);
+ if (an && !an->inuse &&
+ ((an->node.flags & ALIAS_GLOBAL) ||
+ (incmdpos && tok == STRING) || inalmore)) {
+ if (!lexstop) {
+ /*
+ * Tokens that don't require a space after, get one,
+ * because they are treated as if preceded by one.
+ */
+ int c = hgetc();
+ hungetc(c);
+ if (!iblank(c))
+ inpush(" ", INP_ALIAS, 0);
+ }
+ inpush(an->text, INP_ALIAS, an);
+ if (an->text[0] == ' ' && !(an->node.flags & ALIAS_GLOBAL))
+ aliasspaceflag = 1;
+ lexstop = 0;
+ return 1;
+ }
+ if ((suf = strrchr(zshlextext, '.')) && suf[1] &&
+ suf > zshlextext && suf[-1] != Meta &&
+ (an = (Alias)sufaliastab->getnode(sufaliastab, suf+1)) &&
+ !an->inuse && incmdpos) {
+ inpush(dupstring(zshlextext), INP_ALIAS, NULL);
+ inpush(" ", INP_ALIAS, NULL);
+ inpush(an->text, INP_ALIAS, an);
+ lexstop = 0;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
/* expand aliases and reserved words */
/**/
int
exalias(void)
{
- Alias an;
Reswd rw;
hwend();
@@ -1815,7 +1799,9 @@ exalias(void)
if (!tokstr) {
zshlextext = tokstrings[tok];
- return 0;
+ if (tok == NEWLIN)
+ return 0;
+ return checkalias();
} else {
VARARR(char, copy, (strlen(tokstr) + 1));
@@ -1841,34 +1827,10 @@ exalias(void)
if (tok == STRING) {
/* Check for an alias */
- if (!noaliases && isset(ALIASESOPT) &&
- (!isset(POSIXALIASES) ||
- !reswdtab->getnode(reswdtab, zshlextext))) {
- char *suf;
-
- an = (Alias) aliastab->getnode(aliastab, zshlextext);
- if (an && !an->inuse &&
- ((an->node.flags & ALIAS_GLOBAL) || incmdpos || inalmore)) {
- inpush(an->text, INP_ALIAS, an);
- if (an->text[0] == ' ' && !(an->node.flags & ALIAS_GLOBAL))
- aliasspaceflag = 1;
- lexstop = 0;
- if (zshlextext == copy)
- zshlextext = tokstr;
- return 1;
- }
- if ((suf = strrchr(zshlextext, '.')) && suf[1] &&
- suf > zshlextext && suf[-1] != Meta &&
- (an = (Alias)sufaliastab->getnode(sufaliastab, suf+1)) &&
- !an->inuse && incmdpos) {
- inpush(dupstring(zshlextext), INP_ALIAS, NULL);
- inpush(" ", INP_ALIAS, NULL);
- inpush(an->text, INP_ALIAS, an);
- lexstop = 0;
- if (zshlextext == copy)
- zshlextext = tokstr;
- return 1;
- }
+ if ((zshlextext != copy || !isset(POSIXALIASES)) && checkalias()) {
+ if (zshlextext == copy)
+ zshlextext = tokstr;
+ return 1;
}
/* Then check for a reserved word */
@@ -1892,12 +1854,68 @@ exalias(void)
return 0;
}
-/* skip (...) */
+/**/
+void
+zshlex_raw_add(int c)
+{
+ if (!lex_add_raw)
+ return;
+
+ *lexbuf_raw.ptr++ = c;
+ if (lexbuf_raw.siz == ++lexbuf_raw.len) {
+ int newbsiz = lexbuf_raw.siz * 2;
+
+ tokstr_raw = (char *)hrealloc(tokstr_raw, lexbuf_raw.siz, newbsiz);
+ lexbuf_raw.ptr = tokstr_raw + lexbuf_raw.len;
+ memset(lexbuf_raw.ptr, 0, newbsiz - lexbuf_raw.siz);
+ lexbuf_raw.siz = newbsiz;
+ }
+}
+
+/**/
+void
+zshlex_raw_back(void)
+{
+ if (!lex_add_raw)
+ return;
+ lexbuf_raw.ptr--;
+ lexbuf_raw.len--;
+}
+
+/**/
+int
+zshlex_raw_mark(int offset)
+{
+ if (!lex_add_raw)
+ return 0;
+ return lexbuf_raw.len + offset;
+}
+
+/**/
+void
+zshlex_raw_back_to_mark(int mark)
+{
+ if (!lex_add_raw)
+ return;
+ lexbuf_raw.ptr = tokstr_raw + mark;
+ lexbuf_raw.len = mark;
+}
+
+/*
+ * Skip (...) for command-style substitutions: $(...), <(...), >(...)
+ *
+ * In order to ensure we don't stop at closing parentheses with
+ * some other syntactic significance, we'll parse the input until
+ * we find an unmatched closing parenthesis. However, we'll throw
+ * away the result of the parsing and just keep the string we've built
+ * up on the way.
+ */
/**/
static int
skipcomm(void)
{
+#ifdef ZSH_OLD_SKIPCOMM
int pct = 1, c, start = 1;
cmdpush(CS_CMDSUBST);
@@ -1922,7 +1940,7 @@ skipcomm(void)
c = hgetc();
break;
case '\'': {
- int strquote = bptr[-1] == '$';
+ int strquote = lexbuf.ptr[-1] == '$';
add(c);
STOPHIST
while ((c = hgetc()) != '\'' && !lexstop) {
@@ -1968,4 +1986,114 @@ skipcomm(void)
SETPAREND
cmdpop();
return lexstop;
+#else
+ char *new_tokstr;
+ int new_lexstop, new_lex_add_raw;
+ struct lexbufstate new_lexbuf;
+
+ cmdpush(CS_CMDSUBST);
+ SETPARBEGIN
+ add(Inpar);
+
+ new_lex_add_raw = lex_add_raw + 1;
+ if (!lex_add_raw) {
+ /*
+ * We'll combine the string so far with the input
+ * read in for the command substitution. To do this
+ * we'll just propagate the current tokstr etc. as the
+ * variables used for adding raw input, and
+ * ensure we swap those for the real tokstr etc. at the end.
+ *
+ * However, we need to save and restore the rest of the
+ * lexical and parse state as we're effectively parsing
+ * an internal string. Because we're still parsing it from
+ * the original input source (we have to --- we don't know
+ * when to stop inputting it otherwise and can't rely on
+ * the input being recoverable until we've read it) we need
+ * to keep the same history context.
+ */
+ new_tokstr = tokstr;
+ new_lexbuf = lexbuf;
+
+ zcontext_save_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
+ hist_in_word(1);
+ } else {
+ /*
+ * Set up for nested command subsitution, however
+ * we don't actually need the string until we get
+ * back to the top level and recover the lot.
+ * The $() body just appears empty.
+ *
+ * We do need to propagate the raw variables which would
+ * otherwise by cleared, though.
+ */
+ new_tokstr = tokstr_raw;
+ new_lexbuf = lexbuf_raw;
+
+ zcontext_save_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
+ }
+ tokstr_raw = new_tokstr;
+ lexbuf_raw = new_lexbuf;
+ lex_add_raw = new_lex_add_raw;
+ /*
+ * Don't do any ZLE specials down here: they're only needed
+ * when we return the string from the recursive parse.
+ * (TBD: this probably means we should be initialising lexflags
+ * more consistently.)
+ *
+ * Note that in that case we're still using the ZLE line reading
+ * function at the history layer --- this is consistent with the
+ * intention of maintaining the history and input layers across
+ * the recursive parsing.
+ */
+ lexflags &= ~LEXFLAGS_ZLE;
+
+ if (!parse_event(OUTPAR) || tok != OUTPAR)
+ lexstop = 1;
+ /* Outpar lexical token gets added in caller if present */
+
+ /*
+ * We're going to keep the full raw input string
+ * as the current token string after popping the stack.
+ */
+ new_tokstr = tokstr_raw;
+ new_lexbuf = lexbuf_raw;
+ /*
+ * We're also going to propagate the lexical state:
+ * if we couldn't parse the command substitution we
+ * can't continue.
+ */
+ new_lexstop = lexstop;
+
+ zcontext_restore_partial(ZCONTEXT_LEX|ZCONTEXT_PARSE);
+
+ if (lex_add_raw) {
+ /*
+ * Keep going, so retain the raw variables.
+ */
+ tokstr_raw = new_tokstr;
+ lexbuf_raw = new_lexbuf;
+ } else {
+ if (!new_lexstop) {
+ /* Ignore the ')' added on input */
+ new_lexbuf.len--;
+ *--new_lexbuf.ptr = '\0';
+ }
+
+ /*
+ * Convince the rest of lex.c we were examining a string
+ * all along.
+ */
+ tokstr = new_tokstr;
+ lexbuf = new_lexbuf;
+ lexstop = new_lexstop;
+ hist_in_word(0);
+ }
+
+ if (!lexstop)
+ SETPAREND
+ cmdpop();
+
+ return lexstop;
+#endif
}
diff --git a/Src/linklist.c b/Src/linklist.c
index 1e364fb4e..3aa8125d9 100644
--- a/Src/linklist.c
+++ b/Src/linklist.c
@@ -118,6 +118,8 @@ znewlinklist(void)
LinkList list;
list = (LinkList) zalloc(sizeof *list);
+ if (!list)
+ return NULL;
list->list.first = NULL;
list->list.last = &list->node;
list->list.flags = 0;
@@ -152,6 +154,8 @@ zinsertlinknode(LinkList list, LinkNode node, void *dat)
tmp = node->next;
node->next = new = (LinkNode) zalloc(sizeof *tmp);
+ if (!new)
+ return NULL;
new->prev = node;
new->dat = dat;
new->next = tmp;
diff --git a/Src/loop.c b/Src/loop.c
index 2f639fd5a..d025fbb9f 100644
--- a/Src/loop.c
+++ b/Src/loop.c
@@ -102,7 +102,10 @@ execfor(Estate state, int do_exec)
addlinknode(args, dupstring(*x));
}
}
- /* lastval = 0; */
+
+ if (!args || empty(args))
+ lastval = 0;
+
loops++;
pushheap();
cmdpush(CS_FOR);
@@ -238,10 +241,10 @@ execselect(Estate state, UNUSED(int do_exec))
}
if (!args || empty(args)) {
state->pc = end;
- return 1;
+ return 0;
}
loops++;
- /* lastval = 0; */
+
pushheap();
cmdpush(CS_SELECT);
usezle = interact && SHTTY != -1 && isset(USEZLE);
@@ -259,13 +262,14 @@ execselect(Estate state, UNUSED(int do_exec))
0, ZLCON_SELECT);
if (errflag)
str = NULL;
- errflag = oef;
+ /* Keep any user interrupt error status */
+ errflag = oef | (errflag & ERRFLAG_INT);
} else {
str = promptexpand(prompt3, 0, NULL, NULL, NULL);
zputs(str, stderr);
free(str);
fflush(stderr);
- str = fgets(zalloc(256), 256, inp);
+ str = fgets(zhalloc(256), 256, inp);
}
} else
str = (char *)getlinknode(bufstack);
@@ -518,14 +522,17 @@ execif(Estate state, int do_exec)
s = 1;
state->pc = next;
}
- noerrexit = olderrexit;
if (run) {
+ /* we need to ignore lastval until we reach execcmd() */
+ noerrexit = olderrexit ? olderrexit : lastval ? 2 : 0;
cmdpush(run == 2 ? CS_ELSE : (s ? CS_ELIFTHEN : CS_IFTHEN));
execlist(state, 1, do_exec);
cmdpop();
- } else
+ } else {
+ noerrexit = olderrexit;
lastval = 0;
+ }
state->pc = end;
return lastval;
@@ -632,6 +639,14 @@ execcase(Estate state, int do_exec)
zlong
try_errflag = -1;
+/**
+ * Corresponding interrupt error status form `try' block.
+ */
+
+/**/
+zlong
+try_interrupt = -1;
+
/**/
zlong
try_tryflag = 0;
@@ -643,7 +658,7 @@ exectry(Estate state, int do_exec)
Wordcode end, always;
int endval;
int save_retflag, save_breaks, save_contflag;
- zlong save_try_errflag, save_try_tryflag;
+ zlong save_try_errflag, save_try_tryflag, save_try_interrupt;
end = state->pc + WC_TRY_SKIP(state->pc[-1]);
always = state->pc + 1 + WC_TRY_SKIP(*state->pc);
@@ -659,8 +674,9 @@ exectry(Estate state, int do_exec)
try_tryflag = save_try_tryflag;
- /* Don't record errflag here, may be reset. */
- endval = lastval;
+ /* Don't record errflag here, may be reset. However, */
+ /* endval should show failure when there is an error. */
+ endval = lastval ? lastval : errflag;
freeheap();
@@ -669,7 +685,10 @@ exectry(Estate state, int do_exec)
/* The always clause. */
save_try_errflag = try_errflag;
- try_errflag = (zlong)errflag;
+ save_try_interrupt = try_interrupt;
+ try_errflag = (zlong)(errflag & ERRFLAG_ERROR);
+ try_interrupt = (zlong)((errflag & ERRFLAG_INT) ? 1 : 0);
+ /* We need to reset all errors to allow the block to execute */
errflag = 0;
save_retflag = retflag;
retflag = 0;
@@ -681,8 +700,16 @@ exectry(Estate state, int do_exec)
state->pc = always;
execlist(state, 1, do_exec);
- errflag = try_errflag ? 1 : 0;
+ if (try_errflag)
+ errflag |= ERRFLAG_ERROR;
+ else
+ errflag &= ~ERRFLAG_ERROR;
+ if (try_interrupt)
+ errflag |= ERRFLAG_INT;
+ else
+ errflag &= ~ERRFLAG_INT;
try_errflag = save_try_errflag;
+ try_interrupt = save_try_interrupt;
if (!retflag)
retflag = save_retflag;
if (!breaks)
diff --git a/Src/math.c b/Src/math.c
index 266569827..97a97b32b 100644
--- a/Src/math.c
+++ b/Src/math.c
@@ -288,11 +288,11 @@ static int type[TOKCOUNT] =
{
/* 0 */ LR, LR|OP_OP|OP_OPF, RL, RL, RL|OP_OP|OP_OPF,
/* 5 */ RL|OP_OP|OP_OPF, RL, RL, LR|OP_A2IO, LR|OP_A2IO,
-/* 10 */ LR|OP_A2IO, LR|OP_A2, LR|OP_A2, LR|OP_A2IO, LR|OP_A2,
+/* 10 */ LR|OP_A2IO, LR|OP_A2, LR|OP_A2, LR|OP_A2, LR|OP_A2,
/* 15 */ LR|OP_A2, LR|OP_A2IO, LR|OP_A2IO, LR|OP_A2IR, LR|OP_A2IR,
/* 20 */ LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, LR|OP_A2IR, BOOL|OP_A2IO,
/* 25 */ BOOL|OP_A2IO, LR|OP_A2IO, RL|OP_OP, RL|OP_OP, RL|OP_E2,
-/* 30 */ RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2IO,
+/* 30 */ RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2, RL|OP_E2,
/* 35 */ RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO, RL|OP_E2IO,
/* 40 */ BOOL|OP_E2IO, BOOL|OP_E2IO, RL|OP_A2IO, RL|OP_A2, RL|OP_OP,
/* 45 */ RL, RL, LR|OP_OPF, LR|OP_OPF, RL|OP_A2,
@@ -336,16 +336,27 @@ enum prec_type {
static mnumber
getmathparam(struct mathvalue *mptr)
{
+ mnumber result;
if (!mptr->pval) {
char *s = mptr->lval;
mptr->pval = (Value)zhalloc(sizeof(struct value));
if (!getvalue(mptr->pval, &s, 1))
{
mptr->pval = NULL;
+ if (isset(FORCEFLOAT)) {
+ result.type = MN_FLOAT;
+ result.u.d = 0.0;
+ return result;
+ }
return zero_mnumber;
}
}
- return getnumvalue(mptr->pval);
+ result = getnumvalue(mptr->pval);
+ if (isset(FORCEFLOAT) && result.type == MN_INTEGER) {
+ result.type = MN_FLOAT;
+ result.u.d = (double)result.u.l;
+ }
+ return result;
}
static mnumber
@@ -449,12 +460,14 @@ lexconstant(void)
nptr++;
if (*nptr == '0') {
+ int lowchar;
nptr++;
- if (*nptr == 'x' || *nptr == 'X') {
+ lowchar = tolower(*nptr);
+ if (lowchar == 'x' || lowchar == 'b') {
/* Let zstrtol parse number with base */
yyval.u.l = zstrtol_underscore(ptr, &ptr, 0, 1);
/* Should we set lastbase here? */
- lastbase = 16;
+ lastbase = (lowchar == 'b') ? 2 : 16;
if (isset(FORCEFLOAT))
{
yyval.type = MN_FLOAT;
@@ -878,6 +891,8 @@ getcvar(char *s)
static mnumber
setmathvar(struct mathvalue *mvp, mnumber v)
{
+ Param pm;
+
if (mvp->pval) {
/*
* This value may have been hanging around for a while.
@@ -907,7 +922,32 @@ setmathvar(struct mathvalue *mvp, mnumber v)
if (noeval)
return v;
untokenize(mvp->lval);
- setnparam(mvp->lval, v);
+ pm = setnparam(mvp->lval, v);
+ if (pm) {
+ /*
+ * If we are performing an assignment, we return the
+ * number with the same type as the parameter we are
+ * assigning to, in the spirit of the way assignments
+ * in C work. Note this was a change to long-standing
+ * zsh behaviour.
+ */
+ switch (PM_TYPE(pm->node.flags)) {
+ case PM_INTEGER:
+ if (v.type != MN_INTEGER) {
+ v.u.l = (zlong)v.u.d;
+ v.type = MN_INTEGER;
+ }
+ break;
+
+ case PM_EFLOAT:
+ case PM_FFLOAT:
+ if (v.type != MN_FLOAT) {
+ v.u.d = (double)v.u.l;
+ v.type = MN_FLOAT;
+ }
+ break;
+ }
+ }
return v;
}
@@ -1131,7 +1171,9 @@ op(int what)
* Any integer mod -1 is the same as any integer mod 1
* i.e. zero.
*/
- if (b.u.l == -1)
+ if (c.type == MN_FLOAT)
+ c.u.d = fmod(a.u.d, b.u.d);
+ else if (b.u.l == -1)
c.u.l = 0;
else
c.u.l = a.u.l % b.u.l;
@@ -1356,6 +1398,8 @@ matheval(char *s)
if (!mlevel)
outputradix = outputunderscore = 0;
+ if (*s == Nularg)
+ s++;
if (!*s) {
x.type = MN_INTEGER;
x.u.l = 0;
@@ -1393,6 +1437,8 @@ mathevalarg(char *s, char **ss)
*
* To avoid a more opaque error further in, bail out here.
*/
+ if (*s == Nularg)
+ s++;
if (!*s) {
zerr("bad math expression: empty string");
return (zlong)0;
diff --git a/Src/mem.c b/Src/mem.c
index 7e0667a33..b9569ea0c 100644
--- a/Src/mem.c
+++ b/Src/mem.c
@@ -79,6 +79,10 @@
#include <sys/mman.h>
+#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
#if defined(MAP_ANONYMOUS) && defined(MAP_PRIVATE)
#define USE_MMAP 1
diff --git a/Src/module.c b/Src/module.c
index 9e8b3cc2a..368254c29 100644
--- a/Src/module.c
+++ b/Src/module.c
@@ -1577,7 +1577,9 @@ try_load_module(char const *name)
if (l + (**pp ? strlen(*pp) : 1) > PATH_MAX)
continue;
sprintf(buf, "%s/%s.%s", **pp ? *pp : ".", name, DL_EXT);
- ret = dlopen(unmeta(buf), RTLD_LAZY | RTLD_GLOBAL);
+ unmetafy(buf, NULL);
+ if (*buf) /* dlopen(NULL) returns a handle to the main binary */
+ ret = dlopen(buf, RTLD_LAZY | RTLD_GLOBAL);
}
return ret;
@@ -1597,8 +1599,9 @@ do_load_module(char const *name, int silent)
ret = try_load_module(name);
if (!ret && !silent) {
#ifdef HAVE_DLERROR
+ char *errstr = dlerror();
zwarn("failed to load module `%s': %s", name,
- metafy(dlerror(), -1, META_USEHEAP));
+ errstr ? metafy(errstr, -1, META_HEAPDUP) : "empty module path");
#else
zwarn("failed to load module: %s", name);
#endif
@@ -3367,7 +3370,7 @@ mod_export int
handlefeatures(Module m, Features f, int **enables)
{
if (!enables || *enables)
- return setfeatureenables(m, f, *enables);
+ return setfeatureenables(m, f, enables ? *enables : NULL);
*enables = getfeatureenables(m, f);
return 0;
}
diff --git a/Src/options.c b/Src/options.c
index 6e4e7b911..3e3e07474 100644
--- a/Src/options.c
+++ b/Src/options.c
@@ -766,7 +766,17 @@ dosetopt(int optno, int value, int force, char *new_opts)
#ifdef HAVE_SETUID
setuid(getuid());
setgid(getgid());
-#endif /* HAVE_SETUID */
+ if (setuid(getuid())) {
+ zwarn("failed to change user ID: %e", errno);
+ return -1;
+ } else if (setgid(getgid())) {
+ zwarn("failed to change group ID: %e", errno);
+ return -1;
+ }
+#else
+ zwarn("setuid not available");
+ return -1;
+#endif /* not HAVE_SETUID */
#ifdef JOB_CONTROL
} else if (!force && optno == MONITOR && value) {
if (new_opts[optno] == value)
diff --git a/Src/params.c b/Src/params.c
index 61edc5d08..d53b6ca7e 100644
--- a/Src/params.c
+++ b/Src/params.c
@@ -331,6 +331,7 @@ IPDEF5("SHLVL", &shlvl, varinteger_gsu),
#define IPDEF6(A,B,F) {{NULL,A,PM_INTEGER|PM_SPECIAL|PM_DONTIMPORT},BR((void *)B),GSU(F),10,0,NULL,NULL,NULL,0}
IPDEF6("OPTIND", &zoptind, varinteger_gsu),
IPDEF6("TRY_BLOCK_ERROR", &try_errflag, varinteger_gsu),
+IPDEF6("TRY_BLOCK_INTERRUPT", &try_interrupt, varinteger_gsu),
#define IPDEF7(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
#define IPDEF7U(A,B) {{NULL,A,PM_SCALAR|PM_SPECIAL|PM_UNSET},BR((void *)B),GSU(varscalar_gsu),0,0,NULL,NULL,NULL,0}
@@ -641,8 +642,16 @@ split_env_string(char *env, char **name, char **value)
return 0;
tenv = strcpy(zhalloc(strlen(env) + 1), env);
- for (str = tenv; *str && *str != '='; str++)
- ;
+ for (str = tenv; *str && *str != '='; str++) {
+ if (STOUC(*str) >= 128) {
+ /*
+ * We'll ignore environment variables with names not
+ * from the portable character set since we don't
+ * know of a good reason to accept them.
+ */
+ return 0;
+ }
+ }
if (str != tenv && *str == '=') {
*str = '\0';
*name = tenv;
@@ -865,10 +874,14 @@ createparam(char *name, int flags)
DPUTS(oldpm && oldpm->level > locallevel,
"BUG: old local parameter not deleted");
if (oldpm && (oldpm->level == locallevel || !(flags & PM_LOCAL))) {
+ if (isset(POSIXBUILTINS) && (oldpm->node.flags & PM_READONLY)) {
+ zerr("read-only variable: %s", name);
+ return NULL;
+ }
if (!(oldpm->node.flags & PM_UNSET) || (oldpm->node.flags & PM_SPECIAL)) {
oldpm->node.flags &= ~PM_UNSET;
if ((oldpm->node.flags & PM_SPECIAL) && oldpm->ename) {
- Param altpm =
+ Param altpm =
(Param) paramtab->getnode(paramtab, oldpm->ename);
if (altpm)
altpm->node.flags &= ~PM_UNSET;
@@ -918,7 +931,15 @@ shempty(void)
{
}
-/* Create a simple special hash parameter. */
+/*
+ * Create a simple special hash parameter.
+ *
+ * This is for hashes added internally --- it's not possible to add
+ * special hashes from shell commands. It's currently used
+ * - by addparamdef() for special parameters in the zsh/parameter
+ * module
+ * - by ztie for special parameters tied to databases.
+ */
/**/
mod_export Param
@@ -930,7 +951,22 @@ createspecialhash(char *name, GetNodeFunc get, ScanTabFunc scan, int flags)
if (!(pm = createparam(name, PM_SPECIAL|PM_HASHED|flags)))
return NULL;
- pm->level = pm->old ? locallevel : 0;
+ /*
+ * If there's an old parameter, we'll put the new one at
+ * the current locallevel, so that the old parameter is
+ * exposed again after leaving the function. Otherwise,
+ * we'll leave it alone. Usually this means the parameter
+ * will stay in place until explicitly unloaded, however
+ * if the parameter was previously unset within a function
+ * we'll inherit the level of that function and follow the
+ * standard convention that the parameter remains local
+ * even if unset.
+ *
+ * These semantics are similar to those of a normal parameter set
+ * within a function without a local definition.
+ */
+ if (pm->old)
+ pm->level = locallevel;
pm->gsu.h = (flags & PM_READONLY) ? &stdhash_gsu :
&nullsethash_gsu;
pm->u.hash = ht = newhashtable(0, name, NULL);
@@ -1251,7 +1287,8 @@ getarg(char **str, int *inv, Value v, int a2, zlong *w,
if (ishash && (keymatch || !rev))
remnulargs(s);
if (needtok) {
- if (parsestr(s))
+ s = dupstring(s);
+ if (parsestr(&s))
return 0;
singsub(&s);
} else if (rev)
@@ -2654,7 +2691,7 @@ assignsparam(char *s, char *val, int flags)
if (!isident(s)) {
zerr("not an identifier: %s", s);
zsfree(val);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return NULL;
}
queue_signals();
@@ -2783,7 +2820,7 @@ assignaparam(char *s, char **val, int flags)
if (!isident(s)) {
zerr("not an identifier: %s", s);
freearray(val);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return NULL;
}
queue_signals();
@@ -2799,7 +2836,7 @@ assignaparam(char *s, char **val, int flags)
zerr("%s: attempt to set slice of associative array",
v->pm->node.nam);
freearray(val);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return NULL;
}
v = NULL;
@@ -2870,13 +2907,13 @@ sethparam(char *s, char **val)
if (!isident(s)) {
zerr("not an identifier: %s", s);
freearray(val);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return NULL;
}
if (strchr(s, '[')) {
freearray(val);
zerr("nested associative arrays not yet supported");
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return NULL;
}
if (unset(EXECOPT))
@@ -2916,7 +2953,7 @@ setnparam(char *s, mnumber val)
if (!isident(s)) {
zerr("not an identifier: %s", s);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return NULL;
}
if (unset(EXECOPT))
@@ -4368,9 +4405,18 @@ zputenv(char *str)
char *ptr;
int ret;
- for (ptr = str; *ptr && *ptr != '='; ptr++)
+ for (ptr = str; *ptr && STOUC(*ptr) < 128 && *ptr != '='; ptr++)
;
- if (*ptr) {
+ if (STOUC(*ptr) >= 128) {
+ /*
+ * Environment variables not in the portable character
+ * set are non-standard and we don't really know of
+ * a use for them.
+ *
+ * We'll disable until someone complains.
+ */
+ return 1;
+ } else if (*ptr) {
*ptr = '\0';
ret = setenv(str, ptr+1, 1);
*ptr = '=';
diff --git a/Src/parse.c b/Src/parse.c
index 433efb94e..985eb8e71 100644
--- a/Src/parse.c
+++ b/Src/parse.c
@@ -31,7 +31,7 @@
#include "parse.pro"
/* != 0 if we are about to read a command word */
-
+
/**/
mod_export int incmdpos;
@@ -71,13 +71,14 @@ struct heredocs *hdocs;
#define YYERROR(O) { tok = LEXERR; ecused = (O); return 0; }
#define YYERRORV(O) { tok = LEXERR; ecused = (O); return; }
-#define COND_ERROR(X,Y) do { \
- zwarn(X,Y); \
- herrflush(); \
- if (noerrs != 2) \
- errflag = 1; \
- YYERROR(ecused) \
-} while(0)
+#define COND_ERROR(X,Y) \
+ do { \
+ zwarn(X,Y); \
+ herrflush(); \
+ if (noerrs != 2) \
+ errflag |= ERRFLAG_ERROR; \
+ YYERROR(ecused) \
+ } while(0)
/*
@@ -241,6 +242,67 @@ int ecsoffs, ecssub, ecnfunc;
#define EC_DOUBLE_THRESHOLD 32768
#define EC_INCREMENT 1024
+/* save parse context */
+
+/**/
+void
+parse_context_save(struct parse_stack *ps, int toplevel)
+{
+ (void)toplevel;
+
+ ps->incmdpos = incmdpos;
+ ps->aliasspaceflag = aliasspaceflag;
+ ps->incond = incond;
+ ps->inredir = inredir;
+ ps->incasepat = incasepat;
+ ps->isnewlin = isnewlin;
+ ps->infor = infor;
+
+ ps->hdocs = hdocs;
+ ps->eclen = eclen;
+ ps->ecused = ecused;
+ ps->ecnpats = ecnpats;
+ ps->ecbuf = ecbuf;
+ ps->ecstrs = ecstrs;
+ ps->ecsoffs = ecsoffs;
+ ps->ecssub = ecssub;
+ ps->ecnfunc = ecnfunc;
+ ecbuf = NULL;
+ hdocs = NULL;
+}
+
+/* restore parse context */
+
+/**/
+void
+parse_context_restore(const struct parse_stack *ps, int toplevel)
+{
+ (void)toplevel;
+
+ if (ecbuf)
+ zfree(ecbuf, eclen);
+
+ incmdpos = ps->incmdpos;
+ aliasspaceflag = ps->aliasspaceflag;
+ incond = ps->incond;
+ inredir = ps->inredir;
+ incasepat = ps->incasepat;
+ incasepat = ps->incasepat;
+ isnewlin = ps->isnewlin;
+ infor = ps->infor;
+
+ hdocs = ps->hdocs;
+ eclen = ps->eclen;
+ ecused = ps->ecused;
+ ecnpats = ps->ecnpats;
+ ecbuf = ps->ecbuf;
+ ecstrs = ps->ecstrs;
+ ecsoffs = ps->ecsoffs;
+ ecssub = ps->ecssub;
+ ecnfunc = ps->ecnfunc;
+
+ errflag &= ~ERRFLAG_ERROR;
+}
/* Adjust pointers in here-doc structs. */
@@ -358,9 +420,25 @@ ecstrcode(char *s)
} while (0)
+/**/
+mod_export void
+init_parse_status(void)
+{
+ /*
+ * These variables are currently declared by the parser, so we
+ * initialise them here. Possibly they are more naturally declared
+ * by the lexical anaylser; however, as they are used for signalling
+ * between the two it's a bit ambiguous. We clear them when
+ * using the lexical analyser for strings as well as here.
+ */
+ incasepat = incond = inredir = infor = 0;
+ incmdpos = 1;
+}
+
/* Initialise wordcode buffer. */
-static void
+/**/
+void
init_parse(void)
{
if (ecbuf) zfree(ecbuf, eclen);
@@ -371,6 +449,8 @@ init_parse(void)
ecsoffs = ecnpats = 0;
ecssub = 0;
ecnfunc = 0;
+
+ init_parse_status();
}
/* Build eprog. */
@@ -442,11 +522,15 @@ clear_hdocs()
* event : ENDINPUT
* | SEPER
* | sublist [ SEPER | AMPER | AMPERBANG ]
+ *
+ * cmdsubst indicates our event is part of a command-style
+ * substitution terminated by the token indicationg, usual closing
+ * parenthesis. In other cases endtok is ENDINPUT.
*/
/**/
Eprog
-parse_event(void)
+parse_event(int endtok)
{
tok = ENDINPUT;
incmdpos = 1;
@@ -454,36 +538,42 @@ parse_event(void)
zshlex();
init_parse();
- if (!par_event()) {
+ if (!par_event(endtok)) {
clear_hdocs();
return NULL;
}
+ if (endtok != ENDINPUT) {
+ /* don't need to build an eprog for this */
+ return &dummy_eprog;
+ }
return bld_eprog(1);
}
/**/
-static int
-par_event(void)
+int
+par_event(int endtok)
{
int r = 0, p, c = 0;
while (tok == SEPER) {
- if (isnewlin > 0)
+ if (isnewlin > 0 && endtok == ENDINPUT)
return 0;
zshlex();
}
if (tok == ENDINPUT)
return 0;
+ if (tok == endtok)
+ return 0;
p = ecadd(0);
if (par_sublist(&c)) {
- if (tok == ENDINPUT) {
+ if (tok == ENDINPUT || tok == endtok) {
set_list_code(p, Z_SYNC, c);
r = 1;
} else if (tok == SEPER) {
set_list_code(p, Z_SYNC, c);
- if (isnewlin <= 0)
+ if (isnewlin <= 0 || endtok != ENDINPUT)
zshlex();
r = 1;
} else if (tok == AMPER) {
@@ -506,15 +596,16 @@ par_event(void)
yyerror(1);
herrflush();
if (noerrs != 2)
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
ecused--;
return 0;
} else {
int oec = ecused;
- if (!par_event()) {
+ if (!par_event(endtok)) {
ecused = oec;
ecbuf[p] |= wc_bdata(Z_END);
+ return errflag ? 0 : 1;
}
}
return 1;
@@ -527,9 +618,8 @@ parse_list(void)
int c = 0;
tok = ENDINPUT;
- incmdpos = 1;
- zshlex();
init_parse();
+ zshlex();
par_list(&c);
if (tok != ENDINPUT) {
clear_hdocs();
@@ -2330,7 +2420,7 @@ yyerror(int noerr)
for (t0 = 0; t0 != 20; t0++)
if (!t || !t[t0] || t[t0] == '\n')
break;
- if (!(histdone & HISTFLAG_NOEXEC)) {
+ if (!(histdone & HISTFLAG_NOEXEC) && !(errflag & ERRFLAG_INT)) {
if (t0 == 20)
zwarn("parse error near `%l...'", t, 20);
else if (t0)
@@ -2339,7 +2429,7 @@ yyerror(int noerr)
zwarn("parse error");
}
if (!noerr && noerrs != 2)
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
}
/*
@@ -2590,7 +2680,7 @@ eccopyredirs(Estate s)
{
Wordcode pc = s->pc;
wordcode code = *pc;
- int ncode, ncodes = 0, r, type;
+ int ncode, ncodes = 0, r;
if (wc_code(code) != WC_REDIR)
return NULL;
@@ -2598,7 +2688,9 @@ eccopyredirs(Estate s)
init_parse();
while (wc_code(code) == WC_REDIR) {
- type = WC_REDIR_TYPE(code);
+#ifdef DEBUG
+ int type = WC_REDIR_TYPE(code);
+#endif
DPUTS(type == REDIR_HEREDOC || type == REDIR_HEREDOCDASH,
"unexpanded here document");
@@ -3029,7 +3121,7 @@ build_dump(char *nam, char *dump, char **files, int ali, int map, int flags)
file = metafy(file, flen, META_REALLOC);
if (!(prog = parse_string(file, 1)) || errflag) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
close(dfd);
zfree(file, flen);
zwarnnam(nam, "can't read file: %s", *files);
@@ -3139,7 +3231,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
for (hn = shfunctab->nodes[i]; hn; hn = hn->next)
if (cur_add_func(nam, (Shfunc) hn, lnames, progs,
&hlen, &tlen, what)) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
close(dfd);
unlink(dump);
return 1;
@@ -3164,7 +3256,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
pattry(pprog, hn->nam) &&
cur_add_func(nam, (Shfunc) hn, lnames, progs,
&hlen, &tlen, what)) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
close(dfd);
unlink(dump);
return 1;
@@ -3175,13 +3267,13 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
if (errflag ||
!(shf = (Shfunc) shfunctab->getnode(shfunctab, *names))) {
zwarnnam(nam, "unknown function: %s", *names);
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
close(dfd);
unlink(dump);
return 1;
}
if (cur_add_func(nam, shf, lnames, progs, &hlen, &tlen, what)) {
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
close(dfd);
unlink(dump);
return 1;
@@ -3190,7 +3282,7 @@ build_cur_dump(char *nam, char *dump, char **names, int match, int map,
}
if (empty(progs)) {
zwarnnam(nam, "no functions");
- errflag = 0;
+ errflag &= ~ERRFLAG_ERROR;
close(dfd);
unlink(dump);
return 1;
diff --git a/Src/pattern.c b/Src/pattern.c
index df5e602ca..17cd40c23 100644
--- a/Src/pattern.c
+++ b/Src/pattern.c
@@ -3622,7 +3622,7 @@ patmatchrange(char *range, int ch, int *indptr, int *mtp)
return 1;
break;
case PP_PRINT:
- if (isprint(ch))
+ if (ISPRINT(ch))
return 1;
break;
case PP_PUNCT:
diff --git a/Src/prompt.c b/Src/prompt.c
index 0cc9ef917..ffc1d0df2 100644
--- a/Src/prompt.c
+++ b/Src/prompt.c
@@ -183,7 +183,7 @@ promptexpand(char *s, int ns, char *rs, char *Rs, unsigned int *txtchangep)
int oldval = lastval;
s = dupstring(s);
- if (!parsestr(s))
+ if (!parsestr(&s))
singsub(&s);
/*
* We don't need the special Nularg hack here and we're
@@ -192,8 +192,11 @@ promptexpand(char *s, int ns, char *rs, char *Rs, unsigned int *txtchangep)
if (*s == Nularg && s[1] == '\0')
*s = '\0';
- /* Ignore errors and status change in prompt substitution */
- errflag = olderr;
+ /*
+ * Ignore errors and status change in prompt substitution.
+ * However, keep any user interrupt error that occurred.
+ */
+ errflag = olderr | (errflag & ERRFLAG_INT);
lastval = oldval;
}
diff --git a/Src/signals.c b/Src/signals.c
index 2df69f96e..3950ad1a2 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -522,14 +522,14 @@ wait_for_processes(void)
get_usage();
}
/*
- * Remember the status associated with $!, so we can
- * wait for it even if it's exited. This value is
- * only used if we can't find the PID in the job table,
- * so it doesn't matter that the value we save here isn't
- * useful until the process has exited.
+ * Accumulate a list of older jobs. We only do this for
+ * background jobs, which is something in the job table
+ * that's not marked as in the current shell or as shell builtin
+ * and is not equal to the current foreground job.
*/
- if (pn != NULL && pid == lastpid && lastpid_status != -1L)
- lastpid_status = lastval2;
+ if (jn && !(jn->stat & (STAT_CURSH|STAT_BUILTIN)) &&
+ jn - jobtab != thisjob)
+ addbgstatus(pid, (int)lastval2);
}
}
@@ -619,7 +619,7 @@ zhandler(int sig)
zexit(SIGINT, 1);
if (list_pipe || chline || simple_pline) {
breaks = loops;
- errflag = 1;
+ errflag |= ERRFLAG_INT;
inerrflush();
check_cursh_sig(SIGINT);
}
@@ -640,6 +640,11 @@ zhandler(int sig)
if (idle >= 0 && idle < tmout)
alarm(tmout - idle);
else {
+ /*
+ * We want to exit now.
+ * Cancel all errors, including a user interrupt
+ * which is now redundant.
+ */
errflag = noerrs = 0;
zwarn("timeout");
stopmsg = 1;
@@ -1205,7 +1210,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
intrap++;
*sigtr |= ZSIG_IGNORED;
- lexsave();
+ zcontext_save();
/* execsave will save the old trap_return and trap_state */
execsave();
breaks = retflag = 0;
@@ -1260,14 +1265,25 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
new_trap_return = trap_return;
execrestore();
- lexrestore();
+ zcontext_restore();
if (new_trap_state == TRAP_STATE_FORCE_RETURN &&
/* zero return from function isn't special */
!(isfunc && new_trap_return == 0)) {
if (isfunc) {
breaks = loops;
- errflag = 1;
+ /*
+ * For SIGINT we behave the same as the default behaviour
+ * i.e. we set the error bit indicating an interrupt.
+ * We do this with SIGQUIT, too, even though we don't
+ * handle SIGQUIT by default. That's to try to make
+ * it behave a bit more like its normal behaviour when
+ * the trap handler has told us that's what it wants.
+ */
+ if (sig == SIGINT || sig == SIGQUIT)
+ errflag |= ERRFLAG_INT;
+ else
+ errflag |= ERRFLAG_ERROR;
}
lastval = new_trap_return;
/* return triggered */
@@ -1282,8 +1298,12 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
*/
lastval = olastval;
}
- if (try_tryflag)
- errflag = traperr;
+ if (try_tryflag) {
+ if (traperr)
+ errflag |= ERRFLAG_ERROR;
+ else
+ errflag &= ~ERRFLAG_ERROR;
+ }
breaks += obreaks;
/* return not triggered: restore old flag */
retflag = oretflag;
diff --git a/Src/sort.c b/Src/sort.c
index 3d00bb576..92ee1c0d4 100644
--- a/Src/sort.c
+++ b/Src/sort.c
@@ -368,7 +368,7 @@ strmetasort(char **array, int sortwhat, int *unmetalenp)
sortdir = (sortwhat & SORTIT_BACKWARDS) ? -1 : 1;
sortnumeric = (sortwhat & SORTIT_NUMERICALLY) ? 1 : 0;
- qsort(sortptrarr, nsort, sizeof(SortElt *), eltpcmp);
+ qsort(sortptrarr, nsort, sizeof(SortElt), eltpcmp);
sortnumeric = oldsortnumeric;
sortdir = oldsortdir;
diff --git a/Src/subst.c b/Src/subst.c
index 1aa9b982e..f52bcdfc8 100644
--- a/Src/subst.c
+++ b/Src/subst.c
@@ -195,7 +195,7 @@ stringsubst(LinkList list, LinkNode node, int pf_flags, int asssub)
while (!errflag && (c = *str)) {
if ((qt = c == Qstring) || c == String) {
- if ((c = str[1]) == Inpar) {
+ if ((c = str[1]) == Inpar || c == Inparmath) {
if (!qt)
list->list.flags |= LF_ARRAY;
str++;
@@ -258,24 +258,34 @@ stringsubst(LinkList list, LinkNode node, int pf_flags, int asssub)
skipparens(Inpar, Outpar, &str);
#endif
str--;
- } else {
- endchar = c;
- *str = '\0';
-
- while (*++str != endchar)
- DPUTS(!*str, "BUG: parse error in command substitution");
- }
- *str++ = '\0';
- if (endchar == Outpar && str2[1] == '(' && str[-2] == ')') {
+ } else if (c == Inparmath) {
/* Math substitution of the form $((...)) */
- str[-2] = '\0';
+ str[-1] = '\0';
+ while (*str != Outparmath && *str)
+ str++;
+ if (*str != Outparmath) {
+ zerr("failed to find end of math substitution");
+ return NULL;
+ }
+ str[-1] = '\0';
if (isset(EXECOPT))
- str = arithsubst(str2 + 2, &str3, str);
+ str = arithsubst(str2 + 2, &str3, str+1);
else
strncpy(str3, str2, 1);
setdata(node, (void *) str3);
continue;
+ } else {
+ endchar = c;
+ *str = '\0';
+
+ while (*++str != endchar) {
+ if (!*str) {
+ zerr("failed to find end of command substitution");
+ return NULL;
+ }
+ }
}
+ *str++ = '\0';
/* It is a command substitution, which will be parsed again *
* by the lexer, so we untokenize it first, but we cannot use *
@@ -298,7 +308,7 @@ stringsubst(LinkList list, LinkNode node, int pf_flags, int asssub)
if (endchar == Outpar)
str2--;
if (!(s = (char *) ugetnode(pl))) {
- str = strcpy(str2, str);
+ str = (char *)memmove(str2, str, strlen(str)+1);
continue;
}
if (!qt && (pf_flags & PREFORK_SINGLE) && isset(GLOBSUBST))
@@ -1306,7 +1316,7 @@ get_intarg(char **s, int *delmatchp)
p = dupstring(*s + arglen);
*s = t + arglen;
*t = sav;
- if (parsestr(p))
+ if (parsestr(&p))
return -1;
singsub(&p);
if (errflag)
@@ -1317,7 +1327,7 @@ get_intarg(char **s, int *delmatchp)
if (ret < 0)
ret = -ret;
*delmatchp = arglen;
- return ret < 0 ? -ret : ret;
+ return ret;
}
/* Parsing for the (e) flag. */
@@ -1329,18 +1339,21 @@ subst_parse_str(char **sp, int single, int err)
*sp = s = dupstring(*sp);
- if (!(err ? parsestr(s) : parsestrnoerr(s))) {
+ if (!(err ? parsestr(&s) : parsestrnoerr(&s))) {
+ *sp = s;
if (!single) {
int qt = 0;
- for (; *s; s++)
+ for (; *s; s++) {
if (!qt) {
if (*s == Qstring)
*s = String;
else if (*s == Qtick)
*s = Tick;
- } else if (*s == Dnull)
+ }
+ if (*s == Dnull)
qt = !qt;
+ }
}
return 0;
}
@@ -1385,12 +1398,23 @@ static char *
untok_and_escape(char *s, int escapes, int tok_arg)
{
int klen;
- char *dst;
+ char *dst = NULL;
- untokenize(dst = dupstring(s));
- if (escapes) {
- dst = getkeystring(dst, &klen, GETKEYS_SEP, NULL);
- dst = metafy(dst, klen, META_HREALLOC);
+ if (escapes && (*s == String || *s == Qstring) && s[1]) {
+ char *pstart = s+1, *pend;
+ for (pend = pstart; *pend; pend++)
+ if (!iident(*pend))
+ break;
+ if (!*pend) {
+ dst = dupstring(getsparam(pstart));
+ }
+ }
+ if (dst == NULL) {
+ untokenize(dst = dupstring(s));
+ if (escapes) {
+ dst = getkeystring(dst, &klen, GETKEYS_SEP, NULL);
+ dst = metafy(dst, klen, META_HREALLOC);
+ }
}
if (tok_arg)
shtokenize(dst);
@@ -1426,7 +1450,8 @@ check_colon_subscript(char *str, char **endp)
}
sav = **endp;
**endp = '\0';
- if (parsestr(str = dupstring(str)))
+ str = dupstring(str);
+ if (parsestr(&str))
return NULL;
singsub(&str);
remnulargs(str);
@@ -2192,12 +2217,28 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
*/
idbeg = s;
if ((subexp = (inbrace && s[-1] && isstring(*s) &&
- (s[1] == Inbrace || s[1] == Inpar)))) {
+ (s[1] == Inbrace || s[1] == Inpar || s[1] == Inparmath)))) {
int sav;
int quoted = *s == Qstring;
+ int outtok;
val = s++;
- skipparens(*s, *s == Inpar ? Outpar : Outbrace, &s);
+ switch (*s) {
+ case Inbrace:
+ outtok = Outbrace;
+ break;
+ case Inpar:
+ outtok = Outpar;
+ break;
+ case Inparmath:
+ outtok = Outparmath;
+ break;
+ default:
+ /* "Can't Happen" (TM) */
+ DPUTS(1, "Nested substitution: This Can't Happen (TM)");
+ return NULL;
+ }
+ skipparens(*s, outtok, &s);
sav = *s;
*s = 0;
/*
@@ -2811,7 +2852,8 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
haserr = parse_subst_string(s);
noerrs = one;
if (!quoteerr) {
- errflag = oef;
+ /* Retain user interrupt error status */
+ errflag = oef | (errflag & ERRFLAG_INT);
if (haserr)
shtokenize(s);
} else if (haserr || errflag) {
@@ -3238,8 +3280,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
haserr = 1;
}
noerrs = one;
- if (!quoteerr)
- errflag = oef;
+ if (!quoteerr) {
+ /* Retain user interrupt error status */
+ errflag = oef | (errflag & ERRFLAG_INT);
+ }
if (haserr || errflag)
return NULL;
}
@@ -3472,8 +3516,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
untokenize(*ap);
}
noerrs = one;
- if (!quoteerr)
- errflag = oef;
+ if (!quoteerr) {
+ /* Retain any user interrupt error status */
+ errflag = oef | (errflag & ERRFLAG_INT);
+ }
else if (haserr || errflag) {
zerr("parse error in parameter value");
return NULL;
@@ -3505,8 +3551,10 @@ paramsubst(LinkList l, LinkNode n, char **str, int qt, int pf_flags)
noerrs = 1;
haserr = parse_subst_string(val);
noerrs = one;
- if (!quoteerr)
- errflag = oef;
+ if (!quoteerr) {
+ /* Retain any user interrupt error status */
+ errflag = oef | (errflag & ERRFLAG_INT);
+ }
else if (haserr || errflag) {
zerr("parse error in parameter value");
return NULL;
@@ -4075,7 +4123,8 @@ modify(char **str, char **ptr)
noerrs = 1;
parse_subst_string(copy);
noerrs = one;
- errflag = oef;
+ /* Retain any user interrupt error status */
+ errflag = oef | (errflag & ERRFLAG_INT);
remnulargs(copy);
untokenize(copy);
}
@@ -4150,7 +4199,8 @@ modify(char **str, char **ptr)
noerrs = 1;
parse_subst_string(*str);
noerrs = one;
- errflag = oef;
+ /* Retain any user interrupt error status */
+ errflag = oef | (errflag & ERRFLAG_INT);
remnulargs(*str);
untokenize(*str);
}
diff --git a/Src/text.c b/Src/text.c
index f55553ed0..b58c2516d 100644
--- a/Src/text.c
+++ b/Src/text.c
@@ -173,6 +173,8 @@ getpermtext(Eprog prog, Wordcode c, int start_indent)
{
struct estate s;
+ queue_signals();
+
if (!c)
c = prog->prog;
@@ -193,6 +195,9 @@ getpermtext(Eprog prog, Wordcode c, int start_indent)
*tptr = '\0';
freeeprog(prog); /* mark as unused */
untokenize(tbuf);
+
+ unqueue_signals();
+
return tbuf;
}
@@ -206,6 +211,8 @@ getjobtext(Eprog prog, Wordcode c)
struct estate s;
+ queue_signals();
+
if (!c)
c = prog->prog;
@@ -224,6 +231,9 @@ getjobtext(Eprog prog, Wordcode c)
*tptr = '\0';
freeeprog(prog); /* mark as unused */
untokenize(jbuf);
+
+ unqueue_signals();
+
return jbuf;
}
@@ -834,6 +844,10 @@ gettext2(Estate state)
taddstr("))");
stack = 1;
break;
+ case WC_AUTOFN:
+ taddstr("builtin autoload -X");
+ stack = 1;
+ break;
case WC_TRY:
if (!s) {
taddstr("{");
@@ -879,6 +893,9 @@ getredirs(LinkList redirs)
">", ">|", ">>", ">>|", "&>", "&>|", "&>>", "&>>|", "<>", "<",
"<<", "<<-", "<<<", "<&", ">&", NULL /* >&- */, "<", ">"
};
+
+ queue_signals();
+
taddchr(' ');
for (n = firstnode(redirs); n; incnode(n)) {
Redir f = (Redir) getdata(n);
@@ -966,4 +983,6 @@ getredirs(LinkList redirs)
}
}
tptr--;
+
+ unqueue_signals();
}
diff --git a/Src/utils.c b/Src/utils.c
index e6eb8e6a7..3d12807e2 100644
--- a/Src/utils.c
+++ b/Src/utils.c
@@ -112,7 +112,20 @@ set_widearray(char *mb_array, Widechar_array wca)
#endif
-/* Print an error */
+/* Print an error
+
+ The following functions use the following printf-like format codes
+ (implemented by zerrmsg()):
+
+ Code Argument types Prints
+ %s const char * C string (null terminated)
+ %l const char *, int C string of given length (null not required)
+ %L long decimal value
+ %d int decimal value
+ %% (none) literal '%'
+ %c int character at that codepoint
+ %e int strerror() message (argument is typically 'errno')
+ */
static void
zwarning(const char *cmd, const char *fmt, va_list ap)
@@ -153,7 +166,7 @@ VA_DCL
if (errflag || noerrs) {
if (noerrs < 2)
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return;
}
@@ -161,7 +174,7 @@ VA_DCL
VA_GET_ARG(ap, fmt, const char *);
zwarning(NULL, fmt, ap);
va_end(ap);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
}
/**/
@@ -181,7 +194,7 @@ VA_DCL
VA_GET_ARG(ap, fmt, const char *);
zwarning(cmd, fmt, ap);
va_end(ap);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
}
/**/
@@ -330,7 +343,7 @@ zerrmsg(FILE *file, const char *fmt, va_list ap)
num = va_arg(ap, int);
if (num == EINTR) {
fputs("interrupt\n", file);
- errflag = 1;
+ errflag |= ERRFLAG_ERROR;
return;
}
errmsg = strerror(num);
@@ -343,6 +356,7 @@ zerrmsg(FILE *file, const char *fmt, va_list ap)
fputs(errmsg + 1, file);
}
break;
+ /* When adding format codes, update the comment above zwarning(). */
}
} else {
putc(*fmt == Meta ? *++fmt ^ 32 : *fmt, file);
@@ -400,7 +414,7 @@ nicechar(int c)
static char buf[6];
char *s = buf;
c &= 0xff;
- if (isprint(c))
+ if (ISPRINT(c))
goto done;
if (c & 0x80) {
if (isset(PRINTEIGHTBIT))
@@ -409,7 +423,7 @@ nicechar(int c)
*s++ = 'M';
*s++ = '-';
c &= 0x7f;
- if(isprint(c))
+ if(ISPRINT(c))
goto done;
}
if (c == 0x7f) {
@@ -566,7 +580,7 @@ wcs_nicechar(wchar_t c, size_t *widthp, char **swidep)
return buf;
}
if (swidep)
- *swidep = buf + *widthp;
+ *swidep = widthp ? buf + *widthp : buf;
return buf;
}
@@ -693,12 +707,12 @@ slashsplit(char *s)
int t0;
if (!*s)
- return (char **) zshcalloc(sizeof(char **));
+ return (char **) zshcalloc(sizeof(char *));
for (t = s, t0 = 0; *t; t++)
if (*t == '/')
t0++;
- q = r = (char **) zalloc(sizeof(char **) * (t0 + 2));
+ q = r = (char **) zalloc(sizeof(char *) * (t0 + 2));
while ((t = strchr(s, '/'))) {
*q++ = ztrduppfx(s, t - s);
@@ -719,7 +733,7 @@ slashsplit(char *s)
/**/
static int
-xsymlinks(char *s)
+xsymlinks(char *s, int full)
{
char **pp, **opp;
char xbuf2[PATH_MAX*3], xbuf3[PATH_MAX*2];
@@ -727,7 +741,7 @@ xsymlinks(char *s)
zulong xbuflen = strlen(xbuf);
opp = pp = slashsplit(s);
- for (; xbuflen < sizeof(xbuf) && *pp; pp++) {
+ for (; xbuflen < sizeof(xbuf) && *pp && ret >= 0; pp++) {
if (!strcmp(*pp, "."))
continue;
if (!strcmp(*pp, "..")) {
@@ -741,6 +755,8 @@ xsymlinks(char *s)
while (*--p != '/')
xbuflen--;
*p = '\0';
+ /* The \0 isn't included in the length */
+ xbuflen--;
continue;
}
sprintf(xbuf2, "%s/%s", xbuf, *pp);
@@ -758,13 +774,52 @@ xsymlinks(char *s)
} else {
ret = 1;
metafy(xbuf3, t0, META_NOALLOC);
+ if (!full) {
+ /*
+ * If only one expansion requested, ensure the
+ * full path is in xbuf.
+ */
+ zulong len = xbuflen;
+ if (*xbuf3 == '/')
+ strcpy(xbuf, xbuf3);
+ else if ((len += strlen(xbuf3) + 1) < sizeof(xbuf)) {
+ strcpy(xbuf + xbuflen, "/");
+ strcpy(xbuf + xbuflen + 1, xbuf3);
+ } else {
+ *xbuf = 0;
+ ret = -1;
+ break;
+ }
+
+ while (*++pp) {
+ zulong newlen = len + strlen(*pp) + 1;
+ if (newlen < sizeof(xbuf)) {
+ strcpy(xbuf + len, "/");
+ strcpy(xbuf + len + 1, *pp);
+ len = newlen;
+ } else {
+ *xbuf = 01;
+ ret = -1;
+ break;
+ }
+ }
+ /*
+ * No need to update xbuflen, we're finished
+ * the expansion (for now).
+ */
+ break;
+ }
if (*xbuf3 == '/') {
strcpy(xbuf, "");
- if (xsymlinks(xbuf3 + 1) < 0)
+ if (xsymlinks(xbuf3 + 1, 1) < 0)
ret = -1;
+ else
+ xbuflen = strlen(xbuf);
} else
- if (xsymlinks(xbuf3) < 0)
+ if (xsymlinks(xbuf3, 1) < 0)
ret = -1;
+ else
+ xbuflen = strlen(xbuf);
}
}
freearray(opp);
@@ -783,7 +838,7 @@ xsymlink(char *s)
if (*s != '/')
return NULL;
*xbuf = '\0';
- if (xsymlinks(s + 1) < 0)
+ if (xsymlinks(s + 1, 1) < 0)
zwarn("path expansion failed, using root directory");
if (!*xbuf)
return ztrdup("/");
@@ -792,12 +847,30 @@ xsymlink(char *s)
/**/
void
-print_if_link(char *s)
+print_if_link(char *s, int all)
{
if (*s == '/') {
*xbuf = '\0';
- if (xsymlinks(s + 1) > 0)
- printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout);
+ if (all) {
+ char *start = s + 1;
+ char xbuflink[PATH_MAX];
+ for (;;) {
+ if (xsymlinks(start, 0) > 0) {
+ printf(" -> ");
+ zputs(*xbuf ? xbuf : "/", stdout);
+ if (!*xbuf)
+ break;
+ strcpy(xbuflink, xbuf);
+ start = xbuflink + 1;
+ *xbuf = '\0';
+ } else {
+ break;
+ }
+ }
+ } else {
+ if (xsymlinks(s + 1, 1) > 0)
+ printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout);
+ }
}
}
@@ -1049,10 +1122,13 @@ getnameddir(char *name)
if ((pw = getpwnam(name))) {
char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir)
: ztrdup(pw->pw_dir);
- adduserdir(name, dir, ND_USERNAME, 1);
- str = dupstring(dir);
- zsfree(dir);
- return str;
+ if (dir) {
+ adduserdir(name, dir, ND_USERNAME, 1);
+ str = dupstring(dir);
+ zsfree(dir);
+ return str;
+ } else
+ return dupstring(pw->pw_dir);
}
}
#endif /* HAVE_GETPWNAM */
@@ -1456,7 +1532,7 @@ checkmailpath(char **s)
setunderscore(*s);
u = dupstring(u);
- if (! parsestr(u)) {
+ if (!parsestr(&u)) {
singsub(&u);
zputs(u, shout);
fputc('\n', shout);
@@ -2078,6 +2154,8 @@ zstrtol_underscore(const char *s, char **t, int base, int underscore)
base = 10;
else if (*++s == 'x' || *s == 'X')
base = 16, s++;
+ else if (*s == 'b' || *s == 'B')
+ base = 2, s++;
else
base = 8;
}
@@ -2197,6 +2275,10 @@ setblock_stdin(void)
* Note that apart from setting (and restoring) non-blocking input,
* this function does not change the input mode. The calling function
* should have set cbreak mode if necessary.
+ *
+ * fd may be -1 to sleep until the timeout in microseconds. This is a
+ * fallback for old systems that don't have nanosleep(). Some very old
+ * systems might not have select: get with it, daddy-o.
*/
/**/
@@ -2218,6 +2300,8 @@ read_poll(int fd, int *readchar, int polltty, zlong microseconds)
struct ttyinfo ti;
#endif
+ if (fd < 0 || (polltty && !isatty(fd)))
+ polltty = 0; /* no tty to poll */
#if defined(HAS_TIO) && !defined(__CYGWIN__)
/*
@@ -2239,7 +2323,7 @@ read_poll(int fd, int *readchar, int polltty, zlong microseconds)
* as plausible as it sounds, but it seems the right way to guess.
* pws 2000/06/26
*/
- if (polltty) {
+ if (polltty && fd >= 0) {
gettyinfo(&ti);
if ((polltty = ti.tio.c_cc[VMIN])) {
ti.tio.c_cc[VMIN] = 0;
@@ -2255,16 +2339,24 @@ read_poll(int fd, int *readchar, int polltty, zlong microseconds)
expire_tv.tv_sec = (int) (microseconds / (zlong)1000000);
expire_tv.tv_usec = microseconds % (zlong)1000000;
FD_ZERO(&foofd);
- FD_SET(fd, &foofd);
- ret = select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
+ if (fd > -1) {
+ FD_SET(fd, &foofd);
+ ret = select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
+ } else
+ ret = select(0, NULL, NULL, NULL, &expire_tv);
#else
+ if (fd < 0) {
+ /* OK, can't do that. Just quietly sleep for a second. */
+ sleep(1);
+ return 1;
+ }
#ifdef FIONREAD
if (ioctl(fd, FIONREAD, (char *) &val) == 0)
ret = (val > 0);
#endif
#endif
- if (ret < 0) {
+ if (fd >= 0 && ret < 0) {
/*
* Final attempt: set non-blocking read and try to read a character.
* Praise Bill, this works under Cygwin (nothing else seems to).
@@ -2286,6 +2378,80 @@ read_poll(int fd, int *readchar, int polltty, zlong microseconds)
return (ret > 0);
}
+/*
+ * Sleep for the given number of microseconds --- must be within
+ * range of a long at the moment, but this is only used for
+ * limited internal purposes.
+ */
+
+/**/
+int
+zsleep(long us)
+{
+#ifdef HAVE_NANOSLEEP
+ struct timespec sleeptime;
+
+ sleeptime.tv_sec = (time_t)us / (time_t)1000000;
+ sleeptime.tv_nsec = (us % 1000000L) * 1000L;
+ for (;;) {
+ struct timespec rem;
+ int ret = nanosleep(&sleeptime, &rem);
+
+ if (ret == 0)
+ return 1;
+ else if (errno != EINTR)
+ return 0;
+ sleeptime = rem;
+ }
+#else
+ int dummy;
+ return read_poll(-1, &dummy, 0, us);
+#endif
+}
+
+/**
+ * Sleep for time (fairly) randomly up to max_us microseconds.
+ * Don't let the wallclock time extend beyond end_time.
+ * Return 1 if that seemed to work, else 0.
+ *
+ * For best results max_us should be a multiple of 2**16 or large
+ * enough that it doesn't matter.
+ */
+
+/**/
+int
+zsleep_random(long max_us, time_t end_time)
+{
+ long r;
+ time_t now = time(NULL);
+
+ /*
+ * Randomish backoff. Doesn't need to be fundamentally
+ * unpredictable, just probably unlike the value another
+ * exiting shell is using. On some systems the bottom 16
+ * bits aren't that random but the use here doesn't
+ * really care.
+ */
+ r = (long)(rand() & 0xFFFF);
+ /*
+ * Turn this into a fraction of sleep_us. Again, this
+ * doesn't need to be particularly accurate and the base time
+ * is sufficient that we can do the division first and not
+ * worry about the range.
+ */
+ r = (max_us >> 16) * r;
+ /*
+ * Don't sleep beyond timeout.
+ * Not that important as timeout is ridiculously long, but
+ * if there's an interface, interface to it...
+ */
+ while (r && now + (time_t)(r / 1000000) > end_time)
+ r >>= 1;
+ if (r) /* pedantry */
+ return zsleep(r);
+ return 0;
+}
+
/**/
int
checkrmall(char *s)
@@ -2294,7 +2460,7 @@ checkrmall(char *s)
return 1;
fprintf(shout, "zsh: sure you want to delete all the files in ");
if (*s != '/') {
- nicezputs(pwd[1] ? unmeta(pwd) : "", shout);
+ nicezputs(pwd[1] ? pwd : "", shout);
fputc('/', shout);
}
nicezputs(s, shout);
@@ -2949,7 +3115,7 @@ colonsplit(char *s, int uniq)
for (t = s, ct = 0; *t; t++) /* count number of colons */
if (*t == ':')
ct++;
- ptr = ret = (char **) zalloc(sizeof(char **) * (ct + 2));
+ ptr = ret = (char **) zalloc(sizeof(char *) * (ct + 2));
t = s;
do {
@@ -3482,7 +3648,7 @@ inittyptab(void)
for (t0 = (int)STOUC(Snull); t0 <= (int)STOUC(Nularg); t0++)
typtab[t0] |= ITOK | IMETA | INULL;
for (s = ifs ? ifs : EMULATION(EMULATE_KSH|EMULATE_SH) ?
- ztrdup(DEFAULT_IFS_SH) : ztrdup(DEFAULT_IFS); *s; s++) {
+ DEFAULT_IFS_SH : DEFAULT_IFS; *s; s++) {
int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
#ifdef MULTIBYTE_SUPPORT
if (!isascii(c)) {
@@ -3517,7 +3683,7 @@ inittyptab(void)
#ifdef MULTIBYTE_SUPPORT
set_widearray(wordchars, &wordchars_wide);
set_widearray(ifs ? ifs : EMULATION(EMULATE_KSH|EMULATE_SH) ?
- ztrdup(DEFAULT_IFS_SH) : ztrdup(DEFAULT_IFS), &ifs_wide);
+ DEFAULT_IFS_SH : DEFAULT_IFS, &ifs_wide);
#endif
for (s = SPECCHARS; *s; s++)
typtab[STOUC(*s)] |= ISPECIAL;
@@ -4158,7 +4324,7 @@ unmetafy(char *s, int *len)
for (p = s; *p && *p != Meta; p++);
for (t = p; (*t = *p++);)
- if (*t++ == Meta)
+ if (*t++ == Meta && *p)
t[-1] = *p++ ^ 32;
if (len)
*len = t - s;
@@ -4242,7 +4408,7 @@ unmeta(const char *file_name)
}
for (t = file_name, p = fn; *t; p++)
- if ((*p = *t++) == Meta)
+ if ((*p = *t++) == Meta && *t)
*p = *t++ ^ 32;
*p = '\0';
return fn;
@@ -4631,6 +4797,14 @@ mb_metacharlenconv_r(const char *s, wint_t *wcp, mbstate_t *mbsp)
inchar = *++ptr ^ 32;
DPUTS(!*ptr,
"BUG: unexpected end of string in mb_metacharlen()\n");
+ } else if (imeta(*ptr)) {
+ /*
+ * As this is metafied input, this is a token --- this
+ * can't be a part of the string. It might be
+ * something on the end of an unbracketed parameter
+ * reference, for example.
+ */
+ break;
} else
inchar = *ptr;
ptr++;
diff --git a/Src/watch.c b/Src/watch.c
index 8dea0b495..fe409f91a 100644
--- a/Src/watch.c
+++ b/Src/watch.c
@@ -372,6 +372,27 @@ watchlog2(int inout, WATCH_STRUCT_UTMP *u, char *fmt, int prnt, int fini)
return fmt;
}
+/* See if the watch entry matches */
+
+static int
+watchlog_match(char *teststr, char *actual, int len)
+{
+ int ret = 0;
+ Patprog pprog;
+ char *str = dupstring(teststr);
+
+ tokenize(str);
+
+ if ((pprog = patcompile(str, PAT_STATIC, 0))) {
+ queue_signals();
+ if (pattry(pprog, actual))
+ ret = 1;
+ unqueue_signals();
+ } else if (!strncmp(actual, teststr, len))
+ ret = 1;
+ return ret;
+}
+
/* check the List for login/logouts */
/**/
@@ -400,7 +421,7 @@ watchlog(int inout, WATCH_STRUCT_UTMP *u, char **w, char *fmt)
for (vv = v; *vv && *vv != '@' && *vv != '%'; vv++);
sav = *vv;
*vv = '\0';
- if (strncmp(u->ut_name, v, sizeof(u->ut_name)))
+ if (!watchlog_match(v, u->ut_name, sizeof(u->ut_name)))
bad = 1;
*vv = sav;
v = vv;
@@ -410,7 +431,7 @@ watchlog(int inout, WATCH_STRUCT_UTMP *u, char **w, char *fmt)
for (vv = ++v; *vv && *vv != '@'; vv++);
sav = *vv;
*vv = '\0';
- if (strncmp(u->ut_line, v, sizeof(u->ut_line)))
+ if (!watchlog_match(v, u->ut_line, sizeof(u->ut_line)))
bad = 1;
*vv = sav;
v = vv;
@@ -420,7 +441,7 @@ watchlog(int inout, WATCH_STRUCT_UTMP *u, char **w, char *fmt)
for (vv = ++v; *vv && *vv != '%'; vv++);
sav = *vv;
*vv = '\0';
- if (strncmp(u->ut_host, v, strlen(v)))
+ if (!watchlog_match(v, u->ut_host, strlen(v)))
bad = 1;
*vv = sav;
v = vv;
diff --git a/Src/zsh.h b/Src/zsh.h
index d284c7aa7..486ad800a 100644
--- a/Src/zsh.h
+++ b/Src/zsh.h
@@ -163,40 +163,42 @@ struct mathfunc {
#define Hat ((char) 0x86)
#define Star ((char) 0x87)
#define Inpar ((char) 0x88)
-#define Outpar ((char) 0x89)
-#define Qstring ((char) 0x8a)
-#define Equals ((char) 0x8b)
-#define Bar ((char) 0x8c)
-#define Inbrace ((char) 0x8d)
-#define Outbrace ((char) 0x8e)
-#define Inbrack ((char) 0x8f)
-#define Outbrack ((char) 0x90)
-#define Tick ((char) 0x91)
-#define Inang ((char) 0x92)
-#define Outang ((char) 0x93)
-#define OutangProc ((char) 0x94)
-#define Quest ((char) 0x95)
-#define Tilde ((char) 0x96)
-#define Qtick ((char) 0x97)
-#define Comma ((char) 0x98)
+#define Inparmath ((char) 0x89)
+#define Outpar ((char) 0x8a)
+#define Outparmath ((char) 0x8b)
+#define Qstring ((char) 0x8c)
+#define Equals ((char) 0x8d)
+#define Bar ((char) 0x8e)
+#define Inbrace ((char) 0x8f)
+#define Outbrace ((char) 0x90)
+#define Inbrack ((char) 0x91)
+#define Outbrack ((char) 0x92)
+#define Tick ((char) 0x93)
+#define Inang ((char) 0x94)
+#define Outang ((char) 0x95)
+#define OutangProc ((char) 0x96)
+#define Quest ((char) 0x97)
+#define Tilde ((char) 0x98)
+#define Qtick ((char) 0x99)
+#define Comma ((char) 0x9a)
/*
* Null arguments: placeholders for single and double quotes
* and backslashes.
*/
-#define Snull ((char) 0x99)
-#define Dnull ((char) 0x9a)
-#define Bnull ((char) 0x9b)
+#define Snull ((char) 0x9b)
+#define Dnull ((char) 0x9c)
+#define Bnull ((char) 0x9d)
/*
* Backslash which will be returned to "\" instead of being stripped
* when we turn the string into a printable format.
*/
-#define Bnullkeep ((char) 0x9c)
+#define Bnullkeep ((char) 0x9e)
/*
* Null argument that does not correspond to any character.
* This should be last as it does not appear in ztokens and
* is used to initialise the IMETA type in inittyptab().
*/
-#define Nularg ((char) 0x9d)
+#define Nularg ((char) 0x9f)
/*
* Take care to update the use of IMETA appropriately when adding
@@ -409,7 +411,9 @@ enum {
#define INP_HIST (1<<2) /* expanding history */
#define INP_CONT (1<<3) /* continue onto previously stacked input */
#define INP_ALCONT (1<<4) /* stack is continued from alias expn. */
-#define INP_LINENO (1<<5) /* update line number */
+#define INP_HISTCONT (1<<5) /* stack is continued from history expn. */
+#define INP_LINENO (1<<6) /* update line number */
+#define INP_APPEND (1<<7) /* Append new lines to allow backup */
/* Flags for metafy */
#define META_REALLOC 0
@@ -421,6 +425,15 @@ enum {
#define META_HEAPDUP 6
#define META_HREALLOC 7
+/* Context to save and restore (bit fields) */
+enum {
+ /* History mechanism */
+ ZCONTEXT_HIST = (1<<0),
+ /* Lexical analyser */
+ ZCONTEXT_LEX = (1<<1),
+ /* Parser */
+ ZCONTEXT_PARSE = (1<<2)
+};
/**************************/
/* Abstract types for zsh */
@@ -1865,9 +1878,9 @@ typedef groupset *Groupset;
#define PRINT_TYPESET (1<<5)
/* flags for printing for the whence builtin */
-#define PRINT_WHENCE_CSH (1<<5)
-#define PRINT_WHENCE_VERBOSE (1<<6)
-#define PRINT_WHENCE_SIMPLE (1<<7)
+#define PRINT_WHENCE_CSH (1<<6)
+#define PRINT_WHENCE_VERBOSE (1<<7)
+#define PRINT_WHENCE_SIMPLE (1<<8)
#define PRINT_WHENCE_FUNCDEF (1<<9)
#define PRINT_WHENCE_WORD (1<<10)
@@ -2623,6 +2636,20 @@ enum trap_state {
#define IN_EVAL_TRAP() \
(intrap && !trapisfunc && traplocallevel == locallevel)
+/*
+ * Bits in the errflag variable.
+ */
+enum errflag_bits {
+ /*
+ * Standard internal error bit.
+ */
+ ERRFLAG_ERROR = 1,
+ /*
+ * User interrupt.
+ */
+ ERRFLAG_INT = 2
+};
+
/***********/
/* Sorting */
/***********/
@@ -2668,6 +2695,87 @@ struct sortelt {
typedef struct sortelt *SortElt;
+/*********************************************************/
+/* Structures to save and restore for individual modules */
+/*********************************************************/
+
+/* History */
+struct hist_stack {
+ int histactive;
+ int histdone;
+ int stophist;
+ int hlinesz;
+ char *hline;
+ char *hptr;
+ short *chwords;
+ int chwordlen;
+ int chwordpos;
+ int (*hgetc) _((void));
+ void (*hungetc) _((int));
+ void (*hwaddc) _((int));
+ void (*hwbegin) _((int));
+ void (*hwend) _((void));
+ void (*addtoline) _((int));
+ unsigned char *cstack;
+ int csp;
+};
+
+/*
+ * State of a lexical token buffer.
+ *
+ * It would be neater to include the pointer to the start of the buffer,
+ * however the current code structure means that the standard instance
+ * of this, tokstr, is visible in lots of places, so that's not
+ * convenient.
+ */
+
+struct lexbufstate {
+ /*
+ * Next character to be added.
+ * Set to NULL when the buffer is to be visible from elsewhere.
+ */
+ char *ptr;
+ /* Allocated buffer size */
+ int siz;
+ /* Length in use */
+ int len;
+};
+
+/* Lexical analyser */
+struct lex_stack {
+ int dbparens;
+ int isfirstln;
+ int isfirstch;
+ int lexflags;
+ enum lextok tok;
+ char *tokstr;
+ char *zshlextext;
+ struct lexbufstate lexbuf;
+ int lex_add_raw;
+ char *tokstr_raw;
+ struct lexbufstate lexbuf_raw;
+ int lexstop;
+ zlong toklineno;
+};
+
+/* Parser */
+struct parse_stack {
+ struct heredocs *hdocs;
+
+ int incmdpos;
+ int aliasspaceflag;
+ int incond;
+ int inredir;
+ int incasepat;
+ int isnewlin;
+ int infor;
+
+ int eclen, ecused, ecnpats;
+ Wordcode ecbuf;
+ Eccstr ecstrs;
+ int ecsoffs, ecssub, ecnfunc;
+};
+
/************************/
/* Flags to casemodifiy */
/************************/
diff --git a/Src/zsh.mdd b/Src/zsh.mdd
index 9a8c923f9..c2e59c910 100644
--- a/Src/zsh.mdd
+++ b/Src/zsh.mdd
@@ -9,7 +9,8 @@ alwayslink=1
# autobins not specified because of alwayslink
-objects="builtin.o compat.o cond.o exec.o glob.o hashtable.o hashnameddir.o \
+objects="builtin.o compat.o cond.o context.o \
+exec.o glob.o hashtable.o hashnameddir.o \
hist.o init.o input.o jobs.o lex.o linklist.o loop.o math.o \
mem.o module.o options.o params.o parse.o pattern.o prompt.o signals.o \
signames.o sort.o string.o subst.o text.o utils.o watch.o"
@@ -21,9 +22,18 @@ hdrdeps="zshcurses.h zshterm.h"
:<<\Make
@CONFIG_MK@
+# If we're using gcc as the preprocessor, get rid of the additional
+# lines generated by the preprocessor as they can confuse the script.
+# We don't need these in other cases either, but can't necessarily rely
+# on the option to remove them being the same.
signames.c: signames1.awk signames2.awk ../config.h @SIGNAL_H@
$(AWK) -f $(sdir)/signames1.awk @SIGNAL_H@ >sigtmp.c
- $(CPP) sigtmp.c >sigtmp.out
+ case "`$(CPP) --version </dev/null 2>&1`" in \
+ *"Free Software Foundation"*) \
+ $(CPP) -P sigtmp.c >sigtmp.out;; \
+ *) \
+ $(CPP) sigtmp.c >sigtmp.out;; \
+ esac
$(AWK) -f $(sdir)/signames2.awk sigtmp.out > $@
rm -f sigtmp.c sigtmp.out
diff --git a/Src/ztype.h b/Src/ztype.h
index eef0f23db..d1bef0a5a 100644
--- a/Src/ztype.h
+++ b/Src/ztype.h
@@ -75,3 +75,9 @@
#define WC_ZISTYPE(X,Y) zistype((X),(Y))
#define WC_ISPRINT(X) isprint(X)
#endif
+
+#if defined(__APPLE__) && defined(BROKEN_ISPRINT)
+#define ISPRINT(c) isprint_ascii(c)
+#else
+#define ISPRINT(c) isprint(c)
+#endif
diff --git a/Test/A02alias.ztst b/Test/A02alias.ztst
index 7121c50ef..08163eb52 100644
--- a/Test/A02alias.ztst
+++ b/Test/A02alias.ztst
@@ -42,3 +42,42 @@
cat <(echo foo | cat)
0:Alias expansion works at the end of parsed strings
>foo
+
+ alias -g '&&=(){ return $?; } && '
+ alias not_the_print_command=print
+ eval 'print This is output
+ && print And so is this
+ && { print And this too; false; }
+ && print But not this
+ && print Nor this
+ true
+ && not_the_print_command And aliases are expanded'
+0:We can now alias special tokens. Woo hoo.
+>This is output
+>And so is this
+>And this too
+>And aliases are expanded
+
+ $ZTST_testdir/../Src/zsh -fis <<<'
+ PROMPT=""
+ exec 2>&1
+ alias \{=echo
+ { begin
+ {end
+ fc -l -2' 2>/dev/null
+0:Aliasing reserved tokens
+>begin
+>end
+*>*4*{ begin
+*>*5*{end
+
+ $ZTST_testdir/../Src/zsh -fis <<<'
+ PROMPT=""
+ exec 2>&1
+ alias -g S=\"
+ echo S a string S "
+ fc -l -1' 2>/dev/null
+0:Global aliasing quotes
+> a string S
+*>*4*echo S a string S "
+# Note there is a trailing space on the "> a string S " line
diff --git a/Test/A04redirect.ztst b/Test/A04redirect.ztst
index a39ce46c8..602341d05 100644
--- a/Test/A04redirect.ztst
+++ b/Test/A04redirect.ztst
@@ -152,11 +152,18 @@
>hello
>goodbye
- ({ exec 3<&- } 2>/dev/null
- exec 3<&-
- read foo <&-)
-1:'<&-' redirection
-*?\(eval\):*: failed to close file descriptor 3:*
+ ({exec 3<&- } 2>/dev/null
+ exec 3<&-
+ read foo <&-)
+1:'<&-' redirection with numeric fd (no error message on failure)
+
+ (exec {varid}<&0
+ exec {varid}<&-
+ print About to close a second time >&2
+ read {varid}<&-)
+1:'<&-' redirection with fd in variable (error message on failure)
+?About to close a second time
+*?\(eval\):*: failed to close file descriptor *
print foo >&-
0:'>&-' redirection
@@ -531,3 +538,20 @@
print $functions[noredirfn]
0:Output from $functions[] for definition with no redirection
> print This rather boring function has no redirection.
+
+ (x=43
+ x=$(print This should appear, really >&2; print Not used) exec >test.log
+ print x=$x)
+ cat test.log
+0:Assignment with exec used for redirection: no POSIX_BUILTINS
+>x=43
+?This should appear, really
+
+ (setopt POSIX_BUILTINS
+ x=45
+ x=$(print This should appear, too >&2; print And this) exec >test.log
+ print x=$x)
+ cat test.log
+0:Assignment with exec used for redirection: POSIX_BUILTINS
+>x=And this
+?This should appear, too
diff --git a/Test/A05execution.ztst b/Test/A05execution.ztst
index ca97f4f41..cc2d34d23 100644
--- a/Test/A05execution.ztst
+++ b/Test/A05execution.ztst
@@ -190,9 +190,9 @@
print "${pipestatus[@]}")
ZTST_hashmark
done | sort | uniq -c | sed 's/^ *//'
-0:Check whether `$pipestatus[]' behaves.
+0:Check whether '$pipestatus[]' behaves.
>2048 2 1 0
-F:This test checks for a bug in `$pipestatus[]' handling. If it breaks then
+F:This test checks for a bug in '$pipestatus[]' handling. If it breaks then
F:the bug is still there or it reappeared. See workers-29973 for details.
{ setopt MONITOR } 2>/dev/null
@@ -244,3 +244,45 @@ F:anonymous function, and a descriptor leak when backgrounding a pipeline
>autoload_redir () {
> print Autoloaded ksh style
>} > autoload.log
+
+# This tests that we record the status of processes that have already exited
+# for when we wait for them.
+#
+# Actually, we don't guarantee here that the jobs have already exited, but
+# the order of the waits means it's highly likely we do need to recall a
+# previous status, barring accidents which shouldn't happen very often. In
+# other words, we rely on the test working repeatedly rather than just
+# once. The monitor option is irrelevant to the logic, so we'll make
+# our job easier by turning it off.
+ { unsetopt MONITOR } 2>/dev/null
+ (exit 1) &
+ one=$!
+ (exit 2) &
+ two=$!
+ (exit 3) &
+ three=$!
+ wait $three
+ print $?
+ wait $two
+ print $?
+ wait $one
+1:The status of recently exited background jobs is recorded
+>3
+>2
+
+# Regression test for workers/34060 (patch in 34065)
+ setopt ERR_EXIT NULL_GLOB
+ if false; then :; else echo if:$?; fi
+ if false; then :; else for x in _*_; do :; done; echo for:$?; fi
+0:False "if" condition handled correctly by "for" loops with ERR_EXIT
+>if:1
+>for:0
+
+# Regression test for workers/34065 (uses setopt from preceding test)
+ select x; do :; done; echo $?
+ select x in; do :; done; echo $?
+ select x in _*_; do :; done; echo $?
+0:The status of "select" is zero when the loop body does not execute
+>0
+>0
+>0
diff --git a/Test/A06assign.ztst b/Test/A06assign.ztst
index 9a0a4f0cc..0ad9a0aca 100644
--- a/Test/A06assign.ztst
+++ b/Test/A06assign.ztst
@@ -1,5 +1,10 @@
# Tests of parameter assignments
+%prep
+ mkdir assign.tmp && cd assign.tmp
+
+ touch tmpfile1 tmpfile2
+
%test
typeset -A assoc
@@ -413,3 +418,36 @@
>world
>worldliness
>world
+
+ integer i n x
+ float f
+ setopt globassign
+ i=tmpfile1
+ n=tmp*
+ x=*2
+ f=2+2
+ typeset -p i n x f
+0:GLOB_ASSIGN with numeric types
+>typeset -i i=0
+>typeset -a n
+>n=(tmpfile1 tmpfile2)
+>typeset x=tmpfile2
+>typeset -E f=4.000000000e+00
+
+ A=(first second)
+ A="${A[*]}" /bin/sh -c 'echo $A'
+ print -l "${A[@]}"
+0:command execution with assignments shadowing array parameter
+>first second
+>first
+>second
+
+ setopt ksharrays
+ A=(first second)
+ A="${A[*]}" /bin/sh -c 'echo $A'
+ print -l "${A[@]}"
+ unsetopt ksharrays
+0:command execution with assignments shadowing array parameter with ksharrays
+>first second
+>first
+>second
diff --git a/Test/A07control.ztst b/Test/A07control.ztst
index 397a821f1..b1a248732 100644
--- a/Test/A07control.ztst
+++ b/Test/A07control.ztst
@@ -110,3 +110,56 @@
done
1:break error case -1
?(eval):break:2: argument is not positive: -1
+
+ false
+ for x in; do
+ print nothing executed
+ done
+0:Status 0 from for with explicit empty list
+
+ set --
+ false
+ for x; do
+ print nothing executed
+ done
+0:Status 0 from for with implicit empty list
+
+ (exit 2)
+ for x in 1 2; do
+ print $?
+ done
+0:Status from previous command propagated into for loop
+>2
+>0
+
+ false
+ for x in $(echo 1 2; (exit 3)); do
+ print $?
+ done
+0:Status from expansion propagated into for loop
+>3
+>0
+
+ false
+ for x in $(exit 4); do
+ print not executed
+ done
+0:Status from expansion not propagated after unexecuted for loop
+
+ false
+ for x in NonExistentFilePrefix*(N); do
+ print not executed, either
+ done
+0:Status from before for loop not propagated if empty after expansion
+
+ for x in $(echo 1; false); do
+ done
+0:Status reset by empty list in for loop
+
+ false
+ for x in $(echo 1; false); do
+ echo $?
+ (exit 4)
+ done
+4:Last status from loop body is kept even with other funny business going on
+>1
diff --git a/Test/B02typeset.ztst b/Test/B02typeset.ztst
index 51ebc6535..f4fb8ecb9 100644
--- a/Test/B02typeset.ztst
+++ b/Test/B02typeset.ztst
@@ -468,3 +468,20 @@
0:retying arrays to same array works
>foo bar
>goo car
+
+ (
+ setopt POSIXBUILTINS
+ readonly pbro
+ print ${+pbro} >&2
+ (typeset pbro=3)
+ (pbro=4)
+ typeset -r pbro # idempotent (no error)...
+ print ${+pbro} >&2 # ...so still readonly...
+ typeset +r pbro # ...can't turn it off
+ )
+1:Readonly with POSIX_BUILTINS
+?0
+?(eval):5: read-only variable: pbro
+?(eval):6: read-only variable: pbro
+?0
+?(eval):9: read-only variable: pbro
diff --git a/Test/B06fc.ztst b/Test/B06fc.ztst
index eb73eaa14..922b0010f 100644
--- a/Test/B06fc.ztst
+++ b/Test/B06fc.ztst
@@ -9,3 +9,17 @@
$ZTST_testdir/../Src/zsh -f ./fcl
1:Checking that fc -l foo doesn't core dump when history is empty
?./fcl:fc:1: event not found: foo
+
+ PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< $'fc -p /dev/null 0 0\n:'
+0:Checking that fc -p doesn't core dump when history size is zero
+*?*%*
+
+ PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< 'fc -p /dev/null a 0'
+1:Checking that fc -p rejects non-integer history size
+*?*% fc: HISTSIZE must be an integer
+*?*%*
+
+ PS1='%% ' $ZTST_testdir/../Src/zsh +Z -fsi <<< 'fc -p /dev/null 0 a'
+1:Checking that fc -p rejects non-integer history save size
+*?*% fc: SAVEHIST must be an integer
+*?*%*
diff --git a/Test/B07emulate.ztst b/Test/B07emulate.ztst
index 315206a20..2de097e25 100644
--- a/Test/B07emulate.ztst
+++ b/Test/B07emulate.ztst
@@ -247,3 +247,7 @@
>extendedglob is initially off
>bareglobqual is still on
>extendedglob is on, too
+
+ emulate sh -c '[[ a == a ]]'
+0:regression test for POSIX_ALIASES reserved words
+F:Some reserved tokens are handled in alias expansion
diff --git a/Test/C01arith.ztst b/Test/C01arith.ztst
index 4c55b961e..e2dfe56fc 100644
--- a/Test/C01arith.ztst
+++ b/Test/C01arith.ztst
@@ -16,7 +16,13 @@
print -- $(( rnd = there * 10000 ))
# save rounding problems by converting to integer
0:basic floating point arithmetic
->31415.
+>31415
+
+ integer rnd
+ (( rnd = ((29.1 % 13.0 * 10) + 0.5) ))
+ print $rnd
+0:Test floating point modulo function
+>31
print $(( 0x10 + 0X01 + 2#1010 ))
0:base input
@@ -286,3 +292,98 @@
env SHLVL=1+RANDOM $ZTST_testdir/../Src/zsh -f -c 'print $SHLVL'
0:Imported integer functions are not evaluated
>2
+
+ print $(( 0b0 + 0b1 + 0b11 + 0b110 ))
+0:Binary input
+>10
+
+ print $(( 0b2 ))
+1:Binary numbers don't tend to have 2's in
+?(eval):1: bad math expression: operator expected at `2 '
+# ` for emacs shell mode
+
+ integer varassi
+ print $(( varassi = 5.5 / 2.0 ))
+ print $varassi
+0:Integer variable assignment converts result to integer
+>2
+>2
+# It's hard to test for integer to float.
+
+ integer ff1=3 ff2=4
+ print $(( ff1/ff2 ))
+ setopt force_float
+ print $(( ff1/ff2 ))
+ unsetopt force_float
+0:Variables are forced to floating point where necessary
+# 0.75 is exactly representable, don't expect rounding error.
+>0
+>0.75
+
+ # The following tests for a bug that only happens when
+ # backing up over input read a line at a time, so we'll
+ # read the input from stdin.
+ $ZTST_testdir/../Src/zsh -f <<<'
+ print $((echo first command
+ ); echo second command)
+ print third command
+ '
+0:Backing up a line of input when finding out it's not arithmetic
+>first command second command
+>third command
+
+ $ZTST_testdir/../Src/zsh -f <<<'
+ print $((3 +
+ 4))
+ print next line
+ '
+0:Not needing to back up a line when reading multiline arithmetic
+>7
+>next line
+
+ $ZTST_testdir/../Src/zsh -f <<<'
+ print $((case foo in
+ bar)
+ echo not this no, no
+ ;;
+ foo)
+ echo yes, this one
+ ;;
+ esac)
+ print after case in subshell)
+ '
+0:Non-arithmetic subst with command subsitution parse from hell
+>yes, this one after case in subshell
+
+ print "a$((echo one subst)
+ (echo two subst))b"
+0:Another tricky case that is actually a command substitution
+>aone subst
+>two substb
+
+ print "x$((echo one frob); (echo two frob))y"
+0:Same on a single line
+>xone frob
+>two froby
+
+ # This case actually only works by accident: if it wasn't for the
+ # unbalanced parenthesis this would be a valid math substitution.
+ # Hence it's definitely not recommended code. However, it does give
+ # the algorithm an extra check.
+ print $((case foo in
+ foo)
+ print Worked OK
+ ;;
+ esac))
+0:Would-be math expansion with extra parenthesis making it a cmd subst
+>Worked OK
+
+ (setopt extendedglob
+ set -- 32.463
+ print ${$(( $1 * 100 ))%%.[0-9]#})
+0:Arithmetic substitution nested in parameter substitution
+>3246
+
+ print $((`:`))
+0:Null string in arithmetic evaluation after command substitution
+>0
diff --git a/Test/C02cond.ztst b/Test/C02cond.ztst
index 69001476c..6581b9d6b 100644
--- a/Test/C02cond.ztst
+++ b/Test/C02cond.ztst
@@ -8,11 +8,28 @@
cd cond.tmp
- touch unmodified
+ typeset -gi isnfs
+ [[ "$(find . -prune -fstype nfs 2>/dev/null)" == "." ]] && isnfs=1
+ if (( isnfs )) &&
+ (cd -q ${TMPPREFIX:h} >/dev/null 2>&1 &&
+ [[ "$(find . -prune -fstype nfs 2>/dev/null)" != "." ]]); then
+ filetmpprefix=${TMPPREFIX}-$$-
+ isnfs=0
+ else
+ filetmpprefix=
+ fi
+ newnewnew=${filetmpprefix}newnewnew
+ unmodified=${filetmpprefix}unmodified
+ zlnfs=${filetmpprefix}zlnfs
+
+ touch $unmodified
touch zerolength
chgrp $EGID zerolength
+ touch $zlnfs
+ chgrp $EGID $zlnfs
+
print 'Garbuglio' >nonzerolength
mkdir modish
@@ -131,19 +148,19 @@
print -u $ZTST_fd 'This test takes two seconds...'
sleep 2
- cat unmodified
- touch newnewnew
+ cat $unmodified
+ touch $newnewnew
if [[ $OSTYPE == "cygwin" ]]; then
print -u$ZTST_fd "Warning: not testing [[ -N file ]] (not supported on Cygwin)"
true
- elif [[ "$(find . -prune -fstype nfs 2>/dev/null)" == "." ]]; then
+ elif (( isnfs )); then
print -u$ZTST_fd "Warning: not testing [[ -N file ]] (not supported with NFS)"
true
elif test -f /etc/mtab && { grep $(df . 2>/dev/null| tail -n1 | awk '{print $1}') /etc/mtab | grep -q noatime; }; then
print -u$ZTST_fd "Warning: not testing [[ -N file ]] (not supported with noatime file system)"
true
else
- [[ -N newnewnew && ! -N unmodified ]]
+ [[ -N $newnewnew && ! -N $unmodified ]]
fi
0:-N cond
F:This test can fail on NFS-mounted filesystems as the access and
@@ -153,10 +170,10 @@ F:are not recorded. Also, Linux ext3 filesystems may be mounted
F:with the noatime option which does not update access times.
F:Failures in these cases do not indicate a problem in the shell.
- [[ newnewnew -nt zerolength && ! (unmodified -nt zerolength) ]]
+ [[ $newnewnew -nt $zlnfs && ! ($unmodified -nt $zlnfs) ]]
0:-nt cond
- [[ zerolength -ot newnewnew && ! (zerolength -ot unmodified) ]]
+ [[ $zlnfs -ot $newnewnew && ! ($zlnfs -ot $unmodified) ]]
0:-ot cond
[[ link -ef zerolength && ! (link -ef nonzerolength) ]]
@@ -234,8 +251,8 @@ F:Failures in these cases do not indicate a problem in the shell.
fn() {
# careful: first file must exist to trigger bug
- [[ -e unmodified ]] || print Where\'s my file\?
- [[ unmodified -nt NonExistentFile ]]
+ [[ -e $unmodified ]] || print Where\'s my file\?
+ [[ $unmodified -nt NonExistentFile ]]
print status = $?
}
fn
@@ -360,3 +377,6 @@ F:Failures in these cases do not indicate a problem in the shell.
%clean
# This works around a bug in rm -f in some versions of Cygwin
chmod 644 unmodish
+ for tmpfile in $newnewnew $unmodified $zlnfs; do
+ [[ -f $tmpfile ]] && rm -f $tmpfile
+ done
diff --git a/Test/C04funcdef.ztst b/Test/C04funcdef.ztst
index 10491a229..74f881587 100644
--- a/Test/C04funcdef.ztst
+++ b/Test/C04funcdef.ztst
@@ -271,6 +271,7 @@
>OK
>ignorebraces is off
>ignorebraces is still on here
+#` (matching error message for editors parsing the file)
# lsfoo should not be expanded as an anonymous function argument
alias lsfoo='This is not ls.'
@@ -283,6 +284,17 @@
0:Simple anonymous function should not simplify enclosing pipeline
>foo
+ alias fooalias=barexpansion
+ funcwithalias() { echo $(fooalias); }
+ functions funcwithalias
+ barexpansion() { print This is the correct output.; }
+ funcwithalias
+0:Alias expanded in command substitution does not appear expanded in text
+>funcwithalias () {
+> echo $(fooalias)
+>}
+>This is the correct output.
+
%clean
rm -f file.in file.out
diff --git a/Test/D02glob.ztst b/Test/D02glob.ztst
index 217ce7c06..3e2095a0c 100644
--- a/Test/D02glob.ztst
+++ b/Test/D02glob.ztst
@@ -548,6 +548,7 @@
(){ print "Negated:" $@:t } glob.tmp/dir*(Y1^Y)
(){ print "Sorting:" $@:t } glob.tmp/dir*(Y4On)
(){ [[ $#@ -eq 1 ]] && print Globs before last path component } glob.tmp/dir?/subdir(NY1)
+ (){ [[ $1 == glob.tmp/a ]] } glob.tmp/**/a(Y1) && print Breadth first
(){ [[ $#@ -eq 0 ]] && print Respects qualifiers } glob.tmp/dir*(NY1.)
(print -- *(Y)) 2>/dev/null || print "Argument required"
0:short-circuit modifier
@@ -558,6 +559,7 @@
>Negated: dir1 dir2 dir3 dir4
>Sorting: dir4 dir3 dir2 dir1
>Globs before last path component
+>Breadth first
>Respects qualifiers
>Argument required
diff --git a/Test/D04parameter.ztst b/Test/D04parameter.ztst
index 49dcea901..42c7b4ec6 100644
--- a/Test/D04parameter.ztst
+++ b/Test/D04parameter.ztst
@@ -1548,7 +1548,7 @@
foo=
print ${foo:wq}
print ${:wq}
-0:Empty parameter shouldn't cause modifiers to crash the shell
+0:Empty parameter should not cause modifiers to crash the shell
>
>
@@ -1636,3 +1636,66 @@
print ${noexist:^foo})
1:Zipping arrays, NO_UNSET part 2
?(eval):2: noexist: parameter not set
+
+ expr="a@b,c@d:e@f,g@h:i@j,k@l"
+ for sep in : , @; do
+ print -l ${(ps.$sep.)expr}
+ done
+0:Use of variable to get separator when splitting parameter
+>a@b,c@d
+>e@f,g@h
+>i@j,k@l
+>a@b
+>c@d:e@f
+>g@h:i@j
+>k@l
+>a
+>b,c
+>d:e
+>f,g
+>h:i
+>j,k
+>l
+
+ SHLVL=1
+ $ZTST_testdir/../Src/zsh -fc 'echo $SHLVL'
+ $ZTST_testdir/../Src/zsh -fc '(echo $SHLVL)'
+0:SHLVL appears sensible when about to exit shell
+>2
+>2
+
+# The following tests the return behaviour of parsestr/parsestrnoerr
+ alias param-test-alias='print $'\''\x45xpanded in substitution'\'
+ param='$(param-test-alias)'
+ print ${(e)param}
+0:Alias expansion in command substitution in parameter evaluation
+>Expanded in substitution
+
+ a=1 b=2 c=3
+ : One;
+ function {
+ : Two
+ echo $_
+ print -l $argv
+ } $_ Three
+ print -l $_ Four;
+0:$_ with anonymous function
+>Two
+>One
+>Three
+>Three
+>Four
+
+ a=1 b=2 c=3
+ : One
+ function {
+ : Two
+ echo $_
+ print -l $argv
+ }
+ print -l "$_" Four
+0:$_ with anonymous function without arguments
+>Two
+>
+>
+>Four
diff --git a/Test/D07multibyte.ztst b/Test/D07multibyte.ztst
index 2cb995346..33e76bee7 100644
--- a/Test/D07multibyte.ztst
+++ b/Test/D07multibyte.ztst
@@ -448,20 +448,30 @@
0:read passes through invalid multibyte characters
>0xC5
- word=abcま
+ word=abcま
word[-1]=
print $word
- word=abcま
+ word=abcま
word[-2]=
print $word
- word=abcま
+ word=abcま
word[4]=d
print $word
- word=abcま
+ word=abcま
word[3]=not_c
- print $word
+ print $word
0:assignment with negative indices
>abc
>abま
>abcd
>abnot_cま
+
+ # The following doesn't necessarily need UTF-8, but this gives
+ # us the full effect --- if we parse this wrongly the \xe9
+ # in combination with the tokenized input afterwards looks like a
+ # valid UTF-8 character. But it isn't.
+ print $'$\xe9#``' >test_bad_param
+ (setopt nonomatch
+ . ./test_bad_param)
+127:Invalid parameter name with following tokenized input
+?./test_bad_param:1: command not found: $\M-i#
diff --git a/Test/D08cmdsubst.ztst b/Test/D08cmdsubst.ztst
index 5661b0aaa..a4c69a010 100644
--- a/Test/D08cmdsubst.ztst
+++ b/Test/D08cmdsubst.ztst
@@ -106,3 +106,45 @@
>34
>"
>" OK
+
+ echo $(case foo in
+ foo)
+ echo This test worked.
+ ;;
+ bar)
+ echo This test failed in a rather bizarre way.
+ ;;
+ *)
+ echo This test failed.
+ ;;
+ esac)
+0:Parsing of command substitution with unmatched parentheses: case, basic
+>This test worked.
+
+ echo "$(case bar in
+ foo)
+ echo This test spoobed.
+ ;;
+ bar)
+ echo This test plurbled.
+ ;;
+ *)
+ echo This test bzonked.
+ ;;
+ esac)"
+0:Parsing of command substitution with unmatched parentheses: case with quotes
+>This test plurbled.
+
+ echo before $(
+ echo start; echo unpretentious |
+ while read line; do
+ case $line in
+ u*)
+ print Word began with u
+ print and ended with a crunch
+ ;;
+ esac
+ done | sed -e 's/Word/Universe/'; echo end
+ ) after
+0:Parsing of command substitution with ummatched parentheses: with frills
+>before start Universe began with u and ended with a crunch end after
diff --git a/Test/E01options.ztst b/Test/E01options.ztst
index 46b183776..5c453c80b 100644
--- a/Test/E01options.ztst
+++ b/Test/E01options.ztst
@@ -783,14 +783,37 @@
>print is a shell builtin
?(eval):8: command not found: print
-# This option seems to be problematic. I don't quite know how it works.
-## func() {
-## setopt localoptions printexitvalue
-## false
-## }
-## func
-## 1:PRINT_EXIT_VALUE option
-## ?(eval):2: exit 1
+ # With non-special command: original value restored
+ # With special builtin: new value kept
+ # With special builtin preceeded by "command": original value restored.
+ (setopt posixbuiltins
+ FOO=val0
+ FOO=val1 true; echo $FOO
+ FOO=val2 times 1>/dev/null 2>&1; echo $FOO
+ FOO=val3 command times 1>/dev/null 2>&1; echo $FOO)
+0:POSIX_BUILTINS and restoring variables
+>val0
+>val2
+>val2
+
+# PRINTEXITVALUE only works if shell input is coming from standard input.
+# Goodness only knows why.
+ $ZTST_testdir/../Src/zsh -f <<<'
+ setopt printexitvalue
+ func() {
+ false
+ }
+ func
+ '
+1:PRINT_EXIT_VALUE option
+?zsh: exit 1
+
+ $ZTST_testdir/../Src/zsh -f <<<'
+ setopt printexitvalue
+ () { false; }
+ '
+1:PRINT_EXIT_VALUE option for anonymous function
+?zsh: exit 1
setopt promptbang
print -P !
diff --git a/Test/V07pcre.ztst b/Test/V07pcre.ztst
index 3a65331b3..ddfd3f5cd 100644
--- a/Test/V07pcre.ztst
+++ b/Test/V07pcre.ztst
@@ -1,10 +1,12 @@
%prep
- if ! zmodload zsh/pcre 2>/dev/null
+ if ! zmodload -F zsh/pcre C:pcre-match 2>/dev/null
then
ZTST_unimplemented="the zsh/pcre module is not available"
return 0
fi
+# Load the rest of the builtins
+ zmodload zsh/pcre
setopt rematch_pcre
# Find a UTF-8 locale.
setopt multibyte
diff --git a/Test/V08zpty.ztst b/Test/V08zpty.ztst
index 5b08fc281..b0cbfa050 100644
--- a/Test/V08zpty.ztst
+++ b/Test/V08zpty.ztst
@@ -6,7 +6,8 @@
if ! zmodload zsh/zpty 2>/dev/null
then
ZTST_unimplemented="the zsh/zpty module is not available"
- return 0
+ elif [[ $OSTYPE = cygwin ]]; then
+ ZTST_unimplemented="the zsh/zpty module does not work on Cygwin"
fi
%test
diff --git a/Test/W01history.ztst b/Test/W01history.ztst
new file mode 100644
index 000000000..6ef9b11cc
--- /dev/null
+++ b/Test/W01history.ztst
@@ -0,0 +1,60 @@
+# Tests for BANG_HIST replacements
+
+%prep
+
+ if [[ -t 0 ]]; then print -u $ZTST_fd History tests write to /dev/tty; fi
+
+%test
+
+ $ZTST_testdir/../Src/zsh -fis <<<'
+ print one two three four five six seven eight nine ten
+ print !:$ !:10 !:9 !:1 !:0
+ print one two three four five six seven eight nine ten
+ print !:0-$ !:1-2
+ ' 2>/dev/null
+0:History word references
+>one two three four five six seven eight nine ten
+>ten ten nine one print
+>one two three four five six seven eight nine ten
+>print one two three four five six seven eight nine ten one two
+
+ $ZTST_testdir/../Src/zsh -fis <<<'
+ print line one of an arbitrary series
+ print issue two for some mystery sequence
+ print !-1:5-$
+ print !1:2
+ print !2:2
+ print !-3:1-$
+ ' 2>/dev/null
+0:History line numbering
+>line one of an arbitrary series
+>issue two for some mystery sequence
+>mystery sequence
+>one
+>two
+>mystery sequence
+
+ $ZTST_testdir/../Src/zsh -fis <<<'
+ print All metaphor, Malachi, stilts and all
+ print !1:2:s/,/\\\\?/ !1:2:s/m/shm/:s/,/\!/
+ print !1:2:&
+ print -l !1:2-3:gs/a/o/
+ ' 2>/dev/null
+0:History substitution
+>All metaphor, Malachi, stilts and all
+>metaphor? shmetaphor!
+>metaphor!
+>metophor,
+>Molochi,
+
+ $ZTST_testdir/../Src/zsh -fis <<<'
+ echo foo bar
+ echo $(!!) again
+ echo more $( !! )' 2>/dev/null
+0:Regression test for history references in command substitution
+>foo bar
+>foo bar again
+>more foo bar again
+*?*
+F:Check that a history bug introduced by workers/34160 is working again.
+# Discarded line of error output consumes prompts printed by "zsh -i".
diff --git a/Test/X02zlevi.ztst b/Test/X02zlevi.ztst
index 19188dfb7..14bc02ef8 100644
--- a/Test/X02zlevi.ztst
+++ b/Test/X02zlevi.ztst
@@ -1,7 +1,9 @@
# Tests of the vi mode of ZLE
%prep
- if ( zmodload -i zsh/zpty ) >/dev/null 2>&1; then
+ if [[ $OSTYPE = cygwin ]]; then
+ ZTST_unimplemented="the zsh/zpty module does not work on Cygwin"
+ elif ( zmodload -i zsh/zpty ) >/dev/null 2>&1; then
. $ZTST_srcdir/comptest
comptestinit -v -z $ZTST_testdir/../Src/zsh
else
@@ -10,6 +12,215 @@
%test
+ zletest $'goox\ecld'
+0:change last character in buffer
+>BUFFER: good
+>CURSOR: 4
+
+ zletest $'{ ({[}]) }\e0c%chg'
+0:change forward to matching bracket
+>BUFFER: chg
+>CURSOR: 3
+
+ zletest $'s( match )\ed%'
+0:delete backwards to matching bracket
+>BUFFER: s
+>CURSOR: 0
+
+ zletest $'one\eo\edd'
+0:delete empty line
+>BUFFER: one
+>CURSOR: 0
+
+ zletest $'1\eo\eyya2\epa3'
+0:yank and paste blank line
+>BUFFER: 1
+>2
+>3
+>CURSOR: 5
+
+ zpty_run 'bindkey -r "\e~"'
+ zletest $'\e' $'~aI\e' $'~o\e' \~
+0:swap case on a blank line
+>BUFFER: i
+>
+>CURSOR: 2
+
+ zletest $'\eOword\eO\eraok\ejrxj.rae'
+0:replace character when at end of buffer or newline
+>BUFFER: ok
+>wxrd
+>e
+>CURSOR: 9
+
+ zletest $'two\eOone\ehRreplace'
+0:replace acts like insert at newline
+>BUFFER: oreplace
+>two
+>CURSOR: 8
+
+ zletest $' four\eO\C-v\tthree\eO two\eOone\e3J'
+0:join lines with line count
+>BUFFER: one two three
+> four
+>CURSOR: 7
+
+# like real vi, we just join as many as possible, in vim this beeps
+ zletest $'two\eOone\e3J'
+0:join more lines than possible
+>BUFFER: one two
+>CURSOR: 3
+
+ zletest $'fi\eO\eOif\e2>j'
+0:don't indent blank lines
+>BUFFER: if
+>
+> fi
+>CURSOR: 1
+
+ zletest $'\C-v\ti\e>>'
+0:additional indentation
+>BUFFER: i
+>CURSOR: 2
+
+ zletest $'one\eox\e>k'
+0:indent with one character on final line
+>BUFFER: one
+> x
+>CURSOR: 1
+
+ zletest $'one two\eyb'
+0:yank left moves the cursor
+>BUFFER: one two
+>CURSOR: 4
+
+ zletest $'one two\e0ye'
+0:yank right leaves the cursor
+>BUFFER: one two
+>CURSOR: 0
+
+ zletest $'short\eoand longer\eyk'
+0:yank up line moves cursor up but not to buffer start
+>BUFFER: short
+>and longer
+>CURSOR: 4
+
+ zletest $'one\eotwo\ekyj'
+0:yank down line leaves the cursor
+>BUFFER: one
+>two
+>CURSOR: 2
+
+ zletest $'long\eo s\eolong\ekjy-k'
+0:yank up clears lastcol
+>BUFFER: long
+> s
+>long
+>CURSOR: 2
+
+ zletest $'long\eos\eklljyk'
+0:yank up honours lastcol
+>BUFFER: long
+>s
+>CURSOR: 2
+
+ zletest $'long\eolong\eo s\eolong\ekjd-k'
+0:delete up clears lastcol
+>BUFFER: long
+>long
+>CURSOR: 0
+
+ zletest $'yankee doodle\ebhDyy0"1P'
+0:paste register 1 to get last deletion
+>BUFFER: doodleyankee
+>CURSOR: 6
+
+ zletest $'yankee\eyyodoodle\edd"0p'
+0:paste register 0 to get last yank
+>BUFFER: yankee
+>yankee
+>CURSOR: 7
+
+ zletest $'err\eddahello\e"hddP'
+0:setting named register also sets unnamed register
+>BUFFER: hello
+>
+>CURSOR: 0
+
+ zletest $'first\e"ay0ddasecond\e"Add"aP'
+0:appending to named register
+>BUFFER: firs
+>second
+>
+>CURSOR: 0
+
+ zletest $'word\e"a"byy"bp'
+0:set one and then a different register
+>BUFFER: word
+>word
+>CURSOR: 5
+
+ zletest $'i\exaar\e0"a"_cewn\eP'
+0:set register then set black hole register
+>BUFFER: win
+>CURSOR: 1
+
+ zletest $'double\eyy"_"0P'
+0:reset register after selecting black hole
+>BUFFER: double
+>double
+>CURSOR: 0
+
+# zsh works like vi here; in vim you get the concatenated string
+ zletest $'first\e"addasecond\eddP'
+0:retrieve unnamed register after appending
+>BUFFER: second
+>
+>CURSOR: 0
+
+ zletest $'Z\exayankee doodle\e"_db0"_yeP'
+0:yank and delete to black hole register
+>BUFFER: Zyankee e
+>CURSOR: 0
+
+ zletest $'foo\eddabar\e"_p..'
+0:paste from black hole register and repeat
+>BUFFER: bar
+>CURSOR: 2
+
+ zletest $'start\eFa"ac2lnew\eX"ap..'
+0:repeat paste from named register
+>BUFFER: stnwararart
+>CURSOR: 9
+
+ zpty_run 'bindkey -a "^P" yank-pop'
+ zletest $'word\C-wline\eddiSE\eP\C-P'
+0:line based put before followed by character based yank-pop
+>BUFFER: SwordE
+>CURSOR: 4
+
+ zletest $'line\eddiword\C-w\eiSE\eP\C-P'
+0:character based put before followed by line based yank-pop
+>BUFFER: line
+>SE
+>CURSOR: 0
+
+ zletest $'one two three\C-w\C-w\C-wSE\e0p\C-P\C-P'
+0:put after cycled twice with yank-pop
+>BUFFER: SthreeE
+>CURSOR: 5
+
+ zletest $'word\C-wline\eddiSE\ehp\C-P'
+0:line based put after followed by character based yank-pop
+>BUFFER: SwordE
+>CURSOR: 4
+
+ zletest $'line\eddiword\C-w\eiSE\ehp\C-P'
+0:character based after before followed by line based yank-pop
+>BUFFER: SE
+>line
+>CURSOR: 3
+
zletest $'word\euaend'
0:undo initial change
>BUFFER: end
@@ -61,6 +272,12 @@
>BUFFER: pre
>CURSOR: 2
+ zletest $'two\eOone\eo\euo\eu'
+0:undo starting with a next change in the change list
+>BUFFER: one
+>two
+>CURSOR: 2
+
zpty_run 'bindkey "^Gu" split-undo'
zletest $'one\C-gutwo\eu'
0:split the undo sequence
@@ -72,6 +289,278 @@
>BUFFER: one wo
>CURSOR: 2
+ zletest $'keepnot\eo unwanted\ekhhcvj '
+0:force character-wise change to join lines
+>BUFFER: keep wanted
+>CURSOR: 5
+
+ zletest $'}\eOkeep{del\eF{dvj'
+0:character-wise delete to beginning of line leaves the newline'
+>BUFFER: keep
+>}
+>CURSOR: 3
+
+ zletest $'keep\eOdel\edVh'
+0:force line-wise delete of line
+>BUFFER: keep
+>CURSOR: 0
+
+ zletest $'one two three\eFwdVawaX'
+0:line-wise force of a text object
+>BUFFER: X
+>CURSOR: 1
+
+ zletest $'one two\evbcx'
+0:change selection
+>BUFFER: one x
+>CURSOR: 5
+
+ zletest $'four\eOthree\eOtwo\eOone\evjjhCnew'
+0:change character wise selection with C acts linewise
+>BUFFER: new
+>four
+>CURSOR: 3
+
+ zletest $'x testing\ehvbx'
+0:x kills selections
+>BUFFER: x g
+>CURSOR: 2
+
+ zletest $'line end\eOstart 1 back new\e0verawvrbwevbrcwvj0erdwv$re'
+0:replace characters in selections
+>BUFFER: aaaaa b cccc dddddddd eee
+>CURSOR: 24
+
+ zletest $'one two\eyb0vep'
+0:put over selection at start of buffer
+>BUFFER: tw two
+>CURSOR: 1
+
+ zletest $'hello\C-wbye\evhp'
+0:put over selection at end of buffer
+>BUFFER: bhello
+>CURSOR: 5
+
+ zletest $'old\C-w\evyvP'
+0:yank empty selection
+>BUFFER: old
+>CURSOR: 2
+
+ zletest $'old\C-w\evdvP'
+0:delete empty selection
+>BUFFER: old
+>CURSOR: 2
+
+ zletest $'one\eotwo\eyykVp'
+0:yank linewise and put over linewise selection at start of buffer
+>BUFFER: two
+>two
+>CURSOR: 0
+
+ zletest $'one\eotwo\eothree\eyykVp'
+0:yank linewise and put over linewise selection in middle of buffer
+>BUFFER: one
+>three
+>three
+>CURSOR: 4
+
+ zletest $'two\eOone\eyyjVp'
+0:yank linewise and put over linewise selection at end of buffer
+>BUFFER: one
+>one
+>CURSOR: 4
+
+ zletest $'one\eyhVp'
+0:yank character-wise and put over linewise selection
+>BUFFER: n
+>CURSOR: 0
+
+# vim puts a blank line above in this test
+ zletest $'one\eotwo\eyy0kvlp'
+0:yank linewise and put over character-wise selection at start of buffer
+>BUFFER: two
+>e
+>two
+>CURSOR: 0
+
+ zletest $'one\eyyhvp'
+0:yank linewise and put over character-wise selection in middle of buffer
+>BUFFER: o
+>one
+>e
+>CURSOR: 2
+
+# vim behaviour on this one really looks like a bug
+ zletest $'two\eOone\eyyjvhp'
+0:yank linewise and put over character-wise selection at end of buffer
+>BUFFER: one
+>t
+>one
+>CURSOR: 6
+
+ zletest $'abc123456789\exxxxxxxxxhv"9p0P'
+0:paste last (9th) register over a selection
+>BUFFER: ba9c
+>CURSOR: 0
+
+ zletest $'one\eo\eo\eotwo\ekkVdvd'
+0:delete blank line using selection
+>BUFFER: one
+>two
+>CURSOR: 4
+
+ zletest $'One Two Three\e2bvw~'
+0:toggle case of selection
+>BUFFER: One tWO three
+>CURSOR: 4
+
+ zletest $' --ww ww--\eo\eoww\eo\eo--\eo\eo ww\e' bi{a,b,c,d,e,f,g,h,i,j,k}$'\e'
+0:backward word
+>BUFFER: k j--iww hwwg--
+>f
+>eww
+>d
+>c--
+>b
+> aww
+>CURSOR: 0
+
+ zletest $' --ww ww--\eo\eoww\eo\eo--\eo\eo ww\e' Bi{a,b,c,d,e,f,g,h,i}$'\e'
+0:backword blank word
+>BUFFER: i h--ww gww--
+>f
+>eww
+>d
+>c--
+>b
+> aww
+>CURSOR: 0
+
+ zletest $' --ww ww--\eo\eoww\eo\eo--\eo\eo ww\e' gei{a,=,b,c,=,d,e,=,f}$'\e'
+0:backward word end
+>BUFFER: f -=-wew wdw-=-
+>c
+>wbw
+>
+>-=-
+>a
+> ww
+>CURSOR: 0
+
+ zletest $' --ww ww--\eo\eoww\eo\eo--\eo\eo ww\e' gEi{=,b,=,d,e}$'\e'
+0:backward blank word end
+>BUFFER: e --wdw ww-=-
+>
+>wbw
+>
+>-=-
+>
+> ww
+>CURSOR: 0
+
+ zletest $' ww\eO\eO--\eO\eOww\eO\eO --ww ww--\e0' wi{=,a,b,=,c,d,e,=,f,g}$'\e'
+0:forward word
+>BUFFER: =--aww bww=--
+>c
+>dww
+>e
+>=--
+>f
+> gww
+>CURSOR: 32
+
+ zletest $' ww\eO\eO--\eO\eOww\eO\eO --ww ww--\e0' Wi{=,a,b,c,d,=,e,f}$'\e'
+0:forward blank word
+>BUFFER: =--ww aww--
+>b
+>cww
+>d
+>=--
+>e
+> fww
+>CURSOR: 30
+
+ zletest $' ww\eO\eO--\eO\eOww\eO\eO --ww ww--\e0' ea{a,b,c,d,e,f,g}$'\e'
+0:forward word end
+>BUFFER: --awwb wwc--d
+>
+>wwe
+>
+>--f
+>
+> wwg
+>CURSOR: 31
+
+ zletest $' ww\eO\eO--\eO\eOww\eO\eO --ww ww--\e0' Ea{a,b,c,d,e}$'\e'
+0:forward blank word end
+>BUFFER: --wwa ww--b
+>
+>wwc
+>
+>--d
+>
+> wwe
+>CURSOR: 29
+
+ zletest $' ----word ---- word word---- ----\e42|daw30|daw22|daw14|daw2|daw'
+0:delete all word on blanks
+>BUFFER: word
+>CURSOR: 0
+
+ zletest $' word----word word----word word \e38|daw30|daw22|daw14|daw6|daw'
+0:delete all word on alphanumerics
+>BUFFER: --------
+>CURSOR: 4
+
+ zletest $' ----word---- ----word---- ---- \e38|daw30|daw22|daw14|daw6|daw'
+0:delete all word on other characters
+>BUFFER: wordword
+>CURSOR: 4
+
+ zletest $'- word word\e4|2daw'
+0:delete all word with numeric argument
+>BUFFER: -
+>CURSOR: 0
+
+ zletest $'---- word ----word\eo \eo----\eodone\eh' \
+ 'vhawmaawmbawmcawmdawmeawmfawmgv`ara`brb`crc$r$`drd`ere`frf`grg'
+0:all word with existing selection and cursor before mark
+>BUFFER: g---f worde ----dord
+>c $
+>b---
+>aone
+>CURSOR: 0
+
+ zletest $'---- word word----\e0lvlawmaawmbawmcawvrd`ara`brb`crc'
+0:all word with existing selection and mark before cursor
+>BUFFER: ---- aword bworc---d
+>CURSOR: 19
+
+ zletest $' --ww ww---\eo\eoww\evhiwiw' m{a,b,c,d,e}iw vrE \`{a,b,c,d,e}r.
+0:in word with existing selection and cursor before mark
+>BUFFER: E.-.w. .w.--
+>
+>ww
+>CURSOR: 1
+
+ zletest $' --ww ww--\eO \ev0o' m{a,b,c,d,e}iw vrE \`{a,b,c,d,e}r.
+0:in word with existing selection and mark before cursor
+>BUFFER: .
+> .-.w. .wE--
+>CURSOR: 10
+
+ zletest $' `one` $(echo two) " three " $\'four\'\C-v\tfive ${six:-6}\e' \
+ vaaom{a,b,c,d,e,f}v \`{a,b,c,d,e,f}rX
+0:all argument for different arguments
+>BUFFER: X `one`X $(echo two)X" three "X$'four'XfiveX${six:-6}
+>CURSOR: 0
+
+ zletest $'{ls `echo x` $((3+4)) "a b" $\'\\t\\n\' ${d%/}\e' \
+ cia{6,5,4,3,2,1}$'\eBB'
+0:in argument for different arguments
+>BUFFER: 1ls `2` $(3) "4" $'5' ${6}
+>CURSOR: 0
+
%clean
zmodload -ui zsh/zpty
diff --git a/Test/Y01completion.ztst b/Test/Y01completion.ztst
index a2aa00717..383e6529f 100644
--- a/Test/Y01completion.ztst
+++ b/Test/Y01completion.ztst
@@ -1,7 +1,9 @@
# Tests for completion system.
%prep
- if ( zmodload -i zsh/zpty ) >/dev/null 2>&1; then
+ if [[ $OSTYPE = cygwin ]]; then
+ ZTST_unimplemented="the zsh/zpty module does not work on Cygwin"
+ elif ( zmodload -i zsh/zpty ) >/dev/null 2>&1; then
. $ZTST_srcdir/comptest
mkdir comp.tmp
cd comp.tmp
diff --git a/Test/Y02compmatch.ztst b/Test/Y02compmatch.ztst
index 704580043..db734facc 100644
--- a/Test/Y02compmatch.ztst
+++ b/Test/Y02compmatch.ztst
@@ -11,7 +11,9 @@
# contains the compadd output.
%prep
- if ( zmodload -i zsh/zpty ) >/dev/null 2>&1; then
+ if [[ $OSTYPE = cygwin ]]; then
+ ZTST_unimplemented="the zsh/zpty module does not work on Cygwin"
+ elif ( zmodload -i zsh/zpty ) >/dev/null 2>&1; then
. $ZTST_srcdir/comptest
mkdir match.tmp
cd match.tmp
diff --git a/Test/Y03arguments.ztst b/Test/Y03arguments.ztst
index bfdcdec63..0627104f5 100644
--- a/Test/Y03arguments.ztst
+++ b/Test/Y03arguments.ztst
@@ -1,7 +1,9 @@
# Tests for _arguments.
%prep
- if ( zmodload -i zsh/zpty ) >/dev/null 2>&1; then
+ if [[ $OSTYPE = cygwin ]]; then
+ ZTST_unimplemented="the zsh/zpty module does not work on Cygwin"
+ elif ( zmodload -i zsh/zpty ) >/dev/null 2>&1; then
. $ZTST_srcdir/comptest
mkdir comp.tmp
cd comp.tmp
diff --git a/Test/comptest b/Test/comptest
index 4655f3b2b..20a3a5b1d 100644
--- a/Test/comptest
+++ b/Test/comptest
@@ -34,8 +34,9 @@ comptestinit () {
"fpath=( $fpath )" \
"bindkey -$comptest_keymap" \
'LISTMAX=10000000
-stty 38400 columns 80 rows 24
+stty 38400 columns 80 rows 24 tabs -icanon -iexten
TERM=vt100
+KEYTIMEOUT=1
setopt zle
autoload -U compinit
compinit -u
@@ -159,13 +160,18 @@ comptest () {
}
zletest () {
- input="$*"
- # zpty_flush Before zletest
- zpty -n -w zsh "$input"$'\C-X'
+ local first=0
+ for input; do
+ # zpty_flush Before zletest
+ # sleep for $KEYTIMEOUT
+ (( first++ )) && { sleep 2 & } | read -t 0.011 -u 0 -k 1
+ zpty -n -w zsh "$input"
+ done
+ zpty -n -w zsh $'\C-X'
zpty -r -m zsh log "*<WIDGET><finish>*<PROMPT>*" || {
print "failed to invoke finish widget."
return 1
}
# zpty_flush After zletest
- print -lr "${(@)${(ps:\r\n:)log##*<WIDGET><finish>}[1,-2]}"
+ print -lr "${(@)${(@ps:\r\n:)log##*<WIDGET><finish>}[2,-2]}"
}
diff --git a/configure.ac b/configure.ac
index 306a0057d..e4de193ed 100644
--- a/configure.ac
+++ b/configure.ac
@@ -318,7 +318,8 @@ fi], [sitefndir=${datadir}/${tzsh_name}/site-functions])
dnl Add /usr/local/share/zsh/site-functions if not yet present
dnl owing to $sitefndir, whether or not explicitly given.
dnl If not explicitly given, it hasn't been expanded yet.
-if test X$sitefndir = X/usr/local/share/zsh/site-functions
+if test X$sitefndir = X/usr/local/share/zsh/site-functions || \
+ test X$sitefndir = Xno
then fixed_sitefndir=''
elif test X$prefix != X/usr/local; then
if test X$prefix = XNONE && test X$ac_default_prefix = X/usr/local; then
@@ -1291,6 +1292,7 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
pcre_compile pcre_study pcre_exec \
nl_langinfo \
erand48 open_memstream \
+ posix_openpt \
wctomb iconv \
grantpt unlockpt ptsname \
htons ntohs \
@@ -1298,9 +1300,27 @@ AC_CHECK_FUNCS(strftime strptime mktime timelocal \
gdbm_open getxattr \
realpath canonicalize_file_name \
symlink getcwd \
- cygwin_conv_path)
+ cygwin_conv_path \
+ nanosleep)
AC_FUNC_STRCOLL
+AH_TEMPLATE([REALPATH_ACCEPTS_NULL],
+[Define if realpath() accepts NULL as its second argument.])
+AC_CACHE_CHECK([if realpath accepts NULL],
+zsh_cv_func_realpath_accepts_null,
+[AC_RUN_IFELSE([AC_LANG_PROGRAM([
+#include <stdlib.h>
+#include <limits.h>
+],[
+exit(!realpath("/", (char*)0));
+])],
+[zsh_cv_func_realpath_accepts_null=yes],
+[zsh_cv_func_realpath_accepts_null=no],
+[zsh_cv_func_realpath_accepts_null=$ac_cv_func_canonicalize_file_name])])
+if test x$zsh_cv_func_realpath_accepts_null = xyes; then
+ AC_DEFINE(REALPATH_ACCEPTS_NULL)
+fi
+
if test x$enable_cap = xyes; then
AC_CHECK_FUNCS(cap_get_proc)
fi
@@ -2548,6 +2568,8 @@ AH_TEMPLATE([MULTIBYTE_SUPPORT],
[Define to 1 if you want support for multibyte character sets.])
AH_TEMPLATE([BROKEN_WCWIDTH],
[Define to 1 if the wcwidth() function is present but broken.])
+AH_TEMPLATE([BROKEN_ISPRINT],
+[Define to 1 if the isprint() function is broken under UTF-8 locale.])
if test x$zsh_cv_c_unicode_support = xyes; then
AC_DEFINE(MULTIBYTE_SUPPORT)
@@ -2603,6 +2625,38 @@ if test x$zsh_cv_c_unicode_support = xyes; then
if test x$zsh_cv_c_broken_wcwidth = xyes; then
AC_DEFINE(BROKEN_WCWIDTH)
fi
+
+ dnl Check if isprint() behaves correctly under UTF-8 locale.
+ dnl On some platform (maybe only on Mac OS X), isprint() returns
+ dnl true for all characters in the range from 0xa0 to 0xff if
+ dnl called under UTF-8 locale.
+ [locale_prog='char *my_locales[] = {
+ "en_US.UTF-8", "en_GB.UTF-8", "en.UTF-8", '
+ locale_prog="$locale_prog"`locale -a 2>/dev/null | \
+ sed -e 's/utf8/UTF-8/' | grep UTF-8 | \
+ while read line; do echo " \"$line\","; done;`
+ locale_prog="$locale_prog 0 };
+ #include <locale.h>
+ #include <ctype.h>
+
+ int main() {
+ char **localep;
+ for (localep = my_locales; *localep; localep++)
+ if (setlocale(LC_ALL, *localep) && isprint(0xa0))
+ return 0;
+ return 1;
+ }
+ "]
+
+ AC_CACHE_CHECK(if the isprint() function is broken,
+ zsh_cv_c_broken_isprint,
+ [AC_TRY_RUN([$locale_prog],
+ zsh_cv_c_broken_isprint=yes,
+ zsh_cv_c_broken_isprint=no,
+ zsh_cv_c_broken_isprint=no)])
+ if test x$zsh_cv_c_broken_isprint = xyes; then
+ AC_DEFINE(BROKEN_ISPRINT)
+ fi
fi
dnl