typr 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/line.rb CHANGED
@@ -7,36 +7,36 @@ module Typr
7
7
  # == Example
8
8
  #
9
9
  # line = Line.new( top: 5, left: 10, width: 40 )
10
- # line.draw "Hello world"
10
+ # line.show "Hello world"
11
11
  # line.append " more"
12
- # line.ask([ ["Name?", :string], ["Age?", :integer] ])
12
+ # line.ask([ ["Name?", :line], ["Age?", :line] ])
13
13
 
14
14
  class Line < Space
15
- attr_accessor :default, :prompt, :bindings, :data
15
+ attr_accessor :default, :prompt, :bindings, :data, :align, :trim
16
16
 
17
17
  # Render +msg+ (String, Proc, or Space) on this line.
18
18
  #
19
- # line.draw "status: ok"
20
- # line.draw Proc.new { show_time }
19
+ # line.show "status: ok"
20
+ # line.show Proc.new { show_time }
21
21
 
22
- def draw msg=@data
22
+ def show msg=@data, align=@align
23
23
  @data = msg
24
24
  move left, top
25
25
  color @colors[:default]
26
26
  case msg
27
27
  when Proc; msg.call
28
- when Space; msg.draw
29
- when String; show( prepare msg, width )
28
+ when Space; msg.show
29
+ when String; draw( prepare msg, width, align, @trim )
30
30
  end
31
31
  end
32
32
 
33
33
  # Append +str+ to the current content and redraw.
34
34
  #
35
- # line.draw "hello"
35
+ # line.show "hello"
36
36
  # line.append " world" #=> "hello world"
37
37
  # line << "!" #=> "hello world!"
38
38
 
39
- def append(str); draw @data+str end
39
+ def append(str); show @data+str end
40
40
  alias :<< :append
41
41
 
42
42
  # Display keybinding help in a floating grid.
@@ -56,38 +56,68 @@ class Line < Space
56
56
  #
57
57
  # line.reset
58
58
 
59
- def reset; draw( @default || ( @bindings || [@prompt] ).join(' ') ) end
59
+ def reset; show( @default || ( @bindings || [@prompt] ).join(' ') ) end
60
60
 
61
61
  # Prompt the user with a sequence of questions.
62
- # +sentence+ is an array of [question, type] pairs.
63
- # Returns a single answer or an array when multiple questions.
62
+ # +sentence+ is an array of [question, type] pairs (or a hash of them).
63
+ # Returns a single answer, or an array when there are multiple questions.
64
64
  #
65
- # line.ask([ ["Name?", :string] ]) #=> "Alice"
66
- # line.ask([ ["Name?", :string], ["Ok?", ["y","n"]] ]) #=> ["Alice", "y"]
65
+ # The +type+ selects how the answer is collected:
66
+ # Array - interactive pick via <widget>.pick(<type>); an optional third
67
+ # element renders the chosen row's field into the line
68
+ # :key - a single keypress via Typr.read_key
69
+ # :line - interactive line editor via Typr.read_line at the cursor
70
+ #
71
+ # Pressing the exit key (@keymap[:exit], Escape by default) aborts the
72
+ # remaining questions and returns nil.
73
+ #
74
+ # line.ask(name: :line) #=> "Alice"
75
+ # line.ask(keys: :key) #=> "a"
76
+ # line.ask(open: [grid, :row, :name]) #=> 2 (picked row id)
77
+ # line.ask([ ["Name?", :line], ["Ok?", :key] ]) #=> ["Alice", "a"]
67
78
 
68
79
  def ask sentence
69
80
  answer = []
70
81
  move left, top
71
82
  Typr.clear :line
