Module: Tempest::REPL::Compose
- Defined in:
- lib/tempest/repl/compose.rb
Overview
Opens ‘$VISUAL` / `$EDITOR` on a scratch file so the user can compose a multi-line post in their normal editor, the same pattern `git commit` uses. Returns one of the status tuples below; the caller (typically `Runner#handle_compose`) maps each to a user-facing line and, when `:ok`, forwards the body to `Post.create`.
Return values:
[:ok, body] successful compose; body is non-empty
[:empty, nil] user saved an empty body — treat as cancellation
[:editor_failed, nil] the editor subprocess returned a non-zero status
Lines beginning with ‘#` are stripped from the file before posting (so we can pre-populate the file with instructions a la `git commit`’s template).
Constant Summary collapse
- TEMPLATE =
<<~EOT.freeze # Compose your Bluesky post above this line. # Lines starting with `#` and surrounding whitespace are stripped. # Save with an empty body (or quit without changes) to cancel. EOT
Class Method Summary collapse
- .parse(content) ⇒ Object
-
.pick_editor(env) ⇒ Object
Editor resolution order, matching git’s convention: $VISUAL, then $EDITOR, then “vi” as a POSIX-mandated last resort.
- .run(env: ENV, runner: Kernel.method(:system), tempfile_factory: ->(suffix) { Tempfile.new(["tempest-compose-", suffix]) }) ⇒ Object
Class Method Details
.parse(content) ⇒ Object
68 69 70 71 72 73 74 |
# File 'lib/tempest/repl/compose.rb', line 68 def parse(content) content .each_line .reject { |line| line.start_with?("#") } .join .strip end |
.pick_editor(env) ⇒ Object
Editor resolution order, matching git’s convention: $VISUAL, then $EDITOR, then “vi” as a POSIX-mandated last resort. The fallback means we never need to surface a “no editor” error to the user; if even vi cannot be exec’d, ‘Kernel.system` returns false and the call surfaces as :editor_failed.
61 62 63 64 65 66 |
# File 'lib/tempest/repl/compose.rb', line 61 def pick_editor(env) candidate = env["VISUAL"] candidate = env["EDITOR"] if candidate.nil? || candidate.strip.empty? candidate = "vi" if candidate.nil? || candidate.strip.empty? candidate end |
.run(env: ENV, runner: Kernel.method(:system), tempfile_factory: ->(suffix) { Tempfile.new(["tempest-compose-", suffix]) }) ⇒ Object
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 |
# File 'lib/tempest/repl/compose.rb', line 30 def run(env: ENV, runner: Kernel.method(:system), tempfile_factory: ->(suffix) { Tempfile.new(["tempest-compose-", suffix]) }) editor = pick_editor(env) file = tempfile_factory.call(".txt") path = file.path begin file.write(TEMPLATE) file.flush file.close ok = runner.call(editor, path) return [:editor_failed, nil] unless ok body = parse(File.read(path)) return [:empty, nil] if body.empty? [:ok, body] ensure begin file.unlink rescue StandardError # File may already be gone (e.g. editor moved it); best-effort. end end end |