diff options
| author | Jim Porter | 2022-01-04 12:58:38 -0800 |
|---|---|---|
| committer | Eli Zaretskii | 2022-01-12 16:58:37 +0200 |
| commit | db745f37aec2adc44ec4b2eae0720e0365ed0ca9 (patch) | |
| tree | 1c2b405ad2bc81d34fd2ae140c18855d78460665 | |
| parent | 7ebcb4b6f2f4531ebc893bb3b2f74d6298bf9b41 (diff) | |
| download | emacs-db745f37aec2adc44ec4b2eae0720e0365ed0ca9.tar.gz emacs-db745f37aec2adc44ec4b2eae0720e0365ed0ca9.zip | |
Follow POSIX/GNU argument conventions for 'eshell-eval-using-options'
* lisp/eshell/esh-opt.el (eshell--split-switch): New function.
(eshell-set-option): Allow setting a supplied value instead of always
consuming from 'eshell--args'.
(eshell--process-option): Support consuming option values specified as
a single token.
(eshell--process-args): For short options, pass full switch token to
'eshell--process-option'.
* test/lisp/eshell/esh-opt-tests.el (esh-opt-process-args-test): Fix
test.
(test-eshell-eval-using-options): Add tests for various types of
options.
* doc/misc/eshell.texi (Defining new built-in commands): New
subsection, describe how to use 'eshell-eval-using-options'.
* etc/NEWS: Announce the change.
| -rw-r--r-- | doc/misc/eshell.texi | 120 | ||||
| -rw-r--r-- | etc/NEWS | 6 | ||||
| -rw-r--r-- | lisp/eshell/esh-opt.el | 90 | ||||
| -rw-r--r-- | test/lisp/eshell/esh-opt-tests.el | 151 |
4 files changed, 298 insertions, 69 deletions
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index 83d324c7e1b..f1d7c638056 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi | |||
| @@ -694,6 +694,126 @@ Print the current user. This Eshell version of @command{whoami} | |||
| 694 | supports Tramp. | 694 | supports Tramp. |
| 695 | @end table | 695 | @end table |
| 696 | 696 | ||
| 697 | @subsection Defining new built-in commands | ||
| 698 | While Eshell can run Lisp functions directly as commands, it may be | ||
| 699 | more convenient to provide a special built-in command for | ||
| 700 | Eshell. Built-in commands are just ordinary Lisp functions designed | ||
| 701 | to be called from Eshell. When defining an Eshell-specific version of | ||
| 702 | an existing function, you can give that function a name starting with | ||
| 703 | @code{eshell/} so that Eshell knows to use it. | ||
| 704 | |||
| 705 | @defmac eshell-eval-using-options name macro-args options body@dots{} | ||
| 706 | This macro processes a list of @var{macro-args} for the command | ||
| 707 | @var{name} using a set of command line @var{options}. If the | ||
| 708 | arguments are parsed successfully, it will store the resulting values | ||
| 709 | in local symbols and execute @var{body}; any remaining arguments will | ||
| 710 | be available in the locally let-bound variable @code{args}. The | ||
| 711 | return value is the value of the last form in @var{body}. | ||
| 712 | |||
| 713 | If an unknown option was passed in @var{macro-args} and an external | ||
| 714 | command was specified (see below), this macro will start a process for | ||
| 715 | that command and throw the tag @code{eshell-external} with the new | ||
| 716 | process as its value. | ||
| 717 | |||
| 718 | @var{options} should be a list beginning with one or more elements of | ||
| 719 | the following form, with each element representing a particular | ||
| 720 | command-line switch: | ||
| 721 | |||
| 722 | @example | ||
| 723 | (@var{short} @var{long} @var{value} @var{symbol} @var{help-string}) | ||
| 724 | @end example | ||
| 725 | |||
| 726 | @table @var | ||
| 727 | @item short | ||
| 728 | This element, if non-nil, should be a character to be used as a short | ||
| 729 | switch, like @code{-@var{short}}. At least one of this element and | ||
| 730 | @var{long} must be non-nil. | ||
| 731 | |||
| 732 | @item long | ||
| 733 | This element, if non-nil, should be a string to be used as a long | ||
| 734 | switch, like @code{--@var{long}}. | ||
| 735 | |||
| 736 | @item value | ||
| 737 | This element is the value associated with the option. It can be | ||
| 738 | either: | ||
| 739 | |||
| 740 | @table @asis | ||
| 741 | @item @code{t} | ||
| 742 | The option needs a value to be specified after the switch. | ||
| 743 | |||
| 744 | @item @code{nil} | ||
| 745 | The option is given the value @code{t}. | ||
| 746 | |||
| 747 | @item anything else | ||
| 748 | The option is given the specified value. | ||
| 749 | @end table | ||
| 750 | |||
| 751 | @item symbol | ||
| 752 | This element is the Lisp symbol that will be bound to @var{value}. If | ||
| 753 | @var{symbol} is @code{nil}, specifying this switch will instead call | ||
| 754 | @code{eshell-show-usage}, and so is appropriate for an option like | ||
| 755 | @code{--help}. | ||
| 756 | |||
| 757 | @item help-string | ||
| 758 | This element is a documentation string for the option, which will be | ||
| 759 | displayed when @code{eshell-show-usage} is invoked. | ||
| 760 | @end table | ||
| 761 | |||
| 762 | After the list of command-line switch elements, @var{options} can | ||
| 763 | include additional keyword arguments to control how | ||
| 764 | @code{eshell-eval-using-options} behaves. Some of these take | ||
| 765 | arguments, while others don't. The recognized keywords are: | ||
| 766 | |||
| 767 | @table @code | ||
| 768 | @item :external @var{string} | ||
| 769 | Specify @var{string} as an external command to run if there are | ||
| 770 | unknown switches in @var{macro-args}. | ||
| 771 | |||
| 772 | @item :usage @var{string} | ||
| 773 | Set @var{string} as the initial part of the command's documentation | ||
| 774 | string. It appears before the options are listed. | ||
| 775 | |||
| 776 | @item :post-usage @var{string} | ||
| 777 | Set @var{string} to be the (optional) trailing part of the command's | ||
| 778 | documentation string. It appears after the list of options, but | ||
| 779 | before the final part of the documentation about the associated | ||
| 780 | external command, if there is one. | ||
| 781 | |||
| 782 | @item :show-usage | ||
| 783 | If present, then show the usage message if the command is called with | ||
| 784 | no arguments. | ||
| 785 | |||
| 786 | @item :preserve-args | ||
| 787 | Normally, @code{eshell-eval-using-options} flattens the list of | ||
| 788 | arguments in @var{macro-args} and converts each to a string. If this | ||
| 789 | keyword is present, avoid doing that, instead preserving the original | ||
| 790 | arguments. This is useful for commands which want to accept arbitrary | ||
| 791 | Lisp objects. | ||
| 792 | |||
| 793 | @item :parse-leading-options-only | ||
| 794 | If present, do not parse dash or switch arguments after the first | ||
| 795 | positional argument. Instead, treat them as positional arguments | ||
| 796 | themselves. | ||
| 797 | @end table | ||
| 798 | |||
| 799 | For example, you could handle a subset of the options for the | ||
| 800 | @code{ls} command like this: | ||
| 801 | |||
| 802 | @example | ||
| 803 | (eshell-eval-using-options | ||
| 804 | "ls" macro-args | ||
| 805 | '((?a nil nil show-all "show all files") | ||
| 806 | (?I "ignore" t ignore-pattern "ignore files matching pattern") | ||
| 807 | (nil "help" nil nil "show this help message") | ||
| 808 | :external "ls" | ||
| 809 | :usage "[OPTION]... [FILE]... | ||
| 810 | List information about FILEs (the current directory by default).") | ||
| 811 | ;; List the files in ARGS somehow... | ||
| 812 | ) | ||
| 813 | @end example | ||
| 814 | |||
| 815 | @end defmac | ||
| 816 | |||
| 697 | @subsection Built-in variables | 817 | @subsection Built-in variables |
| 698 | Eshell knows a few built-in variables: | 818 | Eshell knows a few built-in variables: |
| 699 | 819 | ||
| @@ -1090,6 +1090,12 @@ dimensions. | |||
| 1090 | Specifying a cons as the from argument allows to start measuring text | 1090 | Specifying a cons as the from argument allows to start measuring text |
| 1091 | from a specified amount of pixels above or below a position. | 1091 | from a specified amount of pixels above or below a position. |
| 1092 | 1092 | ||
| 1093 | --- | ||
| 1094 | ** 'eshell-eval-using-options' now follows POSIX/GNU argument syntax conventions. | ||
| 1095 | Built-in commands in Eshell now accept command-line options with | ||
| 1096 | values passed as a single token, such as '-oVALUE' or | ||
| 1097 | '--option=VALUE'. | ||
| 1098 | |||
| 1093 | ** XDG support | 1099 | ** XDG support |
| 1094 | 1100 | ||
| 1095 | *** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable. | 1101 | *** New function 'xdg-state-home' returns 'XDG_STATE_HOME' environment variable. |
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el index d96b77ddd37..bba1c4ad25d 100644 --- a/lisp/eshell/esh-opt.el +++ b/lisp/eshell/esh-opt.el | |||
| @@ -187,49 +187,82 @@ passed to this command, the external version `%s' | |||
| 187 | will be called instead." extcmd))))) | 187 | will be called instead." extcmd))))) |
| 188 | (throw 'eshell-usage usage))) | 188 | (throw 'eshell-usage usage))) |
| 189 | 189 | ||
| 190 | (defun eshell--set-option (name ai opt options opt-vals) | 190 | (defun eshell--split-switch (switch kind) |
| 191 | "Split SWITCH into its option name and potential value, if any. | ||
| 192 | KIND should be the integer 0 if SWITCH is a short option, or 1 if it's | ||
| 193 | a long option." | ||
| 194 | (if (eq kind 0) | ||
| 195 | ;; Short option | ||
| 196 | (cons (aref switch 0) | ||
| 197 | (and (> (length switch) 1) (substring switch 1))) | ||
| 198 | ;; Long option | ||
| 199 | (save-match-data | ||
| 200 | (string-match "\\([^=]*\\)\\(?:=\\(.*\\)\\)?" switch) | ||
| 201 | (cons (match-string 1 switch) (match-string 2 switch))))) | ||
| 202 | |||
| 203 | (defun eshell--set-option (name ai opt value options opt-vals) | ||
| 191 | "Using NAME's remaining args (index AI), set the OPT within OPTIONS. | 204 | "Using NAME's remaining args (index AI), set the OPT within OPTIONS. |
| 192 | If the option consumes an argument for its value, the argument list | 205 | VALUE is the potential value of the OPT, coming from args like |
| 193 | will be modified." | 206 | \"-fVALUE\" or \"--foo=VALUE\", or nil if no value was supplied. If |
| 207 | OPT doesn't consume a value, return VALUE unchanged so that it can be | ||
| 208 | processed later; otherwsie, return nil. | ||
| 209 | |||
| 210 | If the OPT consumes an argument for its value and VALUE is nil, the | ||
| 211 | argument list will be modified." | ||
| 194 | (if (not (nth 3 opt)) | 212 | (if (not (nth 3 opt)) |
| 195 | (eshell-show-usage name options) | 213 | (eshell-show-usage name options) |
| 196 | (setcdr (assq (nth 3 opt) opt-vals) | 214 | (if (eq (nth 2 opt) t) |
| 197 | (if (eq (nth 2 opt) t) | 215 | (progn |
| 198 | (if (> ai (length eshell--args)) | 216 | (setcdr (assq (nth 3 opt) opt-vals) |
| 199 | (error "%s: missing option argument" name) | 217 | (or value |
| 200 | (pop (nthcdr ai eshell--args))) | 218 | (if (> ai (length eshell--args)) |
| 201 | (or (nth 2 opt) t))))) | 219 | (error "%s: missing option argument" name) |
| 220 | (pop (nthcdr ai eshell--args))))) | ||
| 221 | nil) | ||
| 222 | (setcdr (assq (nth 3 opt) opt-vals) | ||
| 223 | (or (nth 2 opt) t)) | ||
| 224 | value))) | ||
| 202 | 225 | ||
| 203 | (defun eshell--process-option (name switch kind ai options opt-vals) | 226 | (defun eshell--process-option (name switch kind ai options opt-vals) |
| 204 | "For NAME, process SWITCH (of type KIND), from args at index AI. | 227 | "For NAME, process SWITCH (of type KIND), from args at index AI. |
| 205 | The SWITCH will be looked up in the set of OPTIONS. | 228 | The SWITCH will be looked up in the set of OPTIONS. |
| 206 | 229 | ||
| 207 | SWITCH should be either a string or character. KIND should be the | 230 | SWITCH should be a string starting with the option to process, |
| 208 | integer 0 if it's a character, or 1 if it's a string. | 231 | possibly followed by its value, e.g. \"u\" or \"uUSER\". KIND should |
| 209 | 232 | be the integer 0 if it's a short option, or 1 if it's a long option. | |
| 210 | The SWITCH is then be matched against OPTIONS. If no matching handler | 233 | |
| 211 | is found, and an :external command is defined (and available), it will | 234 | The SWITCH is then be matched against OPTIONS. If KIND is 0 and the |
| 212 | be called; otherwise, an error will be triggered to say that the | 235 | SWITCH matches an option that doesn't take a value, return the |
| 213 | switch is unrecognized." | 236 | remaining characters in SWITCH to be processed later as further short |
| 214 | (let* ((opts options) | 237 | options. |
| 215 | found) | 238 | |
| 239 | If no matching handler is found, and an :external command is defined | ||
| 240 | (and available), it will be called; otherwise, an error will be | ||
| 241 | triggered to say that the switch is unrecognized." | ||
| 242 | (let ((switch (eshell--split-switch switch kind)) | ||
| 243 | (opts options) | ||
| 244 | found remaining) | ||
| 216 | (while opts | 245 | (while opts |
| 217 | (if (and (listp (car opts)) | 246 | (if (and (listp (car opts)) |
| 218 | (nth kind (car opts)) | 247 | (equal (car switch) (nth kind (car opts)))) |
| 219 | (equal switch (nth kind (car opts)))) | ||
| 220 | (progn | 248 | (progn |
| 221 | (eshell--set-option name ai (car opts) options opt-vals) | 249 | (setq remaining (eshell--set-option name ai (car opts) |
| 250 | (cdr switch) options opt-vals)) | ||
| 251 | (when (and remaining (eq kind 1)) | ||
| 252 | (error "%s: option --%s doesn't allow an argument" | ||
| 253 | name (car switch))) | ||
| 222 | (setq found t opts nil)) | 254 | (setq found t opts nil)) |
| 223 | (setq opts (cdr opts)))) | 255 | (setq opts (cdr opts)))) |
| 224 | (unless found | 256 | (if found |
| 257 | remaining | ||
| 225 | (let ((extcmd (memq ':external options))) | 258 | (let ((extcmd (memq ':external options))) |
| 226 | (when extcmd | 259 | (when extcmd |
| 227 | (setq extcmd (eshell-search-path (cadr extcmd))) | 260 | (setq extcmd (eshell-search-path (cadr extcmd))) |
| 228 | (if extcmd | 261 | (if extcmd |
| 229 | (throw 'eshell-ext-command extcmd) | 262 | (throw 'eshell-ext-command extcmd) |
| 230 | (error (if (characterp switch) "%s: unrecognized option -%c" | 263 | (error (if (characterp (car switch)) "%s: unrecognized option -%c" |
| 231 | "%s: unrecognized option --%s") | 264 | "%s: unrecognized option --%s") |
| 232 | name switch))))))) | 265 | name (car switch)))))))) |
| 233 | 266 | ||
| 234 | (defun eshell--process-args (name args options) | 267 | (defun eshell--process-args (name args options) |
| 235 | "Process the given ARGS using OPTIONS." | 268 | "Process the given ARGS using OPTIONS." |
| @@ -262,12 +295,9 @@ switch is unrecognized." | |||
| 262 | (if (> (length switch) 0) | 295 | (if (> (length switch) 0) |
| 263 | (eshell--process-option name switch 1 ai options opt-vals) | 296 | (eshell--process-option name switch 1 ai options opt-vals) |
| 264 | (setq ai (length eshell--args))) | 297 | (setq ai (length eshell--args))) |
| 265 | (let ((len (length switch)) | 298 | (while (> (length switch) 0) |
| 266 | (index 0)) | 299 | (setq switch (eshell--process-option name switch 0 |
| 267 | (while (< index len) | 300 | ai options opt-vals))))))) |
| 268 | (eshell--process-option name (aref switch index) | ||
| 269 | 0 ai options opt-vals) | ||
| 270 | (setq index (1+ index)))))))) | ||
| 271 | (nconc (mapcar #'cdr opt-vals) eshell--args))) | 301 | (nconc (mapcar #'cdr opt-vals) eshell--args))) |
| 272 | 302 | ||
| 273 | (provide 'esh-opt) | 303 | (provide 'esh-opt) |
diff --git a/test/lisp/eshell/esh-opt-tests.el b/test/lisp/eshell/esh-opt-tests.el index 532adfb733a..255768635b1 100644 --- a/test/lisp/eshell/esh-opt-tests.el +++ b/test/lisp/eshell/esh-opt-tests.el | |||
| @@ -57,7 +57,7 @@ | |||
| 57 | '((?u "user" t user "execute a command as another USER") | 57 | '((?u "user" t user "execute a command as another USER") |
| 58 | :parse-leading-options-only)))) | 58 | :parse-leading-options-only)))) |
| 59 | (should | 59 | (should |
| 60 | (equal '("world" "emerge") | 60 | (equal '("DN" "emerge" "world") |
| 61 | (eshell--process-args | 61 | (eshell--process-args |
| 62 | "sudo" | 62 | "sudo" |
| 63 | '("-u" "root" "emerge" "-uDN" "world") | 63 | '("-u" "root" "emerge" "-uDN" "world") |
| @@ -65,59 +65,132 @@ | |||
| 65 | 65 | ||
| 66 | (ert-deftest test-eshell-eval-using-options () | 66 | (ert-deftest test-eshell-eval-using-options () |
| 67 | "Tests for `eshell-eval-using-options'." | 67 | "Tests for `eshell-eval-using-options'." |
| 68 | ;; Test short options. | ||
| 68 | (eshell-eval-using-options | 69 | (eshell-eval-using-options |
| 69 | "sudo" '("-u" "root" "whoami") | 70 | "ls" '("-a" "/some/path") |
| 70 | '((?u "user" t user "execute a command as another USER") | 71 | '((?a "all" nil show-all |
| 71 | :parse-leading-options-only) | 72 | "do not ignore entries starting with .")) |
| 72 | (should (equal user "root"))) | 73 | (should (eq show-all t)) |
| 74 | (should (equal args '("/some/path")))) | ||
| 73 | (eshell-eval-using-options | 75 | (eshell-eval-using-options |
| 74 | "sudo" '("--user" "root" "whoami") | 76 | "ls" '("/some/path") |
| 75 | '((?u "user" t user "execute a command as another USER") | 77 | '((?a "all" nil show-all |
| 76 | :parse-leading-options-only) | 78 | "do not ignore entries starting with .")) |
| 77 | (should (equal user "root"))) | 79 | (should (eq show-all nil)) |
| 80 | (should (equal args '("/some/path")))) | ||
| 78 | 81 | ||
| 82 | ;; Test long options. | ||
| 79 | (eshell-eval-using-options | 83 | (eshell-eval-using-options |
| 80 | "sudo" '("emerge" "-uDN" "world") | 84 | "ls" '("--all" "/some/path") |
| 81 | '((?u "user" t user "execute a command as another USER")) | 85 | '((?a "all" nil show-all |
| 82 | (should (equal user "world"))) | 86 | "do not ignore entries starting with .")) |
| 87 | (should (eq show-all t)) | ||
| 88 | (should (equal args '("/some/path")))) | ||
| 89 | |||
| 90 | ;; Test options with constant values. | ||
| 83 | (eshell-eval-using-options | 91 | (eshell-eval-using-options |
| 84 | "sudo" '("emerge" "-uDN" "world") | 92 | "ls" '("/some/path" "-h") |
| 85 | '((?u "user" t user "execute a command as another USER") | 93 | '((?h "human-readable" 1024 human-readable |
| 86 | :parse-leading-options-only) | 94 | "print sizes in human readable format")) |
| 87 | (should (eq user nil))) | 95 | (should (eql human-readable 1024)) |
| 96 | (should (equal args '("/some/path")))) | ||
| 97 | (eshell-eval-using-options | ||
| 98 | "ls" '("/some/path" "--human-readable") | ||
| 99 | '((?h "human-readable" 1024 human-readable | ||
| 100 | "print sizes in human readable format")) | ||
| 101 | (should (eql human-readable 1024)) | ||
| 102 | (should (equal args '("/some/path")))) | ||
| 103 | (eshell-eval-using-options | ||
| 104 | "ls" '("/some/path") | ||
| 105 | '((?h "human-readable" 1024 human-readable | ||
| 106 | "print sizes in human readable format")) | ||
| 107 | (should (eq human-readable nil)) | ||
| 108 | (should (equal args '("/some/path")))) | ||
| 88 | 109 | ||
| 110 | ;; Test options with user-specified values. | ||
| 111 | (eshell-eval-using-options | ||
| 112 | "ls" '("-I" "*.txt" "/some/path") | ||
| 113 | '((?I "ignore" t ignore-pattern | ||
| 114 | "do not list implied entries matching pattern")) | ||
| 115 | (should (equal ignore-pattern "*.txt")) | ||
| 116 | (should (equal args '("/some/path")))) | ||
| 117 | (eshell-eval-using-options | ||
| 118 | "ls" '("-I*.txt" "/some/path") | ||
| 119 | '((?I "ignore" t ignore-pattern | ||
| 120 | "do not list implied entries matching pattern")) | ||
| 121 | (should (equal ignore-pattern "*.txt")) | ||
| 122 | (should (equal args '("/some/path")))) | ||
| 89 | (eshell-eval-using-options | 123 | (eshell-eval-using-options |
| 90 | "ls" '("-I" "*.txt" "/dev/null") | 124 | "ls" '("--ignore" "*.txt" "/some/path") |
| 91 | '((?I "ignore" t ignore-pattern | 125 | '((?I "ignore" t ignore-pattern |
| 92 | "do not list implied entries matching pattern")) | 126 | "do not list implied entries matching pattern")) |
| 93 | (should (equal ignore-pattern "*.txt"))) | 127 | (should (equal ignore-pattern "*.txt")) |
| 128 | (should (equal args '("/some/path")))) | ||
| 129 | (eshell-eval-using-options | ||
| 130 | "ls" '("--ignore=*.txt" "/some/path") | ||
| 131 | '((?I "ignore" t ignore-pattern | ||
| 132 | "do not list implied entries matching pattern")) | ||
| 133 | (should (equal ignore-pattern "*.txt")) | ||
| 134 | (should (equal args '("/some/path")))) | ||
| 94 | 135 | ||
| 136 | ;; Test multiple short options in a single token. | ||
| 95 | (eshell-eval-using-options | 137 | (eshell-eval-using-options |
| 96 | "ls" '("-l" "/dev/null") | 138 | "ls" '("-al" "/some/path") |
| 97 | '((?l nil long-listing listing-style | 139 | '((?a "all" nil show-all |
| 98 | "use a long listing format")) | 140 | "do not ignore entries starting with .") |
| 99 | (should (eql listing-style 'long-listing))) | 141 | (?l nil long-listing listing-style |
| 142 | "use a long listing format")) | ||
| 143 | (should (eq t show-all)) | ||
| 144 | (should (eql listing-style 'long-listing)) | ||
| 145 | (should (equal args '("/some/path")))) | ||
| 100 | (eshell-eval-using-options | 146 | (eshell-eval-using-options |
| 101 | "ls" '("/dev/null") | 147 | "ls" '("-aI*.txt" "/some/path") |
| 102 | '((?l nil long-listing listing-style | 148 | '((?a "all" nil show-all |
| 103 | "use a long listing format")) | 149 | "do not ignore entries starting with .") |
| 104 | (should (eq listing-style nil))) | 150 | (?I "ignore" t ignore-pattern |
| 151 | "do not list implied entries matching pattern")) | ||
| 152 | (should (eq t show-all)) | ||
| 153 | (should (equal ignore-pattern "*.txt")) | ||
| 154 | (should (equal args '("/some/path")))) | ||
| 105 | 155 | ||
| 156 | ;; Test that "--" terminates options. | ||
| 106 | (eshell-eval-using-options | 157 | (eshell-eval-using-options |
| 107 | "ls" '("/dev/null" "-h") | 158 | "ls" '("--" "-a") |
| 108 | '((?h "human-readable" 1024 human-readable | 159 | '((?a "all" nil show-all |
| 109 | "print sizes in human readable format")) | 160 | "do not ignore entries starting with .")) |
| 110 | (should (eql human-readable 1024))) | 161 | (should (eq show-all nil)) |
| 162 | (should (equal args '("-a")))) | ||
| 111 | (eshell-eval-using-options | 163 | (eshell-eval-using-options |
| 112 | "ls" '("/dev/null" "--human-readable") | 164 | "ls" '("--" "--all") |
| 113 | '((?h "human-readable" 1024 human-readable | 165 | '((?a "all" nil show-all |
| 114 | "print sizes in human readable format")) | 166 | "do not ignore entries starting with .")) |
| 115 | (should (eql human-readable 1024))) | 167 | (should (eq show-all nil)) |
| 168 | (should (equal args '("--all")))) | ||
| 169 | |||
| 170 | ;; Test :parse-leading-options-only. | ||
| 116 | (eshell-eval-using-options | 171 | (eshell-eval-using-options |
| 117 | "ls" '("/dev/null") | 172 | "sudo" '("-u" "root" "whoami") |
| 118 | '((?h "human-readable" 1024 human-readable | 173 | '((?u "user" t user "execute a command as another USER") |
| 119 | "print sizes in human readable format")) | 174 | :parse-leading-options-only) |
| 120 | (should (eq human-readable nil)))) | 175 | (should (equal user "root")) |
| 176 | (should (equal args '("whoami")))) | ||
| 177 | (eshell-eval-using-options | ||
| 178 | "sudo" '("--user" "root" "whoami") | ||
| 179 | '((?u "user" t user "execute a command as another USER") | ||
| 180 | :parse-leading-options-only) | ||
| 181 | (should (equal user "root")) | ||
| 182 | (should (equal args '("whoami")))) | ||
| 183 | (eshell-eval-using-options | ||
| 184 | "sudo" '("emerge" "-uDN" "world") | ||
| 185 | '((?u "user" t user "execute a command as another USER")) | ||
| 186 | (should (equal user "DN")) | ||
| 187 | (should (equal args '("emerge" "world")))) | ||
| 188 | (eshell-eval-using-options | ||
| 189 | "sudo" '("emerge" "-uDN" "world") | ||
| 190 | '((?u "user" t user "execute a command as another USER") | ||
| 191 | :parse-leading-options-only) | ||
| 192 | (should (eq user nil)) | ||
| 193 | (should (equal args '("emerge" "-uDN" "world"))))) | ||
| 121 | 194 | ||
| 122 | (provide 'esh-opt-tests) | 195 | (provide 'esh-opt-tests) |
| 123 | 196 | ||