72
- draw @prompt
73
- for question, object in sentence
74
- color( @colors[:question] )
75
- append " " + question.to_s + " "
76
- column = Typr.column
77
- color( @colors[:answer] )
78
- case object
79
- when Array then answer << object.first.pick( object.last )
80
- else answer << Typr.read( object, @data )
83
+ saved = @trim
84
+ @trim = :left
85
+ begin
86
+ @data = @prompt.to_s
87
+ colored = color_code( @colors[:default] ).to_s + @data
88
+ move left, top
89
+ draw prepare( colored, width, @align, @trim )
90
+ for question, object in sentence
91
+ text = " " + question.to_s + " "
92
+ @data += text
93
+ colored += color_code( @colors[:question] ).to_s + text
94
+ move left, top
95
+ draw prepare( colored, width, @align, @trim )
96
+ color( @colors[:answer] )
97
+ case object
98
+ when Array then answer << object.first.pick( object[1] )
99
+ when :key then answer << Typr.read_key
100
+ when :line then answer << Typr.read_line( colored + color_code( @colors[:answer] ),
101
+ left: left, top: top )
102
+ end
103
+ return if !answer.last or answer.last == @keymap[:exit]
104
+ text = ( object.is_a?(Array) and object[2] ) ?
105
+ object.first.data[answer.last][object[2]].to_s : answer.last.to_s
106
+ @data += text
107
+ colored += color_code( @colors[:answer] ).to_s + text
108
+ move left, top
109
+ draw prepare( colored, width, @align, @trim )
81
110
  end
82
- return if !answer.last or answer.last == @keymap[:exit]
83
- move column, top
84
- append answer.last.to_s
111
+ ensure
112
+ @trim = saved
85
113
  end
86
114
  return ( answer.one? ? answer.first : answer )
87
115
  end
88
116
 
89
117
  def initialize args
90
118
  @right= -1
119
+ @align = :left
120
+ @trim = :right
91
121
  @prompt = ?>
92
122
  super
93
123
  @bottom = @top
data/lib/space.rb CHANGED
@@ -10,7 +10,7 @@ module Typr
10
10
  #
11
11
  # @example
12
12
  # box = Space.new(left: 0, top: 2, right: 0.5, bottom: -4, border: :round)
13
- # box.draw
13
+ # box.show
14
14
 
15
15
  class Space
16
16
  include Typr
@@ -29,21 +29,29 @@ include Typr
29
29
  STR
30
30
  eval( method % ([name]*11) ) }
31
31
 
32
+ def symbolize obj
33
+ case obj
34
+ when Hash
35
+ obj.each_with_object({}) { |(k, v), h|
36
+ h[k.is_a?(String) ? k.to_sym : k] = symbolize(v) }
37
+ else obj end
38
+ end
39
+
32
40
  attr_writer :left, :top, :right, :bottom
33
41
  attr_accessor :margin, :colors, :interval, :borders
34
42
 
35
43
  def width; right - left + 1 end
36
44
  def height; bottom - top + 1 end
37
45
 
38
- def start; @updater = Thread.new{ loop{draw; sleep @interval }} end
46
+ def start; @updater = Thread.new{ loop{show; sleep @interval }} end
39
47
  def stop; @updater.terminate end
40
48
 
41
49
  def draw_border x,y,char
42
- show move_code(x, y) + char unless not char or
50
+ draw move_code(x, y) + char unless not char or
43
51
  x < 0 or x > Typr.width or y < 0 or y > Typr.height
44
52
  end
45
53
 
46
- def draw
54
+ def show
47
55
  return if @borders.empty?
48
56
  color @colors[:border]
49
57
  draw_border(left - 1, top - 1, @borders[:top_left])
@@ -71,10 +79,11 @@ eval( method % ([name]*11) ) }
71
79
  end
72
80
 
73
81
  def initialize args={}
74
- @max, @keymap, @colors, @margin = 0, {}, {}, ' '
82
+ @max, @keymap, @colors, @margin = 0, {}, {}, ' '
75
83
  @left, @top, @interval, @borders = 0, 0, 1, {}
76
84
  args.each{ |name, value|
77
85
  instance_variable_set ?@ + name.to_s, value }
86
+ @colors = symbolize( @colors ) if @colors.is_a? Hash
78
87
  @keymap = { exit: KEY_ESCAPE }.merge @keymap
