Repository navigation
Expand file tree
/
Copy pathhelp.clj
More file actions
108 lines (95 loc) · 4.22 KB
/
Copy pathhelp.clj
File metadata and controls
108 lines (95 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
(ns leiningen.help
"Display a list of tasks or help for a given task."
(:require [clojure.string :as string]
[clojure.java.io :as io]
[leiningen.core.main :as main]))
(def ^{:private true
:doc "Width of task name column in list of tasks produced by help task."}
task-name-column-width 20)
(defn- get-arglists [task]
(for [args (or (:help-arglists (meta task)) (:arglists (meta task)))]
(vec (remove #(= 'project %) args))))
(def ^:private 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 \space)) "%2s")
command
(formatted-docstring command docstring padding))))
(defn- get-subtasks-and-docstrings-for [task]
(into {}
(map (fn [subtask]
(let [m (meta subtask)]
[(str (:name m)) (first (.split (:doc m "") "\n"))]))
(:subtasks (meta task)))))
(defn subtask-help-for
[task-ns task]
(if-let [subtasks (seq (get-subtasks-and-docstrings-for task))]
(let [longest-key-length (apply max (map count (keys subtasks)))]
(string/join "\n" (concat ["\n\nSubtasks available:"]
(for [[subtask doc] subtasks]
(formatted-help subtask doc
longest-key-length)))))))
(defn- resolve-task [task-name]
(try (let [task-ns (doto (symbol (str "leiningen." task-name)) require)
task (ns-resolve task-ns (symbol task-name))]
[task-ns task])
(catch java.io.FileNotFoundException e
[nil nil])))
(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."
([task-name]
(let [[task-ns task] (resolve-task task-name)]
(if task
(let [help-fn (ns-resolve task-ns 'help)]
(str (or (and (not= task-ns 'leiningen.help) help-fn (help-fn))
(:doc (meta task))
(:doc (meta (find-ns task-ns))))
(subtask-help-for task-ns task)
(if (some seq (get-arglists task))
(str "\n\nArguments: " (pr-str (get-arglists task))))))
(format "Task: '%s' not found" task-name))))
([project task-name]
(let [aliases (merge main/aliases (:aliases project))]
(help-for (aliases task-name task-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))))
first-line (first (.split (help-for {} task-name) "\n"))]
;; Use first line of task docstring if ns metadata isn't present
(str task-name (apply str (repeat (- task-name-column-width
(count task-name)) " "))
(or ns-summary first-line)))
(catch Throwable e
(binding [*out* *err*]
(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.
Also provides readme, faq, tutorial, news, sample, profiles,
deploying and copying info."
;; TODO: explain partial aliases in specific help
([project task] (println (or (static-help task) (help-for project task))))
([project]
(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.")
;; TODO: show user-level aliases too
(if-let [aliases (:aliases project)]
(do
(println "\nAliases:")
(doseq [[k v] aliases]
(println (str k " " v)))))
(println "\nSee also: readme, faq, tutorial, news, sample, profiles,"
"deploying and copying.")))