Skip to content

Commit 2b0254c

Browse files
authored
Merge pull request #15 from arichiardi/handle-exec-fn
Introduce --execute option and functionality
2 parents 5737a8c + 92b2a17 commit 2b0254c

File tree

3 files changed

+71
-14
lines changed

3 files changed

+71
-14
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121

2222
- Add `--no-prefix` or `{:launchpad/options {:prefix false}}` to hide the
2323
start-of-line per-process prefix in the output
24+
- Introduce `--execute` (or `{:launchpad/options {:execute false}}`) and
25+
functionality that can launch the first configured `:exec-fn` (and
26+
relative `:exec-args`).
2427

2528
## Changed
2629

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,34 @@ Most of the time you want to add extra steps either right before, or right after
255255
launchpad/start-process]
256256
launchpad/after-steps)})
257257
```
258+
259+
## Launch `:exec-fn` in aliases
260+
261+
Launchpad can also call the first `:exec-fn` function (and relative `:exec-args`) it finds in its aggregated aliases.
262+
263+
This behavior is enabled by adding `--execute` to the command line.
264+
265+
> [!TIP]
266+
> The `Aliases:` line in the summary shows the ordered list of processed aliases. Only the first `:exec-fn` is used.
267+
268+
For example, you can configure an `:mcp` alias (from bhauman/clojure-mcp) within `deps.local.edn` like this:
269+
270+
```clojure
271+
:aliases {:mcp {:extra-deps {org.slf4j/slf4j-nop {:mvn/version "2.0.16"}
272+
com.bhauman/clojure-mcp {:local/root "/path/to/clojure-mcp"}}
273+
:exec-fn clojure-mcp.main/start-mcp-server
274+
:exec-args {:port 7888}}}
275+
...
276+
```
277+
278+
and launchpad will be able to call `clojure-mcp.main/start-mcp-server` this way:
279+
280+
```
281+
$ launchpad --execute mcp
282+
```
283+
284+
Note that this is a completely new code path and neither start nrepl nor hooks up the hot reloading facilities.
285+
258286
## Praise from Users
259287

260288
"This looks like a much easier way to get a new project up and running in a consistent and predictable manner where there is less likelihood of steps being missed or being different enough to cause confusion or additional cognitive load when switching projects. As you point out, also great for getting a team all working in a consistent configuration." -- Tim Cross, @theophilusx1

src/lambdaisland/launchpad.clj

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@
5353
"--[no-]debug-repl" {:doc "Include gfredericks/debug-repl dependency and middleware"}
5454
"--[no-]go" {:doc "Call (user/go) on boot"}
5555
"--[no-]namespace-maps" {:doc "Disable *print-namespace-maps* through nREPL middleware"}
56-
"--[no-]prefix" {:doc "Disable per-process prefix"}])
56+
"--[no-]prefix" {:doc "Disable per-process prefix"}
57+
"--[no-]execute" {:doc "Parse and execute the first :exec-fn found in aliases"}])
5758

5859
(def library-versions
5960
(:deps (edn/read-string (slurp (io/resource "launchpad/deps.edn")))))
@@ -364,14 +365,28 @@
364365
(catch Exception e
365366
(println "(user/go) failed" e))))))
366367

367-
(defn run-nrepl-server [{:keys [nrepl-port nrepl-bind middleware] :as ctx}]
368+
(defn nrepl-server-eval-forms [{:keys [nrepl-port nrepl-bind middleware] :as ctx}]
368369
(-> ctx
369370
(update :requires conj 'nrepl.cmdline)
370371
(update :eval-forms (fnil conj [])
371372
`(nrepl.cmdline/-main "--port" ~(str nrepl-port)
372373
"--bind" ~(str nrepl-bind)
373374
"--middleware" ~(pr-str middleware)))))
374375

376+
(defn exec-fn-eval-forms [{:keys [aliases deps-edn] :as ctx}]
377+
(let [{:keys [alias exec-fn exec-args]}
378+
(->> aliases
379+
;; we use only the first alias where :exec-fn is defined
380+
(some #(when (get-in deps-edn [:aliases % :exec-fn])
381+
(-> (get-in deps-edn [:aliases %])
382+
(assoc :alias %)))))]
383+
(assert (and exec-fn (symbol? exec-fn))
384+
"Launchpad could not find any valid :exec-fn symbol, aborting...")
385+
(info (format "Executing %s from the %s alias" exec-fn alias))
386+
(-> ctx
387+
(update :requires conj (symbol (namespace exec-fn)))
388+
(update :eval-forms (fnil conj []) `(~exec-fn ~exec-args)))))
389+
375390
(defn register-watch-handlers [ctx handlers]
376391
(update ctx
377392
:watch-handlers
@@ -559,7 +574,7 @@
559574
(System/exit exit))
560575
ctx))))))
561576

562-
(defn start-clojure-process [{:keys [aliases nrepl-port] :as ctx}]
577+
(defn start-clojure-process [ctx]
563578
(let [args (clojure-cli-args ctx)]
564579
(apply debug (map shellquote args))
565580
((run-process {:cmd args
@@ -583,7 +598,7 @@
583598
inject-aliases-as-property
584599
include-watcher
585600
print-summary
586-
run-nrepl-server])
601+
nrepl-server-eval-forms])
587602

588603
(def after-steps [wait-for-nrepl
589604
;; stuff that happens after the server is up
@@ -593,6 +608,14 @@
593608
[start-clojure-process]
594609
after-steps))
595610

611+
(def execute-steps [handle-cli-args
612+
;; extra java flags
613+
disable-stack-trace-elision
614+
inject-aliases-as-property
615+
print-summary
616+
exec-fn-eval-forms
617+
start-clojure-process])
618+
596619
(def ^:deprecated start-process start-clojure-process)
597620

598621
(defn find-project-root []
@@ -626,17 +649,20 @@
626649
end-steps
627650
pre-steps
628651
post-steps] :as ctx}]
629-
(let [ctx (process-steps
652+
(let [default-steps
653+
(if-not (:execute ctx)
654+
(concat
655+
start-steps
656+
before-steps
657+
pre-steps
658+
[start-clojure-process]
659+
post-steps
660+
after-steps
661+
end-steps)
662+
execute-steps)
663+
ctx (process-steps
630664
(update ctx :aliases concat (map keyword (::cli/argv ctx)))
631-
(or steps
632-
(concat
633-
start-steps
634-
before-steps
635-
pre-steps
636-
[start-clojure-process]
637-
post-steps
638-
after-steps
639-
end-steps)))
665+
(or steps default-steps))
640666
processes (:processes ctx)]
641667
(System/exit (apply min (for [p processes]
642668
(.waitFor p))))))

0 commit comments

Comments
 (0)