Class: Mxup::Launcher

Inherits:
Object
  • Object
show all
Defined in:
lib/mxup/launcher.rb

Overview

Generates and manages per-window launcher scripts.

Each declared window with non-trivial content (setup snippet, wait_for, env vars, or a command) gets a launcher script at

~/.local/share/mxup/<session>/<window>_launcher.sh

The keys sent to tmux are simply “. <path>”, so we can rewrite the script on every ‘mxup up` without having to re-send anything to healthy panes.

Instance Method Summary collapse

Constructor Details

#initialize(config, runtime_root: RUNTIME_DIR) ⇒ Launcher

Returns a new instance of Launcher.



16
17
18
19
# File 'lib/mxup/launcher.rb', line 16

def initialize(config, runtime_root: RUNTIME_DIR)
  @config       = config
  @runtime_root = runtime_root
end

Instance Method Details

#build_script(window) ⇒ Object

Build (but don’t write) the shell text for a window’s launcher script. Exposed for inspection/tests; production callers use #write_all.



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
# File 'lib/mxup/launcher.rb', line 54

def build_script(window)
  sections = []
  sections << "# mxup launcher for #{window.name}"
  sections << "cd #{Shellwords.escape(window.root)}"

  if @config.setup && !@config.setup.empty?
    sections << ''
    @config.setup.split("\n").each { |l| sections << l }
  end

  if window.wait_for
    sections << ''
    sections.concat(build_wait_block(window.wait_for))
  end

  if window.env.any?
    sections << ''
    window.env.each { |k, v| sections << "export #{k}=#{Shellwords.escape(v)}" }
  end

  if window.command && !window.command.empty?
    sections << ''
    sections << window.command
  end

  sections.join("\n") + "\n"
end

#build_wait_block(spec) ⇒ Object

Shell snippet (array of lines) implementing a wait_for check.



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
109
110
# File 'lib/mxup/launcher.rb', line 83

def build_wait_block(spec)
  check = probe_for(spec)
  lines = []
  lines << "echo 'Waiting for #{spec.label}...'"
  lines << "_mxup_wait_start=$(date +%s)"
  lines << ''

  if spec.timeout
    lines << "until #{check}; do"
    lines << "  _mxup_elapsed=$(($(date +%s) - _mxup_wait_start))"
    lines << "  if [ \"$_mxup_elapsed\" -ge #{spec.timeout.to_i} ]; then"
    lines << "    echo 'Timed out waiting for #{spec.label} after #{spec.timeout.to_i}s' >&2"
    lines << '    break'
    lines << '  fi'
    lines << "  echo \"  still waiting... (${_mxup_elapsed}s of #{spec.timeout.to_i}s)\""
    lines << "  sleep #{spec.interval}"
    lines << 'done'
  else
    lines << "until #{check}; do"
    lines << "  echo \"  still waiting... ($(($(date +%s) - _mxup_wait_start))s)\""
    lines << "  sleep #{spec.interval}"
    lines << 'done'
  end

  lines << ''
  lines << "echo '#{spec.label} is ready.'"
  lines
end

#cleanupObject



47
48
49
50
# File 'lib/mxup/launcher.rb', line 47

def cleanup
  dir = session_runtime_dir
  FileUtils.rm_rf(dir) if Dir.exist?(dir)
end

#command_for(window) ⇒ Object

Returns the shell keys to send to a fresh pane for this window. Empty string for a window that has nothing to execute (bare interactive shell).



31
32
33
# File 'lib/mxup/launcher.rb', line 31

def command_for(window)
  content?(window) ? ". #{script_path(window.name)}" : ''
end

#script_path(window_name) ⇒ Object



25
26
27
# File 'lib/mxup/launcher.rb', line 25

def script_path(window_name)
  File.join(session_runtime_dir, "#{window_name}_launcher.sh")
end

#session_runtime_dirObject



21
22
23
# File 'lib/mxup/launcher.rb', line 21

def session_runtime_dir
  File.join(@runtime_root, @config.session)
end

#write_allObject

Materialise launcher scripts for every window that needs one. Safe to call repeatedly; overwrites existing files.



37
38
39
40
41
42
43
44
45
# File 'lib/mxup/launcher.rb', line 37

def write_all
  FileUtils.mkdir_p(session_runtime_dir)
  @config.windows.each do |win|
    next unless content?(win)
    path = script_path(win.name)
    File.write(path, build_script(win))
    File.chmod(0o755, path)
  end
end