Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 315 lines (240 sloc) 11.237 kb
9a27eeb @stuarthalloway initial commit
stuarthalloway authored
1 # tools.cli
2
84aabfc @guns Add ns docstrings
guns authored
3 Tools for working with command line arguments.
3399597 @gar3thjon3s moved over clargon and README
gar3thjon3s authored
4
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
5 ## Stable Releases and Dependency Information
c73193b @guns Document new features in 0.3.0-beta1
guns authored
6
9e740a6 @guns Update README with 0.3.1 release
guns authored
7 The 0.3.x series of tools.cli features a new flexible API, better adherence
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
8 to GNU option parsing conventions, and ClojureScript support.
c73193b @guns Document new features in 0.3.0-beta1
guns authored
9
10 [Leiningen](https://github.com/technomancy/leiningen) dependency information:
11
9e740a6 @guns Update README with 0.3.1 release
guns authored
12 [org.clojure/tools.cli "0.3.1"]
c73193b @guns Document new features in 0.3.0-beta1
guns authored
13
14 [Maven](http://maven.apache.org/) dependency information:
15
16 <dependency>
17 <groupId>org.clojure</groupId>
18 <artifactId>tools.cli</artifactId>
9e740a6 @guns Update README with 0.3.1 release
guns authored
19 <version>0.3.1</version>
c73193b @guns Document new features in 0.3.0-beta1
guns authored
20 </dependency>
21
22 The function `clojure.tools.cli/cli` has been superseded by
23 `clojure.tools.cli/parse-opts`, and should not be used in new programs.
24
25 The previous function will remain for the forseeable future. It has also been
26 adapted to use the new tokenizer, so upgrading is still worthwhile even if you
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
27 are not ready to migrate to `parse-opts`.
28
29 ## Quick Start
30
31 ```clojure
32 (ns my.program
33 (:require [clojure.tools.cli :refer [parse-opts]])
34 (:gen-class))
35
36 (def cli-options
37 ;; An option with a required argument
38 [["-p" "--port PORT" "Port number"
39 :default 80
40 :parse-fn #(Integer/parseInt %)
41 :validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]]
42 ;; A non-idempotent option
43 ["-v" nil "Verbosity level"
44 :id :verbosity
45 :default 0
46 :assoc-fn (fn [m k _] (update-in m [k] inc))]
47 ;; A boolean option defaulting to nil
48 ["-h" "--help"]])
49
50 (defn -main [& args]
51 (parse-opts args cli-options))
52 ```
53
54 Execute the command line:
55
56 my-program -vvvp8080 foo --help --invalid-opt
57
58 to produce the map:
59
60 ```clojure
0f98dd3 @guns Update README with note about error handling
guns authored
61 {:options {:port 8080
62 :verbosity 3
63 :help true}
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
64
65 :arguments ["foo"]
66
67 :summary " -p, --port PORT 80 Port number
68 -v Verbosity level
69 -h, --help"
70
71 :errors ["Unknown option: \"--invalid-opt\""]}
72 ```
c73193b @guns Document new features in 0.3.0-beta1
guns authored
73
0f98dd3 @guns Update README with note about error handling
guns authored
74 **Note** that exceptions are _not_ thrown on parse errors, so errors must be
75 handled explicitly after checking the `:errors` entry for a truthy value.
76
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
77 Please see the [example program](#example-usage) for a more detailed example
78 and refer to the docstring of `parse-opts` for comprehensive documentation:
79
80 http://clojure.github.io/tools.cli/index.html#clojure.tools.cli/parse-opts
81
9e740a6 @guns Update README with 0.3.1 release
guns authored
82 ## New Features in 0.3.x
c73193b @guns Document new features in 0.3.0-beta1
guns authored
83
84 ### Better Option Tokenization
85
86 In accordance with the [GNU Program Argument Syntax Conventions][GNU], two
87 features have been added to the options tokenizer:
88
89 * Short options may be grouped together.
90
91 For instance, `-abc` is equivalent to `-a -b -c`. If the `-b` option
92 requires an argument, the same `-abc` is interpreted as `-a -b "c"`.
93
94 * Long option arguments may be specified with an equals sign.
95
96 `--long-opt=ARG` is equivalent to `--long-opt "ARG"`.
97
98 If the argument is omitted, it is interpreted as the empty string.
99 e.g. `--long-opt=` is equivalent to `--long-opt ""`
100
101 [GNU]: https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
102
103 ### In-order Processing for Subcommands
104
105 Large programs are often divided into subcommands with their own sets of
106 options. To aid in designing such programs, `clojure.tools.cli/parse-opts`
107 accepts an `:in-order` option that directs it to stop processing arguments at
108 the first unrecognized token.
109
110 For instance, the `git` program has a set of top-level options that are
111 unrecognized by subcommands and vice-versa:
112
113 git --git-dir=/other/proj/.git log --oneline --graph
114
115 By default, `clojure.tools.cli/parse-opts` interprets this command line as:
116
117 options: [[--git-dir /other/proj/.git]
118 [--oneline]
119 [--graph]]
120 arguments: [log]
121
122 When :in-order is true however, the arguments are interpreted as:
123
124 options: [[--git-dir /other/proj/.git]]
125 arguments: [log --oneline --graph]
126
127 Note that the options to `log` are not parsed, but remain in the unprocessed
128 arguments vector. These options could be handled by another call to
129 `parse-opts` from within the function that handles the `log` subcommand.
130
131 ### Options Summary
132
133 `parse-opts` returns a minimal options summary string:
134
135 -p, --port NUMBER 8080 Required option with default
136 --host HOST localhost Short and long options may be omitted
137 -d, --detach Boolean option
138 -h, --help
139
140 This may be inserted into a larger usage summary, but it is up to the caller.
141
142 If the default formatting of the summary is unsatisfactory, a `:summary-fn`
143 may be supplied to `parse-opts`. This function will be passed the sequence
144 of compiled option specification maps and is expected to return an options
145 summary.
146
147 The default summary function `clojure.tools.cli/summarize` is public and may
148 be useful within your own `:summary-fn` for generating the default summary.
149
150 ### Option Argument Validation
151
152 There is a new option entry `:validate`, which takes a tuple of
153 `[validation-fn validation-msg]`. The validation-fn receives an option's
154 argument *after* being parsed by `:parse-fn` if it exists.
155
156 ["-p" "--port PORT" "A port number"
157 :parse-fn #(Integer/parseInt %)
158 :validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]]
159
160 If the validation-fn returns a falsy value, the validation-msg is added to the
161 errors vector.
162
163 ### Error Handling and Return Values
164
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
165 Instead of throwing errors, `parse-opts` collects error messages into a vector
166 and returns them to the caller. Unknown options, missing required arguments,
167 validation errors, and exceptions thrown during `:parse-fn` are all added to
168 the errors vector.
c73193b @guns Document new features in 0.3.0-beta1
guns authored
169
170 Correspondingly, `parse-opts` returns the following map of values:
171
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
172 {:options A map of default options merged with parsed values from the command line
c73193b @guns Document new features in 0.3.0-beta1
guns authored
173 :arguments A vector of unprocessed arguments
174 :summary An options summary string
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
175 :errors A vector of error messages, or nil if no errors}
c73193b @guns Document new features in 0.3.0-beta1
guns authored
176
177 During development, parse-opts asserts the uniqueness of option `:id`,
178 `:short-opt`, and `:long-opt` values and throws an error on failure.
179
180 ### ClojureScript Support
181
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
182 The `cljs.tools.cli` namespace is available for use in ClojureScript programs!
183 Both `parse-opts` and `summarize` have been ported, and have complete feature
184 parity with their Clojure counterparts.
c73193b @guns Document new features in 0.3.0-beta1
guns authored
185
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
186 ClojureScript Versions `0.0-2080` and above are supported, but earlier
187 versions are likely to work as well.
c73193b @guns Document new features in 0.3.0-beta1
guns authored
188
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
189 ## Example Usage
c73193b @guns Document new features in 0.3.0-beta1
guns authored
190
191 ```clojure
192 (ns cli-example.core
193 (:require [cli-example.server :as server]
194 [clojure.string :as string]
195 [clojure.tools.cli :refer [parse-opts]])
196 (:import (java.net InetAddress))
197 (:gen-class))
198
199 (def cli-options
200 [;; First three strings describe a short-option, long-option with optional
201 ;; example argument description, and a description. All three are optional
202 ;; and positional.
203 ["-p" "--port PORT" "Port number"
204 :default 80
205 :parse-fn #(Integer/parseInt %)
206 :validate [#(< 0 % 0x10000) "Must be a number between 0 and 65536"]]
207 ["-H" "--hostname HOST" "Remote host"
208 :default (InetAddress/getByName "localhost")
209 ;; Specify a string to output in the default column in the options summary
210 ;; if the default value's string representation is very ugly
211 :default-desc "localhost"
212 :parse-fn #(InetAddress/getByName %)]
213 ;; If no required argument description is given, the option is assumed to
214 ;; be a boolean option defaulting to nil
215 [nil "--detach" "Detach from controlling process"]
216 ["-v" nil "Verbosity level; may be specified multiple times to increase value"
217 ;; If no long-option is specified, an option :id must be given
218 :id :verbosity
219 :default 0
220 ;; Use assoc-fn to create non-idempotent options
221 :assoc-fn (fn [m k _] (update-in m [k] inc))]
222 ["-h" "--help"]])
223
224 (defn usage [options-summary]
225 (->> ["This is my program. There are many like it, but this one is mine."
226 ""
227 "Usage: program-name [options] action"
228 ""
229 "Options:"
230 options-summary
231 ""
232 "Actions:"
233 " start Start a new server"
234 " stop Stop an existing server"
235 " status Print a server's status"
236 ""
237 "Please refer to the manual page for more information."]
238 (string/join \newline)))
239
240 (defn error-msg [errors]
241 (str "The following errors occurred while parsing your command:\n\n"
242 (string/join \newline errors)))
243
244 (defn exit [status msg]
245 (println msg)
246 (System/exit status))
247
248 (defn -main [& args]
249 (let [{:keys [options arguments errors summary]} (parse-opts args cli-options)]
250 ;; Handle help and error conditions
251 (cond
252 (:help options) (exit 0 (usage summary))
253 (not= (count arguments) 1) (exit 1 (usage summary))
254 errors (exit 1 (error-msg errors)))
255 ;; Execute program with options
256 (case (first arguments)
257 "start" (server/start! options)
258 "stop" (server/stop! options)
259 "status" (server/status! options)
260 (exit 1 (usage summary)))))
261 ```
262
74ff546 @gar3thjon3s Update README.md to match other contrib projects
gar3thjon3s authored
263 ## Developer Information
264
265 * [GitHub project](https://github.com/clojure/tools.cli)
266 * [Bug Tracker](http://dev.clojure.org/jira/browse/TCLI)
267 * [Continuous Integration](http://build.clojure.org/job/tools.cli/)
268 * [Compatibility Test Matrix](http://build.clojure.org/job/tools.cli-test-matrix/)
269
270 ## Change Log
271
ae3f8b2 @guns Prepare for 0.3.1 release
guns authored
272 * Release 0.3.1 on 2014-01-02
273 * Apply patch for [TCLI-8](http://dev.clojure.org/jira/browse/TCLI-8):
274 Correct test that trivially always passes
275 * Apply patch for [TCLI-7](http://dev.clojure.org/jira/browse/TCLI-7):
276 summarize throws when called with an empty sequence of options
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
277 * Release 0.3.0 on 2013-12-15
278 * Add public functions `parse-opts` and `summarize` to supersede `cli`,
279 addressing [TCLI-3](http://dev.clojure.org/jira/browse/TCLI-3),
280 [TCLI-4](http://dev.clojure.org/jira/browse/TCLI-4), and
281 [TCLI-6](http://dev.clojure.org/jira/browse/TCLI-6)
282 * Add ClojureScript port of `parse-opts` and `summarize`, available in
283 `cljs.tools.cli`.
284 * Move extra documentation of `cli` function to
285 https://github.com/clojure/tools.cli/wiki/Documentation-for-0.2.4
dbcf61a @guns Clarify docstring for :errors entry
guns authored
286 * Release 0.2.4 on 2013-08-06
409beee @gar3thjon3s Update README.md
gar3thjon3s authored
287 * Applying patch for [TCLI-2](http://dev.clojure.org/jira/browse/TCLI-2)
288 (support an assoc-fn option)
3dced05 @gar3thjon3s Update README for 0.2.3
gar3thjon3s authored
289 * Release 0.2.3 on 2013-08-06
290 * Add optional description string to prefix the returned banner
970fafd @gar3thjon3s Update README with latest release information
gar3thjon3s authored
291 * Release 0.2.2 on 2012-08-09
dbcf61a @guns Clarify docstring for :errors entry
guns authored
292 * Applying patch for [TCLI-1](http://dev.clojure.org/jira/browse/TCLI-1)
970fafd @gar3thjon3s Update README with latest release information
gar3thjon3s authored
293 (do not include keys when no value provided by :default)
74ff546 @gar3thjon3s Update README.md to match other contrib projects
gar3thjon3s authored
294 * Release 0.2.1 on 2011-11-03
295 * Removing the :required option. Hangover from when -h and --help were
296 implemented by default, causes problems if you want help and dont
297 provide a :required argument.
298 * Release 0.2.0 on 2011-10-31
299 * Remove calls to System/exit
300 * Remove built-in help options
301 * Release 0.1.0
302 * Initial import of Clargon codebase
303
9a27eeb @stuarthalloway initial commit
stuarthalloway authored
304 ## License
305
306 Copyright (c) Rich Hickey and contributors. All rights reserved.
307
308 The use and distribution terms for this software are covered by the
309 Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
310 which can be found in the file epl.html at the root of this distribution.
311 By using this software in any fashion, you are agreeing to be bound by
312 the terms of this license.
86e9f9d @guns Prepare README and metadata for 0.3.0 release
guns authored
313
9a27eeb @stuarthalloway initial commit
stuarthalloway authored
314 You must not remove this notice, or any other, from this software.
Something went wrong with that request. Please try again.