Move plugin's subtask help mechanism to the help ns.

This commit is contained in:
Colin Jones 2010-10-26 22:36:57 -05:00
parent bd3675b3aa
commit 053761774b
4 changed files with 78 additions and 45 deletions

View file

@ -1,6 +1,7 @@
(ns leiningen.help
"Display a list of tasks or help for a given task."
(:use [leiningen.util.ns :only [namespaces-matching]]))
(:use [leiningen.util.ns :only [namespaces-matching]])
(:require [clojure.string :as string]))
(def tasks (->> (namespaces-matching "leiningen")
(filter #(re-find #"^leiningen\.(?!core|util)[^\.]+$" (name %)))
@ -11,17 +12,59 @@
(for [args (or (:help-arglists (meta task)) (:arglists (meta task)))]
(vec (remove #(= 'project %) args))))
(def help-padding 3)
(defn- formatted-docstring [command docstring padding]
(apply str
(replace
{\newline
(apply str
(cons \newline (repeat (+ padding (count command)) \space)))}
docstring)))
(defn- formatted-help [command docstring longest-key-length]
(let [padding (+ longest-key-length help-padding (- (count command)))]
(format (str "%1s" (apply str (repeat padding " ")) "%2s")
command
(formatted-docstring command docstring padding))))
(defn- get-subtasks-and-docstrings-for [task]
(let [task-ns (symbol (str "leiningen." task))
task (ns-resolve task-ns (symbol task))]
(into {}
(map
(fn [subtask]
(let [m (meta subtask)]
[(str (:name m)) (:doc m)]))
(:subtasks (meta task))))))
(defn subtask-help-for
[task-name]
(let [subtasks (get-subtasks-and-docstrings-for task-name)]
(if (empty? subtasks)
nil
(let [longest-key-length (apply max (map count (keys subtasks)))
task-ns (doto (symbol (str "leiningen." task-name)) require)
task (ns-resolve task-ns (symbol task-name))
help-fn (ns-resolve task-ns 'help)]
(string/join
"\n"
(concat ["\n\nSubtasks available:"]
(for [[subtask doc] subtasks]
(formatted-help subtask doc longest-key-length))))))))
(defn help-for
"Help for a task is stored in its docstring, or if that's not present
in its namespace."
[task]
(let [task-ns (doto (symbol (str "leiningen." task)) require)
task (ns-resolve task-ns (symbol task))
[task-name]
(let [task-ns (doto (symbol (str "leiningen." task-name)) require)
task (ns-resolve task-ns (symbol task-name))
help-fn (ns-resolve task-ns 'help)]
(str "Arguments: " (pr-str (get-arglists task)) "\n"
(or (and help-fn (help-fn))
(:doc (meta task))
(:doc (meta (find-ns task-ns)))))))
(:doc (meta (find-ns task-ns))))
(subtask-help-for task-name))))
;; affected by clojure ticket #130: bug of AOT'd namespaces losing metadata
(defn help-summary-for [task-ns]

View file

@ -8,7 +8,7 @@
get-default-uberjar-name)]
[clojure.java.io :only (file)])
(:require [leiningen.install]
[clojure.string :as string])
[leiningen.help])
(:import [java.util.zip ZipOutputStream]
[java.io File FileOutputStream]))
@ -20,6 +20,7 @@
(defn extract-name-and-group [project-name]
((juxt name namespace) (symbol project-name)))
;; TODO: extract shared behavior between this and the install task
(defn install
"Download, package, and install plugin jarfile into
~/.lein/plugins
@ -53,47 +54,15 @@ Syntax: lein plugin uninstall GROUP/ARTIFACT-ID VERSION"
(.delete (file plugins-path
(plugin-standalone-filename group name version)))))
;; TODO: move subtask documentation support to help namespace.
(defn- formatted-docstring [command docstring padding]
(apply str
(replace
{\newline
(apply str (cons
\newline
(repeat (+ padding (count command)) " ")))}
docstring)))
(def help-padding 3)
(defn- formatted-help [command docstring longest-key-length]
(let [padding (+ longest-key-length help-padding (- (count command)))]
(format (str "%1s" (apply str (repeat padding " ")) "%2s")
command
(formatted-docstring command docstring padding))))
(declare help)
(defn- get-help-map []
(into {}
(map
(fn [subtask]
[(str (:name (meta subtask))) (:doc (meta subtask))])
[#'help #'install #'uninstall])))
(defn help []
(let [help-map (get-help-map)
longest-key-length (apply max (map count (keys help-map)))]
(string/join "\n" (concat
["Manage user-level plugins.\n"
"Subtasks available:\n"]
(for [[subtask doc] help-map]
(formatted-help subtask doc longest-key-length))))))
(defn ^{:help-arglists '([subtask project-name version])} plugin
([] (println (help)))
(defn ^{:doc "Manage user-level plugins."
:help-arglists '([subtask project-name version])
:subtasks [#'install #'uninstall]}
plugin
([] (println (leiningen.help/help-for "plugin")))
([_] (plugin))
([_ _] (plugin))
([subtask project-name version]
(case subtask
"install" (install project-name version)
"uninstall" (uninstall project-name version)
(help))))
(plugin))))

6
test/test_help.clj Normal file
View file

@ -0,0 +1,6 @@
(ns test-help
(:use [leiningen.help]
[clojure.test]))
(deftest basic-test
(is (= "" "")))

View file

@ -14,6 +14,21 @@
(is (= (extract-name-and-group "tehname")
["tehname" nil])))
(deftest test-help
(is (= "Arguments: ([subtask project-name version])
Manage user-level plugins.
Subtasks available:
install Download, package, and install plugin jarfile into
~/.lein/plugins
Syntax: lein plugin install GROUP/ARTIFACT-ID VERSION
You can use the same syntax here as when listing Leiningen
dependencies.
uninstall Delete the plugin jarfile
Syntax: lein plugin uninstall GROUP/ARTIFACT-ID VERSION\n"
(with-out-str (plugin "help")))))
;; TODO: figure out a clever way to actually test instaling
;; (deftest test-install
;; (install "lein-plugin" "0.1.0")