module EftCmdr

Constants

ACTIONS
DATE
SSH_LINE

–

VERSION

Public Class Methods

_opts(spec, more = {}) click to toggle source

helper

# File lib/eftcmdr.rb, line 105
def self._opts(spec, more = {})
  { title: spec['title'], scroll: spec['scroll'] } .merge more
end
ask(spec, state) click to toggle source

ask

# File lib/eftcmdr.rb, line 155
def self.ask(spec, state)                                     # {{{1
  Eft.ask spec['text'], _opts(spec, default: spec['default']) do |q|
    q.on_ok do |x|
      x =~ Regexp.new(spec['validate']) \
        or raise ValidationError, "#{x} !~ #{spec['validate']}" \
          if spec['validate']
      then_run spec['then'], state, spec['ask'].to_sym => x
    end
    on_cancel_esc q, spec, state
  end
end
ask_pass(spec, state) click to toggle source

ask password

# File lib/eftcmdr.rb, line 168
def self.ask_pass(spec, state)                                # {{{1
  Eft.ask_pass spec['text'], _opts(spec) do |q|
    q.on_ok do |x|
      then_run spec['then'], state, spec['ask_pass'].to_sym => x
    end
    on_cancel_esc q, spec, state
  end
end
ask_yesno(spec, state) click to toggle source

ask yes/no

# File lib/eftcmdr.rb, line 178
def self.ask_yesno(spec, state)                               # {{{1
  Eft.ask_yesno spec['text'], _opts(spec) do |q|
    q.on_yes do
      then_run spec['then'], state, spec['ask_yesno'].to_sym => true
    end
    q.on_no do
      then_run (spec['else'] || spec['then']), state,
        spec['ask_yesno'].to_sym => false
    end
    on_cancel_esc q, spec, state
  end
end
build_authorized_keys(file, dir, cmd) click to toggle source

turn dir (e.g. β€˜~/.eftcmdr.d`) into file (e.g. `~/.ssh/authorized_keys`): each `dir/$USER.pub` is added to `file` w/ forced command `cmd dir/$USER.yml $USER`; added entries are marked w/ a comment that includes the text `EFTCMDR` so that they can be ignored on subsequent runs.

# File lib/eftcmdr.rb, line 244
def self.build_authorized_keys(file, dir, cmd)                # {{{1
  dir =~ %r{\A[A-Za-z0-9_./-]+\z} \
    or raise InvalidFileNameError, "invalid dir name: #{dir}"
  cmd =~ %r{\A[A-Za-z0-9_./-]+\z} \
    or raise InvalidFileNameError, "invalid command name: #{cmd}"
  original = (File.exists?(file) ? File.read(file) : '') \
               .lines.reject { |l| l =~ /EFTCMDR/ }
  lines = Dir["#{dir}/*.pub"].sort.map do |x|
    b = File.basename x, '.pub'
    b =~ %r{\A[A-Za-z0-9_.-]+\z} \
      or raise InvalidFileNameError, "invalid file name: #{x}"
    k = File.read(x).chomp; f = x.sub /\.pub\z/, '.yml'
    SSH_LINE["#{cmd} #{f} #{b}", k, "(EFTCMDR #{x})"]
  end
  File.open(file, 'w') do |f|
    (original + lines).each { |l| f.puts l }
  end
end
check(spec, state) click to toggle source

checkboxes

# File lib/eftcmdr.rb, line 126
def self.check(spec, state)                                   # {{{1
  Eft.check spec['text'], _opts(spec) do |cb|
    spec['choices'].each do |c|
      cb.choice c['tag'], c['text'], c['selected']
    end
    cb.on_ok do |choices|
      then_run spec['then'], state, spec['check'].to_sym => choices
    end
    on_cancel_esc cb, spec, state
  end
end
eval(spec, state, &b) click to toggle source

evaluate and continue

# File lib/eftcmdr.rb, line 75
def self.eval(spec, state, &b)
  v = state.eval spec['code']
  n = v ? spec['then'] : spec['else'] || spec['then']
  b ? b[v,n] : then_run(n, state, spec['eval'].to_sym => v)
end
load_yaml(file, *args) click to toggle source

load yaml (parsed w/ ERB) @return [Array] [yaml,state]

# File lib/eftcmdr.rb, line 90
def self.load_yaml(file, *args)
  s = new_state file, args
  y = YAML.load ERB.new(File.read(file)).result s.scope
  [y,s]
end
menu(spec, state) click to toggle source

menu

new_state(file = nil, args = []) click to toggle source

new state

# File lib/eftcmdr.rb, line 84
def self.new_state(file = nil, args = [])
  State.new({}, Data.new(file, args, nil))
end
on_cancel_esc(e, spec, state) click to toggle source

handle β€˜on_{cancel,esc}`

# File lib/eftcmdr.rb, line 97
def self.on_cancel_esc(e, spec, state)
  e.on_cancel { then_run spec['cancel'], state } \
    if e.respond_to? :on_cancel
  e.on_esc { then_run spec['esc'], state } \
    if e.respond_to? :on_esc
end
radio(spec, state) click to toggle source

radiolist

# File lib/eftcmdr.rb, line 139
def self.radio(spec, state)                                   # {{{1
  Eft.radio spec['text'],
      _opts(spec, selected: spec['selected']) do |r|
    spec['choices'].each do |c|
      r.choice c['tag'], c['text']
    end
    r.on_ok do |choice|
      then_run spec['then'], state, spec['radio'].to_sym => choice
    end
    on_cancel_esc r, spec, state
  end
end
run(spec, state = new_state) click to toggle source

run self.$ACTION

# File lib/eftcmdr.rb, line 62
def self.run(spec, state = new_state)
  ACTIONS.each { |x| return self.send x, spec, state if spec[x] }
  raise InvalidSpecError, 'no action found'
end
show_msg(spec, state) click to toggle source

show message

# File lib/eftcmdr.rb, line 194
def self.show_msg(spec, state)                                # {{{1
  o = _opts(spec)
  if spec['code']
    eval spec, state do |v,n|
      Eft.show_msg v, o do |t|
        t.on_ok { then_run n, state, spec['show_msg'].to_sym => v }
        on_cancel_esc t, spec, state
      end
    end
  elsif spec['text']
    Eft.show_msg spec['text'], o do |t|
      t.on_ok { then_run spec['then'], state }
      on_cancel_esc t, spec, state
    end
  else
    raise InvalidSpecError, 'show_msg needs code or text'
  end
end
show_text(spec, state) click to toggle source

show text/file

# File lib/eftcmdr.rb, line 214
def self.show_text(spec, state)                               # {{{1
  if spec['code']
    eval spec, state do |v,n|
      Eft.show_text _opts(spec, text: v) do |t|
        t.on_ok { then_run n, state, spec['show_text'].to_sym => v }
        on_cancel_esc t, spec, state
      end
    end
  elsif spec['text']
    Eft.show_text _opts(spec, text: spec['text']) do |t|
      t.on_ok { then_run spec['then'], state }
      on_cancel_esc t, spec, state
    end
  elsif spec['file']
    Eft.show_text _opts(spec, file: spec['file']) do |t|
      t.on_ok { then_run spec['then'], state }
      on_cancel_esc t, spec, state
    end
  else
    raise InvalidSpecError, 'show_text needs code, text, or file'
  end
end
then_run(spec, state, ctx = {}) click to toggle source

run w/ merged ctx if there is a next action to run

# File lib/eftcmdr.rb, line 68
def self.then_run(spec, state, ctx = {})
  run spec, state.merge_ctx(ctx) if spec
end