Browse files

Merge pull request #803 from tobias/help-for-subtasks

Support subtask specific help via 'lein help task subtask'
  • Loading branch information...
2 parents 102dcad + 6998dd6 commit 7adb435ca76963ae0b2892a2830574eb35096706 @technomancy committed Oct 5, 2012
Showing with 41 additions and 5 deletions.
  1. +3 −0 doc/
  2. +33 −5 src/leiningen/help.clj
  3. +5 −0 test/leiningen/test/help.clj
@@ -79,6 +79,9 @@ that all your arguments will be strings, so it's up to you to call
Often more complicated tasks get divided up into subtasks. Placing
`:subtasks` metadata on a task defn which contains a vector of subtask
vars will allow `lein help $TASK_CONTAINING_SUBTASKS` to list them.
+This list of subtasks will show the first line of the docstring for each
+subtask. The full help for a subtask can be viewed via
## Code Evaluation
@@ -42,7 +42,9 @@
(string/join "\n" (concat ["\n\nSubtasks available:"]
(for [[subtask doc] subtasks]
(formatted-help subtask doc
- longest-key-length)))))))
+ longest-key-length))
+ [(str "\nRun `lein help " (:name (meta task))
+ " $SUBTASK` for subtask details.")])))))
(defn- resolve-task [task-name]
(try (let [task-ns (doto (symbol (str "leiningen." task-name)) require)
@@ -51,13 +53,19 @@
(catch e
[nil nil])))
+(defn- resolve-subtask [task-name subtask-name]
+ (let [[_ task] (resolve-task task-name)]
+ (some #(if (= (symbol subtask-name) (:name (meta %))) %)
+ (:subtasks (meta task)))))
(defn- static-help [name]
(if-let [resource (io/resource (format "leiningen/help/%s" name))]
(slurp resource)))
(defn help-for
- "Help for a task is stored in its docstring, or if that's not present
- in its namespace."
+ "Returns a string containing help for a task.
+Looks for a function named 'help' in the subtask's namespace,
+then a docstring on the task, then a docstring on the task ns."
(let [[task-ns task] (resolve-task task-name)]
(if task
@@ -73,6 +81,24 @@
(let [aliases (merge main/aliases (:aliases project))]
(help-for (aliases task-name task-name)))))
+(defn help-for-subtask
+ "Returns a string containing help for a subtask.
+Looks for a function named 'help-<subtask>' in the subtask's namespace,
+using the subtask's docstring if the help function is not found."
+ ([task-name subtask-name]
+ (if-let [subtask (resolve-subtask task-name subtask-name)]
+ (let [subtask-meta (meta subtask)
+ help-fn (ns-resolve (:ns subtask-meta)
+ (symbol (str "help-" subtask-name)))
+ arglists (get-arglists subtask)]
+ (str (or (and help-fn (help-fn)) (:doc subtask-meta))
+ (if (some seq arglists)
+ (str "\n\nArguments: " (pr-str arglists)))))
+ (format "Subtask: '%s %s' not found" task-name subtask-name)))
+ ([project task-name subtask-name]
+ (let [aliases (merge main/aliases (:aliases project))]
+ (help-for-subtask (aliases task-name task-name) subtask-name))))
(defn help-summary-for [task-ns]
(try (let [task-name (last (.split (name task-ns) "\\."))
ns-summary (:doc (meta (find-ns (doto task-ns require))))
@@ -86,18 +112,20 @@
(str task-ns " Problem loading: " (.getMessage e))))))
(defn ^:no-project-needed ^:higher-order help
- "Display a list of tasks or help for a given task.
+ "Display a list of tasks or help for a given task or subtask.
Also provides readme, faq, tutorial, news, sample, profiles,
deploying and copying info."
;; TODO: explain partial aliases in specific help
+ ([project task subtask] (println (or (static-help (str task "-" subtask))
+ (help-for-subtask project task subtask))))
([project task] (println (or (static-help task) (help-for project task))))
(println "Leiningen is a tool for working with Clojure projects.\n")
(println "Several tasks are available:")
(doseq [task-ns (main/tasks)]
(println (help-summary-for task-ns)))
- (println "\nRun lein help $TASK for details.")
+ (println "\nRun `lein help $TASK` for details.")
;; TODO: show user-level aliases too
(if-let [aliases (:aliases project)]
@@ -20,6 +20,11 @@
(is (re-find #"template\s+A meta-template for 'lein new' templates."
+(deftest subtask-help-for-new-default
+ (let [subtask-help (help-for-subtask "new" "default")]
+ (is (re-find #"^A general project template." subtask-help))
+ (is (re-find #"Arguments: \(\[name\]\)" subtask-help))))
(deftest test-docstring-formatting
(is (= "This is an
AWESOME command

0 comments on commit 7adb435

Please sign in to comment.