module Flammarion::Writeable

Clickable Image module mixin for Flammarion::Writeable

Features:

- clickable => will call the given block when user clicks image
- update() => can be replaced/updated 
- src= => img src can be updated on the fly

Mixin for Flammarion::Writeable which provides short-cuts for common html elements

Parameters will not be escaped (raw)!

Some examples:

f.p                       =>     f.puts "<p/>", raw: true
f.h1 "Title"              =>     f.puts "<h1>Title</h2>", raw: true
f.img src: "url", width: 32 =>     f.puts '<img src="url" width="32"/>', raw: true
f.p "Hello", "World"      =>     f.puts "<p>Hello</p><p>World</p>", raw: true

Paragraph which can be updated easily as a mixin for Flammarion

Run the given program using Open3.popen3 and redirects output to the subpane(“out”) (STDOUT and STDERR).

A simple CSS-based progress bar for Flammarion.

Use set() to set the progress as an integer in percent.

progress = f.progress
... # do first half
progress.set(50)
... # finish work
progress.set(100) # => will set to 100%

Or use each() with an array

progress.each([1,2,3]) { |x| ... }

Attributes

alt[RW]
height[RW]
title[RW]
url[RW]
width[RW]

Public Instance Methods

img_raw(url, width, height, alt, title, options = {}, &block) click to toggle source
# File lib/cem/cflame/clickable_img.rb, line 54
def img_raw(url, width, height, alt, title, options = {}, &block)
  return ClickableImage.new(url, width, height, alt, title, @engraving.make_id, self, block)    
end
method_missing(m, *args, &block) click to toggle source
# File lib/cem/cflame/missing_html.rb, line 18
def method_missing(m, *args, &block)
  
  if !isHTML5Element(m)
    puts "Warning: #{m} is not a valid HTML 5 Tag"
  end    
  
  attribs = args.last.is_a?(Hash) ? args.pop.map { |key, value| %| #{key.to_s}="#{value}"| }.join : ""
  
  if args.size == 0
    puts "<#{m} #{attribs}/>", raw: true
  else
    puts args.map { |value| "<#{m} #{attribs}>#{value}</#{m}>" }.join, raw: true
  end 
end
p(text) click to toggle source
# File lib/cem/cflame/p.rb, line 31
def p(text)
  object = Paragraph.new(text, @engraving.make_id, self)
  puts object, raw:true
  object
end
progress(name = nil) click to toggle source
# File lib/cem/cflame/progress.rb, line 45
def progress(name = nil)
  return Progress.new(name || @engraving.make_id, self)    
end
system(*cmd, pane_out: "out", pane_err: "out", pane_in: "in", status: true, close_btn: true, auto_clear: true, kill_sig: 'KILL') click to toggle source

This method does not block, but returns after the program has been started.

Caution: By default most program run via Open3.popen3 assume they are started in non PTY mode and will buffer their output. To tell the program to be interactive use something like 'script -qefc "<program>" /dev/null' as command. See stackoverflow.com/questions/1401002/trick-an-application-into-thinking-its-stdout-is-a-terminal-not-a-pipe

+*cmd+

cmd string to pass to Open3.popen3

pane_out

Name of the pane that the STDOUT of the program should be print to. Defaults to “out”

pane_err

Name of the pane that the STDERR of the program should be print to. Defaults to “out”. Set to nil/false to prevent STDERR to be printed.

pane_in

Name of the pane that should be used to wait for input from the user. Defaults to “in”. Set to nil/false to prevent user input.

status

Should status updates (start, termination) be printed to Writeable::status. Defaults to true. Set to nil/false to disable.

close_btn

Should a close button be shown in the pane_in. Defaults to true. Set to nil/false to disable.

auto_clear

Should the panes be cleared prior to launching the program? Defaults to true. Set to nil/false to disable.

kill_sig

What to pass to Process.kill when close_btn is pressed but program does not react to STDIN being closed. Defaults to “KILL”. Could be “TERM”.

# File lib/cem/cflame/popen.rb, line 22
def system(*cmd, pane_out: "out", pane_err: "out", pane_in: "in", status: true, close_btn: true, auto_clear: true, kill_sig: 'KILL')

  # Clear all panes if auto_clear is set
  [pane_out, pane_err, pane_in].uniq.each { |p| p && subpane(p).clear } if auto_clear

  i, o, e, t = Open3.popen3(*cmd, pgroup: true)
  cmd = cmd.join

  status("Running '#{cmd}'".light_green) if status

  if pane_in
  
    subpane(pane_in).input("> ", autoclear:true, history:true) do |msg|
      i.puts msg['text']
    end 

    if close_btn
    
      subpane(pane_in).button("Close") do       
      
        subpane(pane_in).clear if auto_clear
        i.close
        
        value = begin
          if t.join(1)
            t.value
          else
            # TERM/KILL whole progress group
            Process.kill(kill_sig, -Process.getpgid(t.pid))
            if t.join(3)
              t.value
            else
              nil
            end
          end
        end
            
        if !value 
          status("Command '#{cmd}' did not terminate promptly.".light_red);
        end if status
      end
    end
  end

  Thread.new do
    begin
      while l = e.readpartial(4096)
        subpane(pane_err).print l.red
      end
    rescue EOFError
      # Do nothing
    end
  end if pane_err

  begin
    while l = o.readpartial(4096)
      subpane(pane_out).print l
    end
  rescue EOFError
    subpane(pane_in).clear if auto_clear
    
    if status && t.join(5)
      t.value.success? ? status("Command '#{cmd}' exited with success".light_green) : status("Command '#{cmd}' exited with error code: #{t.value}".light_red)
    end
  end  
end