79
88
  @colors = { default: [:white, :black], border: [:white, :black] }.merge(@colors)
80
89
  borders = @borders.dup
data/lib/stack.rb CHANGED
@@ -1,7 +1,3 @@
1
- #!/usr/bin/env ruby
2
- # coding: utf-8
3
- # frozen_string_literal: true
4
-
5
1
  module Typr
6
2
 
7
3
  ##
@@ -54,7 +50,7 @@ module Typr
54
50
  #
55
51
  # stack.print 42 # renders a blank row
56
52
 
57
- def print id; show " " * (width-@margin.size) end
53
+ def print id; draw " " * (width-@margin.size) end
58
54
 
59
55
  ##
60
56
  # Resets widget state by one or more categories.
@@ -84,12 +80,16 @@ module Typr
84
80
  if type.to_s[ /column/ ]
85
81
  positions( row_id )[ @hints_start..-1 ].each_with_index{ |pos, idx|
86
82
  move( left + pos, top + row_id )
87
- show @hints[idx] }
88
- else @hints.chars.each_with_index{ |char, idx|
89
- pos = idx + @hints_start + headspace
90
- break if pos > [height, rows-1+headspace].min
91
- move( left, top + pos )
92
- show char }
83
+ draw @hints[idx] }
84
+ else
85
+ bottom = top + headspace + [height, rows].min - 1
86
+ (top + headspace..bottom).each{ |pos|
87
+ move( left, pos ); draw ' ' }
88
+ @hints.chars.each_with_index{ |char, idx|
89
+ pos = idx + @hints_start + headspace
90
+ break if top + pos > bottom
91
+ move( left, top + pos )
92
+ draw char }
93
93
  end
94
94
  end
95
95
 
@@ -100,11 +100,11 @@ module Typr
100
100
  # This method is called by your application's main loop each frame; it does not handle
101
101
  # events itself (see {#send}).
102
102
 
103
- def draw
103
+ def show
104
104
  if @header
105
105
  color @colors[ :header ]
106
106
  move left,top
107
- show @margin
107
+ draw @margin
108
108
  print :header
109
109
  end
110
110
  list = page.to_a
@@ -116,7 +116,7 @@ module Typr
116
116
  dark=!dark if @alternate
117
117
  background ( select ? @colors[:selected] :
118
118
  (@alternate and dark) ? @colors[:alternate] : @colors[:default][1] )
119
- show @margin
119
+ draw @margin
120
120
  print id
121
121
  background if select
122
122
  end
@@ -195,7 +195,6 @@ module Typr
195
195
  # stack.pick "rows" # multi-select rows
196
196
 
197
197
  def pick type = :row, row=0 #, key=nil
198
- @hints_start = 0
199
198
  type = type.to_s
200
199
  multiple = type[-1] == ?s
201
200
  loop do
@@ -204,10 +203,10 @@ module Typr
204
203
  column = pick( :column, page.to_a.index( row + headspace)) or return
205
204
  value = [ row , column ]
206
205
  else
207
- draw
206
+ show
208
207
  draw_hints type, row unless type['none']
209
208
  limit = type['row'] ? height : positions(row).count
210
- key = Typr.read :key
209
+ key = Typr.read_key
211
210
  if key.is_a?(String) and value =
212
211
  @hints[0..limit-@hints_start-1].index(key)
213
212
  value += @hints_start
@@ -262,9 +261,9 @@ module Typr
262
261
 
263
262
  def initialize args={}
264
263
  @keymap, @separator, @selected = {}, " ", {}
265
- @start, @hints_start, @highlight = 0, 0, 0#A_STANDOUT
264
+ @start, @hints_start = 0, 0
266
265
  @alternate = true
267
- super #args
266
+ super
268
267
  @colors = { hints: [255, :black ], header: [232,:grey60 ],
269
268
  selected: :grey25, alternate: :grey10, rows: {} }.merge @colors
270
269
  @selected = { fields:[], columns:[], rows:[] }.merge @selected