Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Terminal can be launched with a specified command #38

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This change

## [Unreleased]
### Changed
- Can now specify the launch command [#3](https://github.com/phronmophobic/membrane.term/issues/3)
- Document public API [#28](https://github.com/phronmophobic/membrane.term/issues/28)
- **Breaking** `screenshot` `:play` option was file, is now string (command line is unaffected, `--play` still references a file) [#26](https://github.com/phronmophobic/membrane.term/issues/28)

Expand Down
48 changes: 44 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Some reasons to use **membrane.term**:

Pre 1.0 release.
APIs and behavior are subject to change.

macOS and Linux are the current focus, Windows support is pre-alpha.
## Installation

Membrane.term works on macOS and Linux operating systems.
Expand Down Expand Up @@ -60,6 +60,9 @@ A demo of the types of things you can do:
![run-term-demo](doc/images/run-term-demo.gif?raw=true)

You can also optional specify:
- [`-c, --command`](#command) Command to launch with, defaults to:
- macOS & Linux: `$SHELL` else `/bin/bash`
- Windows: `powershell`
- `-w, --width` width of the terminal window in character columns (default: 90)
- `-h, --height` height of the terminal window in character rows (default: 30)
- [`--color-scheme`](#color-schemes) choose a different color scheme
Expand All @@ -75,6 +78,7 @@ Given play script `play-msgcat.sh`:
<!-- copied from doc/examples/play-msgcat.sh -->
```bash
# override prompt to something doc-friendly
/bin/bash # could alternatively use --command
export PS1="$ "
# print out some colors
clear
Expand All @@ -91,10 +95,11 @@ Membrane.term passes the script to the terminal character by character, then wri
<!-- generated by script/regen-screenshots.sh -->
![play-msgcat-example](doc/images/screenshot-msgcat.png)

You must specify:
- `-p, --play` script to play

You can also optionally specify:
- [`-c, --command`](#command) Command to launch with, defaults to:
- macOS & Linux: `$SHELL` else `/bin/bash`
- Windows: `powershell`
- `-p, --play` script to play in the terminal
- `-w, --width` width of the terminal window in character columns (default: 90)
- `-h, --height` height of the terminal window in character columns (default: 30)
- `-o, --out` filename of the image file to generate (default: terminal.png)\
Expand All @@ -112,6 +117,7 @@ Given play script `play-deep-diff.sh`:
<!-- copied from doc/examples/play-deep-diff.sh -->
```bash
# our setup
/bin/bash # could alternatively use --command
export PS1="$ "
cd
mkdir -p target/term-screenshot
Expand All @@ -135,6 +141,40 @@ Produces `deep-diff.jpg`:
<!-- generated by script/regen-screenshots.sh -->
![play-deep-diff-example](doc/images/screenshot-deep-diff.png)


## Command

By default, `membrane.term` will attempt to launch with your OS shell.

Use the `--command` option to launch with a different program.

Let's suppose your favorite process monitor is [htop](https://htop.dev/) and that just want to run that:
```bash
clj -M:membrane.term run-term --command "htop --tree --delay 10"
```

Sometimes you are interested in taking a screenshot of only the output of a command:
```bash
clj -M:membrane.term screenshot --command "msgcat --color=test" --width 80 --height 21
```
![screenshot-msgcat-command-example](doc/images/screenshot-msgcat-command.png)

Or, for a contrived example, let's pretend you want to play some text in `vi` and take a screenshot.
Given file `an-ode-to-clojure.txt`:
```
iRoses are red
Violets are blue
Clojure is fun
And so are you
```

Let's run:
```bash
clj -M:membrane.term screenshot --command vi --play an-ode-to-clojure.txt \
--width 40 --height 10
```
![screenshot-vi-command-example](doc/images/screenshot-vi-command.png)

## Color Schemes

There are boatloads of terminal color schemes available at [iTerm2-Color-Schemes](https://github.com/mbadolato/iTerm2-Color-Schemes).
Expand Down
1 change: 1 addition & 0 deletions deps.edn
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{:paths ["src" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.10.3"}
babashka/process {:mvn/version "0.0.2"}
org.clojure/data.xml {:mvn/version "0.2.0-alpha6"}
org.clojure/data.zip {:mvn/version "1.0.0"}
dev.nubank/docopt {:mvn/version "0.6.1-fix7"}
Expand Down
4 changes: 4 additions & 0 deletions doc/examples/an-ode-to-clojure.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
iRoses are red
Violets are blue
Clojure is fun
And so are you
1 change: 1 addition & 0 deletions doc/examples/play-deep-diff.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/bin/bash -l
export PS1="$ "
cd
mkdir -p target/term-screenshot
Expand Down
1 change: 1 addition & 0 deletions doc/examples/play-msgcat.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/bin/bash -l
# override prompt to something doc-friendly
export PS1="$ "
# print out some colors
Expand Down
Binary file modified doc/images/screenshot-deep-diff.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/images/screenshot-msgcat-command.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/images/screenshot-msgcat-font.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/images/screenshot-msgcat-scheme.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/images/screenshot-msgcat.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added doc/images/screenshot-vi-command.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@
<artifactId>clojure</artifactId>
<version>1.10.3</version>
</dependency>
<dependency>
<groupId>babashka</groupId>
<artifactId>process</artifactId>
<version>0.0.2</version>
</dependency>
<dependency>
<groupId>org.clojure</groupId>
<artifactId>data.xml</artifactId>
Expand Down
14 changes: 13 additions & 1 deletion script/regen-screenshots.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#/usr/bin/env bash
#!/usr/bin/env bash

set -eou pipefail

Expand Down Expand Up @@ -31,3 +31,15 @@ clj -M:membrane.term screenshot \
--font-family "NovaMono" \
--font-size 16 \
--out doc/images/screenshot-msgcat-font.png

echo "- launch msgcat as command -"
clj -M:membrane.term screenshot \
--command 'msgcat --color=test' \
--width 80 --height 22 \
--out doc/images/screenshot-msgcat-command.png

echo "- launch with vi and play some text -"
clj -M:membrane.term screenshot \
--command vi --play doc/examples/an-ode-to-clojure.txt \
--width 40 --height 10 \
--out doc/images/screenshot-vi-command.png
58 changes: 45 additions & 13 deletions src/com/phronemophobic/membrane/term.clj
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@
(:import [com.pty4j PtyProcess WinSize]))


(defn- start-pty []
(let [cmd (into-array String ["/bin/bash" "-l"])
(def ^:private windows?
(-> (System/getProperty "os.name")
(string/lower-case)
(string/includes? "win")))

(defn- start-pty [cmd]
(let [cmd (into-array String cmd)
pty (PtyProcess/exec ^"[Ljava.lang.String;" cmd
^java.util.Map (merge (into {} (System/getenv))
{"TERM" "xterm-256color"}))]
Expand Down Expand Up @@ -278,9 +283,9 @@
nil)
view)))

(defn- run-pty-process [width height term-state]
(defn- run-pty-process [cmd width height term-state]
(let [^PtyProcess
pty (doto ^PtyProcess (start-pty)
pty (doto ^PtyProcess (start-pty cmd)
(.setWinSize (WinSize. width height)))]
(future
(try
Expand Down Expand Up @@ -316,6 +321,12 @@
(defn- load-default-toolkit []
@(requiring-resolve 'membrane.java2d/toolkit))

(defn- default-cmd []
[(if windows?
"powershell"
(or (System/getenv "SHELL")
"/bin/bash"))])

(def default-color-scheme
"Default color-scheme used in [[default-run-term-opts]] and [[default-screenshot-opts]]"
{:white [1 1 1]
Expand Down Expand Up @@ -352,8 +363,15 @@
"Launch an interactive membrane.term terminal. Terminal exits when explicitly closed by user.

Accepts optional `opts` map:
- `:width` Window width in characters (default: `90`)
- `:height` Window height in characters (default: `30`)
- `:command` The command to run, typically, but not necessarily, a shell.
- Examples:
- `[\"/bin/bash\" \"--login\"]`
- `[\"top\"]`
- Defaults:
- macOS and linux: value of SHELL environment value, else `[\"/bin/bash\"]`
- Windows: `[\"powershell\"]`
- `:width` Window width in characters (default: `90`)
- `:height` Window height in characters (default: `30`)
- `:color-scheme` Map for terminal colors (defaults to an internal scheme)
Colors are specified per membrane convention, vectors of `[red green blue]` or
`[red green blue alpha]` with values from `0` - `1` inclusive. Example: `[0.14 0.74 0.14 0.50]`.
Expand Down Expand Up @@ -381,16 +399,17 @@
- Usable examples from membrane library: `membrane.java2d/toolkit`, `membrane.skia/toolkit`"
([]
(run-term {}))
([{:keys [width height color-scheme font-family font-size toolkit] :as opts}]
([{:keys [command width height color-scheme font-family font-size toolkit] :as opts}]
(let [opts (merge default-run-term-opts opts)
{:keys [width height color-scheme font-family font-size toolkit]} opts
{:keys [command width height color-scheme font-family font-size toolkit]} opts
command (or command (default-cmd))
term-state (atom {:vt (vt/make-vt width height)})
toolkit (if toolkit
toolkit
(load-default-toolkit))
font (load-terminal-font toolkit font-family font-size)]
(swap! term-state assoc
:pty (run-pty-process width height term-state))
:pty (run-pty-process command width height term-state))
(tk/run-sync
toolkit
(fn []
Expand All @@ -414,7 +433,14 @@
Terminal is not displayed and automatically exits after screenshot is written.

Requires `opts` map:
- `:play` Script string to play in terminal (**required**)
- `:command` The command to run, typically, but not necessarily, a shell.
- Examples:
- `[\"/bin/bash\" \"--login\"]`
- `[\"top\"]`
- Defaults:
- macOS and linux: value of SHELL environment value, else `[\"/bin/bash\"]`
- Windows: `[\"powershell\"]`
- `:play` Optional script string to play in terminal
- `:out` Filename for screenshot image (default: `\"terminal.png\"`)
- `:line-delay` Delay in milliseconds to wait after each line in `:play` script is sent to terminal (default: `1000`)
- `:final-delay` Delay in milliseconds to wait after all lines in `:play` script are sent to terminal (default: `10000`)
Expand Down Expand Up @@ -446,16 +472,18 @@
- `IToolkitRunSync`
- `IToolkitSaveImage`
- Usable examples from membrane library: `membrane.java2d/toolkit`, `membrane.skia/toolkit`"
[{:keys [play out line-delay final-delay width height color-scheme font-family font-size toolkit] :as opts}]
[{:keys [command play out line-delay final-delay width height color-scheme font-family font-size toolkit] :as opts}]
(let [opts (merge default-screenshot-opts opts)
{:keys [play width height out line-delay final-delay color-scheme font-family font-size toolkit]} opts
{:keys [command play width height out line-delay final-delay color-scheme font-family font-size toolkit]} opts
command (or command (default-cmd))
play (or play "")
term-state (atom {:vt (vt/make-vt width height)})
toolkit (if toolkit
toolkit
(load-default-toolkit))
font (load-terminal-font toolkit font-family font-size)]
(swap! term-state assoc
:pty (run-pty-process width height term-state))
:pty (run-pty-process command width height term-state))
(doseq [line (string/split-lines play)]
(send-input (:pty @term-state) line)
(send-input (:pty @term-state) "\n")
Expand All @@ -473,6 +501,10 @@
(.close (.getOutputStream pty)))))

(comment
(run-term {:cmd ["ls" "-l"]})
(run-term {:cmd ["top"]})
(run-term {:font-family "MesloLGS NF" :font-size 14 :width 200} )

(screenshot {:play "ls -l" :out "x.png"})
(screenshot {:play "ls -l\n" :out "y.png"})
(screenshot {:play "export PS1='$ '\nclear\nmsgcat --color=test | head -11" :out "z.png"}))
19 changes: 15 additions & 4 deletions src/com/phronemophobic/membrane/term/main.clj
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,26 @@
[membrane.ui :as ui]
[membrane.toolkit :as tk]
[com.phronemophobic.membrane.term.color-scheme :as color-scheme]
[docopt.core :as docopt]))
[docopt.core :as docopt]
[babashka.process :as process]))

(def docopt-usage
"membrane.term

Usage:
membrane.term run-term [--width=<cols>] [--height=<rows>] \\
membrane.term run-term [--command=<cmdline>] \\
[--width=<cols>] [--height=<rows>] \\
[--color-scheme=<path>] [--font-family=<font>] [--font-size=<points>] [--toolkit=<toolkit>]
membrane.term screenshot --play=<path> [--width=<cols>] [--height=<rows>] \\
membrane.term screenshot [--command=<cmdline>] [--play=<path>] \\
[--width=<cols>] [--height=<rows>] \\
[--color-scheme=<path>] [--font-family=<font>] [--font-size=<points>]\\
[--out=<file>] [--line-delay=<ms>] [--final-delay=<ms>] [--toolkit=<toolkit>]
membrane.term --help

Common Options:
-c, --command=<cmdline> Command to launch with, typically but not necessary a shell.
Default: on macOS and Linux defaults to $SHELL else /bin/bash
on Windows powershell
-w, --width=<cols> Width in characters [default: 90]
-h, --height=<rows> Height in characters [default: 30]
--color-scheme=<path> Local path or url to iTerm .itermcolors scheme file, uses internal scheme by default.
Expand Down Expand Up @@ -110,6 +116,10 @@ Replace membrane.term with your appropriate Clojure tools CLI launch sequence. F
(catch Throwable e
{:error (ex-message e)})))

(defn parse-command [v]
(when v
(process/tokenize (str v))))

(defn- validate-font [args]
(let [font-family (get args "--font-family")
font-size (get args "--font-size")
Expand Down Expand Up @@ -151,7 +161,8 @@ Replace membrane.term with your appropriate Clojure tools CLI launch sequence. F
(defn -main [& args]
(docopt/docopt (undo-line-continuations docopt-usage) args
(fn result-fn [arg-map]
(let [arg-map (validate-args arg-map {"--width" (int-parser-validator 1)
(let [arg-map (validate-args arg-map {"--command" parse-command
"--width" (int-parser-validator 1)
"--height" (int-parser-validator 1)
"--play" parse-play-script
"--color-scheme" parse-color-scheme
Expand Down