canis 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (134) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +45 -0
  3. data/CHANGES +52 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +24 -0
  7. data/Rakefile +2 -0
  8. data/canis.gemspec +25 -0
  9. data/examples/alpmenu.rb +46 -0
  10. data/examples/app.sample +19 -0
  11. data/examples/appemail.rb +191 -0
  12. data/examples/atree.rb +105 -0
  13. data/examples/bline.rb +181 -0
  14. data/examples/common/devel.rb +319 -0
  15. data/examples/common/file.rb +93 -0
  16. data/examples/data/README.markdown +9 -0
  17. data/examples/data/brew.txt +38 -0
  18. data/examples/data/color.2 +37 -0
  19. data/examples/data/gemlist.txt +59 -0
  20. data/examples/data/lotr.txt +12 -0
  21. data/examples/data/ports.txt +136 -0
  22. data/examples/data/table.txt +37 -0
  23. data/examples/data/tasks.csv +88 -0
  24. data/examples/data/tasks.txt +27 -0
  25. data/examples/data/todo.txt +16 -0
  26. data/examples/data/todocsv.csv +28 -0
  27. data/examples/data/unix1.txt +21 -0
  28. data/examples/data/unix2.txt +11 -0
  29. data/examples/dbdemo.rb +506 -0
  30. data/examples/dirtree.rb +177 -0
  31. data/examples/newtabbedwindow.rb +100 -0
  32. data/examples/newtesttabp.rb +92 -0
  33. data/examples/tabular.rb +212 -0
  34. data/examples/tasks.rb +179 -0
  35. data/examples/term2.rb +88 -0
  36. data/examples/testbuttons.rb +307 -0
  37. data/examples/testcombo.rb +102 -0
  38. data/examples/testdb.rb +182 -0
  39. data/examples/testfields.rb +208 -0
  40. data/examples/testflowlayout.rb +43 -0
  41. data/examples/testkeypress.rb +98 -0
  42. data/examples/testlistbox.rb +187 -0
  43. data/examples/testlistbox1.rb +199 -0
  44. data/examples/testmessagebox.rb +144 -0
  45. data/examples/testprogress.rb +116 -0
  46. data/examples/testree.rb +107 -0
  47. data/examples/testsplitlayout.rb +53 -0
  48. data/examples/testsplitlayout1.rb +49 -0
  49. data/examples/teststacklayout.rb +48 -0
  50. data/examples/testwsshortcuts.rb +68 -0
  51. data/examples/testwsshortcuts2.rb +129 -0
  52. data/lib/canis.rb +16 -0
  53. data/lib/canis/core/docs/index.txt +104 -0
  54. data/lib/canis/core/docs/list.txt +16 -0
  55. data/lib/canis/core/docs/style_help.yml +34 -0
  56. data/lib/canis/core/docs/tabbedpane.txt +15 -0
  57. data/lib/canis/core/docs/table.txt +31 -0
  58. data/lib/canis/core/docs/textpad.txt +48 -0
  59. data/lib/canis/core/docs/tree.txt +23 -0
  60. data/lib/canis/core/include/.DS_Store +0 -0
  61. data/lib/canis/core/include/action.rb +83 -0
  62. data/lib/canis/core/include/actionmanager.rb +49 -0
  63. data/lib/canis/core/include/appmethods.rb +179 -0
  64. data/lib/canis/core/include/bordertitle.rb +49 -0
  65. data/lib/canis/core/include/canisparser.rb +100 -0
  66. data/lib/canis/core/include/colorparser.rb +437 -0
  67. data/lib/canis/core/include/defaultfilerenderer.rb +64 -0
  68. data/lib/canis/core/include/io.rb +320 -0
  69. data/lib/canis/core/include/layouts/SplitLayout.rb +161 -0
  70. data/lib/canis/core/include/layouts/abstractlayout.rb +213 -0
  71. data/lib/canis/core/include/layouts/flowlayout.rb +104 -0
  72. data/lib/canis/core/include/layouts/stacklayout.rb +109 -0
  73. data/lib/canis/core/include/listbindings.rb +89 -0
  74. data/lib/canis/core/include/listeditable.rb +319 -0
  75. data/lib/canis/core/include/listoperations.rb +61 -0
  76. data/lib/canis/core/include/listselectionmodel.rb +388 -0
  77. data/lib/canis/core/include/multibuffer.rb +173 -0
  78. data/lib/canis/core/include/ractionevent.rb +73 -0
  79. data/lib/canis/core/include/rchangeevent.rb +27 -0
  80. data/lib/canis/core/include/rhistory.rb +95 -0
  81. data/lib/canis/core/include/rinputdataevent.rb +47 -0
  82. data/lib/canis/core/include/textdocument.rb +111 -0
  83. data/lib/canis/core/include/vieditable.rb +175 -0
  84. data/lib/canis/core/include/widgetmenu.rb +66 -0
  85. data/lib/canis/core/system/colormap.rb +165 -0
  86. data/lib/canis/core/system/keydefs.rb +32 -0
  87. data/lib/canis/core/system/ncurses.rb +237 -0
  88. data/lib/canis/core/system/panel.rb +129 -0
  89. data/lib/canis/core/system/window.rb +1081 -0
  90. data/lib/canis/core/util/ansiparser.rb +119 -0
  91. data/lib/canis/core/util/app.rb +696 -0
  92. data/lib/canis/core/util/basestack.rb +412 -0
  93. data/lib/canis/core/util/defaultcolorparser.rb +84 -0
  94. data/lib/canis/core/util/extras/README +5 -0
  95. data/lib/canis/core/util/extras/bottomline.rb +1815 -0
  96. data/lib/canis/core/util/extras/padreader.rb +192 -0
  97. data/lib/canis/core/util/focusmanager.rb +31 -0
  98. data/lib/canis/core/util/helpmanager.rb +160 -0
  99. data/lib/canis/core/util/oldwidgetshortcuts.rb +304 -0
  100. data/lib/canis/core/util/promptmenu.rb +235 -0
  101. data/lib/canis/core/util/rcommandwindow.rb +933 -0
  102. data/lib/canis/core/util/rdialogs.rb +520 -0
  103. data/lib/canis/core/util/textutils.rb +74 -0
  104. data/lib/canis/core/util/viewer.rb +238 -0
  105. data/lib/canis/core/util/widgetshortcuts.rb +508 -0
  106. data/lib/canis/core/widgets/applicationheader.rb +103 -0
  107. data/lib/canis/core/widgets/box.rb +58 -0
  108. data/lib/canis/core/widgets/divider.rb +310 -0
  109. data/lib/canis/core/widgets/extras/README.md +12 -0
  110. data/lib/canis/core/widgets/extras/rtextarea.rb +960 -0
  111. data/lib/canis/core/widgets/extras/stackflow.rb +474 -0
  112. data/lib/canis/core/widgets/keylabelprinter.rb +194 -0
  113. data/lib/canis/core/widgets/listbox.rb +326 -0
  114. data/lib/canis/core/widgets/listfooter.rb +86 -0
  115. data/lib/canis/core/widgets/rcombo.rb +210 -0
  116. data/lib/canis/core/widgets/rcontainer.rb +415 -0
  117. data/lib/canis/core/widgets/rlink.rb +30 -0
  118. data/lib/canis/core/widgets/rmenu.rb +970 -0
  119. data/lib/canis/core/widgets/rmenulink.rb +30 -0
  120. data/lib/canis/core/widgets/rmessagebox.rb +400 -0
  121. data/lib/canis/core/widgets/rprogress.rb +118 -0
  122. data/lib/canis/core/widgets/rtabbedpane.rb +631 -0
  123. data/lib/canis/core/widgets/rtabbedwindow.rb +70 -0
  124. data/lib/canis/core/widgets/rwidget.rb +3634 -0
  125. data/lib/canis/core/widgets/scrollbar.rb +147 -0
  126. data/lib/canis/core/widgets/statusline.rb +113 -0
  127. data/lib/canis/core/widgets/table.rb +1072 -0
  128. data/lib/canis/core/widgets/tabular.rb +264 -0
  129. data/lib/canis/core/widgets/textpad.rb +1674 -0
  130. data/lib/canis/core/widgets/tree.rb +690 -0
  131. data/lib/canis/core/widgets/tree/treecellrenderer.rb +150 -0
  132. data/lib/canis/core/widgets/tree/treemodel.rb +432 -0
  133. data/lib/canis/version.rb +3 -0
  134. metadata +229 -0
@@ -0,0 +1,48 @@
1
+ # Help for Textpads
2
+
3
+ (These were earlier called _TextViews_ )
4
+
5
+ Textpads allow display of multiline textual information and provide for
6
+ basic search, and vim-like navigation keys.
7
+
8
+ Some textpads are extended to display multiple buffers such as the help
9
+ screens. Textpads may display text that has ANSI escape codes such as
10
+ unix `man` pages, or the output of commands such as `ri` or `dooby` or
11
+ any other unix command that outputs colored output.
12
+
13
+ There is a second format that provides a lot more control than ANSI,
14
+ which is a `tmux` like format. This is used in the `status_line`.
15
+
16
+ Finally, there is a (new) help format, much like markdown (very
17
+ restricted, though). This page is formatted using the help format.
18
+
19
+ Following are some styles it provides:
20
+
21
+ - strong using __ as in __strong__. end
22
+ - strong using double asterisks that is ** : **strong text with spaces**. end
23
+ - emphasis using single asterisk * as in *emphasis*. end.
24
+ Emphasis *taking spaces in* between with single asterisk.
25
+ - emphasis using single _ as in _thisisemphsized_, will not take _
26
+ inside.
27
+ - code using tilde as in `do_process_now` or `@bgcolor` and `$fgcolor`.
28
+ - underline using bar as in |underlined|, this depends on TERM setting.
29
+ xterm shows underlines, most others do not.
30
+ - Link as in [[list]] (double brackets in source, but single in display).
31
+ - key using angular brackets as in <KEY_BACKSPACE>.
32
+
33
+ A block follows in white and bold (start with a single > on previous
34
+ line, and end with a single < char after block:
35
+ >
36
+ I think most of these need to be fixed so they don't start capturing
37
+ if surrounded by spaces. A lookahead and lookbehind is required other
38
+ wise they can wreak havoc.
39
+ <
40
+
41
+
42
+ Textpads do not provide row selection, but do allow mapping of the <ENTER>
43
+ key and provide the `word_under_cursor` to the calling block as part of
44
+ the action event. For instance, on this (or other) help pages, pressing
45
+ the <TAB> key will take the cursor to the next link (if there is one).
46
+ Pressing <ENTER> on the link will open the linked help file. This is the
47
+ link to the [[index]] or main help page.
48
+
@@ -0,0 +1,23 @@
1
+ # Help for Trees
2
+
3
+ Trees are multirow components that support tree-like information, with
4
+ leafs and branches (nodes) that contain more leafs or branches.
5
+
6
+ These are often used for directory-like structures.
7
+
8
+ Trees support all or most motion commands of [[Textpad]] in addition to
9
+ defining some additional ones such as:
10
+ >
11
+ - O Expand all children
12
+ - X Collapse all children
13
+ - o toggle expanded state
14
+ - p go to parent
15
+ - x collapse parent
16
+ <
17
+
18
+ Pressing <ENTER> expands or collapses a node (branch).
19
+ The `$row_selector` key by default is "v" which is used to trigger a
20
+ method, such as displaying details on some other list or view.
21
+
22
+ (This page needs to be completed)
23
+
Binary file
@@ -0,0 +1,83 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: action.rb
3
+ # Description: A common action class which can be used with buttons, popupmenu
4
+ # and anythign else that takes an action or command
5
+ # Author: jkepler http://github.com/mare-imbrium/canis/
6
+ # Date: been around since the beginning
7
+ # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
8
+ # Last update: 2014-04-28 14:53
9
+ # NOTE: I don't like the dependence on rwidget and EventHandler. Seems it needs
10
+ # that only for fire_handler and not sure if that's used. I've not bound :FIRE
11
+ # ever.
12
+ #
13
+ # Darn, do i really need to have dsl_accessors and property This is not a
14
+ # widget and there's no repaint. Do button's and popups really repaint
15
+ # themselves when a dsl_property is modified ?
16
+ # ----------------------------------------------------------------------------- #
17
+ #
18
+ #require 'canis/core/widgets/rwidget'
19
+ include Canis
20
+ module Canis
21
+ ## encapsulates behaviour allowing centralization
22
+ # == Example
23
+ # a = Action.new("&New Row") { commands }
24
+ # a.accelerator "Alt N"
25
+ # menu.add(a)
26
+ # b = Button.new form do
27
+ # action a
28
+ # ...
29
+ # end
30
+ class Action < Proc
31
+ # once again commented on 2014-04-28 - 14:37 to keep simple
32
+ #include EventHandler # removed 2012-01-3 maybe you can bind FIRE
33
+ #include ConfigSetup # removed 2012-01-3
34
+ # name used on button or menu
35
+ attr_accessor :name
36
+ attr_accessor :enabled
37
+ attr_accessor :tooltip_text
38
+ attr_accessor :help_text
39
+ attr_accessor :mnemonic
40
+ attr_accessor :accelerator
41
+
42
+ def initialize name, config={}, &block
43
+ super &block
44
+ @name = name
45
+ @name.freeze
46
+ @enabled = true
47
+ # removing dependency from config
48
+ #config_setup config # @config.each_pair { |k,v| variable_set(k,v) }
49
+ @config = config
50
+ keys = @config.keys
51
+ keys.each do |e|
52
+ variable_set(e, @config[e])
53
+ end
54
+ #@_events = [:FIRE]
55
+ end
56
+ def call *args
57
+ return unless @enabled
58
+ # seems to be here, if you've bound :FIRE no this, not on any widget
59
+ #fire_handler :FIRE, self
60
+ super
61
+ end
62
+
63
+
64
+ # the next 3 are to adapt this to CMenuitems
65
+ def hotkey
66
+ return @mnemonic if @mnemonic
67
+ ix = @name.index('&')
68
+ if ix
69
+ return @name[ix+1, 1].downcase
70
+ end
71
+ end
72
+ # to adapt this to CMenuitems
73
+ def label
74
+ @name.sub('&','')
75
+ end
76
+ # to adapt this to CMenuitems
77
+ def action
78
+ self
79
+ end
80
+
81
+ end # class
82
+ end # module
83
+
@@ -0,0 +1,49 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: actionmanager.rb
3
+ # Description: a class that manages actions for a widget
4
+ #
5
+ # Author: jkepler http://github.com/mare-imbrium/canis/
6
+ # Date: 2012-01-4
7
+ # License: Same as Ruby's License (http://www.ruby-lang.org/LICENSE.txt)
8
+ # Last update: ,,L
9
+ # ----------------------------------------------------------------------------- #
10
+ #
11
+ # Maintains actions for a widget
12
+ module Canis
13
+ class ActionManager
14
+ include Io
15
+ attr_reader :actions
16
+
17
+ def initialize #form, config={}, &block
18
+ @actions = []
19
+ #instance_eval &block if block_given?
20
+ end
21
+ def add_action act
22
+ @actions << act
23
+ end
24
+ def remove_action act
25
+ @actions.remove act
26
+ end
27
+ #
28
+ # insert an item at given position (index)
29
+ def insert_action pos, *val
30
+ @actions[pos] = val
31
+ end
32
+ #def create_menuitem *args
33
+ #PromptMenu.create_menuitem *args
34
+ #end
35
+
36
+ # popup the hist
37
+ #
38
+ def show_actions
39
+ return if @actions.empty?
40
+ list = @actions
41
+ menu = PromptMenu.new self do |m|
42
+ list.each { |e|
43
+ m.add *e
44
+ }
45
+ end
46
+ menu.display_new :title => 'Widget Menu (Press letter)'
47
+ end
48
+ end # class
49
+ end # mod RubyC
@@ -0,0 +1,179 @@
1
+ module Canis
2
+ module Utils
3
+ private
4
+ def _suspend clear=true
5
+ return unless block_given?
6
+ Ncurses.def_prog_mode
7
+ if clear
8
+ Ncurses.endwin
9
+ # NOTE: avoid false since screen remains half off
10
+ # too many issues
11
+ else
12
+ system "/bin/stty sane"
13
+ end
14
+ yield if block_given?
15
+ Ncurses.reset_prog_mode
16
+ if !clear
17
+ # Hope we don't screw your terminal up with this constantly.
18
+ Canis::stop_ncurses
19
+ Canis::start_ncurses
20
+ #@form.reset_all # not required
21
+ end
22
+ @form.repaint if @form
23
+ @window.wrefresh if @window
24
+ Ncurses::Panel.update_panels
25
+ end
26
+ #
27
+ # Suspends to shell so user can execute commands.
28
+ # Maybe not be able to get your prompt correctly.
29
+ #
30
+ public
31
+ def suspend
32
+ _suspend(false) do
33
+ system("tput cup 26 0")
34
+ system("tput ed")
35
+ system("echo Enter C-d to return to application")
36
+ system (ENV['PS1']='\s-\v\$ ') if ENV['SHELL']== '/bin/bash'
37
+ system(ENV['SHELL']);
38
+ end
39
+ end
40
+
41
+ #
42
+ # prompts user for unix command and displays output in viewer
43
+ #
44
+ def shell_output
45
+ $shell_history ||= []
46
+ cmd = get_string("Enter shell command:", :maxlen => 50) do |f|
47
+ require 'canis/core/include/rhistory'
48
+ f.extend(FieldHistory)
49
+ f.history($shell_history)
50
+ end
51
+ if cmd && !cmd.empty?
52
+ run_command cmd
53
+ $shell_history.push(cmd) unless $shell_history.include? cmd
54
+ end
55
+ end
56
+
57
+ #
58
+ # executes given command and displays in viewer
59
+ # @param [String] unix command, e.g., git -st
60
+ def run_command cmd
61
+ # http://whynotwiki.com/Ruby_/_Process_management#What_happens_to_standard_error_.28stderr.29.3F
62
+ require 'canis/core/util/viewer'
63
+ begin
64
+ res = `#{cmd} 2>&1`
65
+ rescue => ex
66
+ res = ex.to_s
67
+ res << ex.backtrace.join("\n")
68
+ end
69
+ res.gsub!("\t"," ")
70
+ # Earlier close key was ENTER but we need that to execute or fire
71
+ Canis::Viewer.view(res.split("\n"), :close_key => 'q', :title => "<q> to close, M-l M-h to scroll")
72
+ end
73
+ def shell_out command
74
+ w = @window || @form.window
75
+ w.hide
76
+ Ncurses.endwin
77
+ ret = system command
78
+ Ncurses.refresh
79
+ #Ncurses.curs_set 0 # why ?
80
+ w.show
81
+ return ret
82
+ end
83
+ end # utils
84
+ class PrefixCommand
85
+ attr_accessor :object
86
+ def initialize _symbol, calling, config={}, &block
87
+ @object = calling
88
+ @symbol = _symbol
89
+ @descriptions = {}
90
+ define_prefix_command _symbol
91
+ yield self if block_given?
92
+ end
93
+ def define_prefix_command _name, config={}
94
+ $rb_prefix_map ||= {}
95
+ #h = {}
96
+ #@map = h
97
+ _name = _name.to_sym unless _name.is_a? Symbol
98
+ # TODO it may already exist, so retrieve it
99
+ $rb_prefix_map[_name] ||= {}
100
+ @map = $rb_prefix_map[_name]
101
+ # create a variable by name _name
102
+ # create a method by same name to use
103
+ @object.instance_eval %{
104
+ def #{_name.to_s} *args
105
+ h = $rb_prefix_map["#{_name}".to_sym]
106
+ raise "No prefix_map named #{_name}, #{$rb_prefix_map.keys} " unless h
107
+ ch = @window.getchar
108
+ if ch
109
+ res = h[ch]
110
+ if res.is_a? Proc
111
+ res.call
112
+ else
113
+ send(res) if res
114
+ end
115
+ else
116
+ 0
117
+ end
118
+ end
119
+ }
120
+ return _name
121
+ end
122
+ def call
123
+ h = @map
124
+ ch = @object.window.getch # dicey.
125
+ $log.debug "XXX: CALLED #{ch} "
126
+ if ch
127
+ if ch == KEY_F1
128
+ text = ["Options are: "]
129
+ h.keys.each { |e| c = keycode_tos(e); text << " #{c} #{@descriptions[e]} " }
130
+ textdialog text, :title => " #{@symbol} key bindings "
131
+ return
132
+ end
133
+ res = h[ch]
134
+ if res.is_a? Proc
135
+ res.call
136
+ elsif res.is_a? Symbol
137
+ @object.send(res) if res
138
+ else
139
+ Ncurses.beep
140
+ @object.window.ungetch(ch)
141
+
142
+ :UNHANDLED
143
+ end
144
+ else
145
+ raise "got nothing"
146
+ end
147
+ end
148
+
149
+ # define a key within a prefix key map such as C-x
150
+ # Now that i am moving this from global, how will describe bindings get hold of the bindings
151
+ # and descriptions
152
+ def define_key _keycode, *args, &blk
153
+ _symbol = @symbol
154
+ h = $rb_prefix_map[_symbol]
155
+ raise ArgumentError, "No such keymap #{_symbol} defined. Use define_prefix_command." unless h
156
+ _keycode = _keycode[0].getbyte(0) if _keycode[0].class == String
157
+ arg = args.shift
158
+ if arg.is_a? String
159
+ desc = arg
160
+ arg = args.shift
161
+ elsif arg.is_a? Symbol
162
+ # its a symbol
163
+ desc = arg.to_s
164
+ elsif arg.nil?
165
+ desc = "unknown"
166
+ else
167
+ raise ArgumentError, "Don't know how to handle #{arg.class} in PrefixManager"
168
+ end
169
+ @descriptions[_keycode] = desc
170
+
171
+ if !block_given?
172
+ blk = arg
173
+ end
174
+ h[_keycode] = blk
175
+ end
176
+ alias :key :define_key
177
+ end
178
+ end # module RubyC
179
+ include Canis::Utils
@@ -0,0 +1,49 @@
1
+ # I am moving the common title and border printing stuff into
2
+ # a separate module.
3
+ module Canis
4
+ module BorderTitle
5
+ dsl_accessor :suppress_borders #to_print_borders
6
+ dsl_accessor :border_attrib, :border_color
7
+ dsl_accessor :title #set this on top
8
+ dsl_accessor :title_attrib #bold, reverse, normal
9
+
10
+ def bordertitle_init
11
+ @_bordertitle_init_called = true
12
+ @row_offset = @col_offset = 0 if @suppress_borders
13
+ @internal_width = 1 if @suppress_borders # the other programs have zero not 1 NOTE
14
+ end
15
+ # why the dash does it reduce height by one.
16
+ def print_borders
17
+ bordertitle_init unless @_bordertitle_init_called
18
+ raise ArgumentError, "Graphic not set" unless @graphic
19
+ raise "#{self} needs width" unless @width
20
+ raise "#{self} needs height" unless @height
21
+ width = @width
22
+ height = @height-1
23
+ window = @graphic
24
+ startcol = @col
25
+ startrow = @row
26
+ @color_pair = get_color($datacolor)
27
+ bordercolor = @border_color || @color_pair
28
+ borderatt = @border_attrib || Ncurses::A_NORMAL
29
+ window.print_border startrow, startcol, height, width, bordercolor, borderatt
30
+ print_title
31
+ end
32
+ def print_title
33
+ bordertitle_init unless @_bordertitle_init_called
34
+ return unless @title
35
+ raise "#{self} needs width" unless @width
36
+ # removed || since this can change after first invocation and should be recalculated.
37
+ @color_pair = get_color($datacolor)
38
+ #$log.debug " print_title #{@row}, #{@col}, #{@width} "
39
+ # check title.length and truncate if exceeds width
40
+ _title = @title
41
+ if @title.length > @width - 2
42
+ _title = @title[0..@width-2]
43
+ end
44
+ @graphic.printstring( @row, @col+(@width-_title.length)/2, _title, @color_pair, @title_attrib) unless @title.nil?
45
+ end
46
+
47
+ end
48
+ end
49
+ include BorderTitle
@@ -0,0 +1,100 @@
1
+ # ----------------------------------------------------------------------------- #
2
+ # File: canisparser.rb
3
+ # Description: creates an returns instances of parser objects
4
+ # Author: j kepler http://github.com/mare-imbrium/canis/
5
+ # Date: 2014-06-11 - 12:23
6
+ # License: MIT
7
+ # Last update: 2014-06-16 16:56
8
+ # ----------------------------------------------------------------------------- #
9
+ # canisparser.rb Copyright (C) 2012-2014 j kepler
10
+ module Canis
11
+
12
+ # Uses multiton pattern from http://blog.rubybestpractices.com/posts/gregory/059-issue-25-creational-design-patterns.html
13
+ # to create and returns cached instances of a text parser.
14
+ # Users will call the +[]+ method rather than the +new+ method.
15
+ # If users wish to declare their own custom parser, then the +map+ method is to be used.
16
+ #
17
+ # @example
18
+ #
19
+ # CanisParser[:tmux]
20
+ #
21
+ # To define your own parser:
22
+ #
23
+ # CanisParser.map( :custom => [ 'canis/core/include/customparser', 'Canis::CustomParser' ]
24
+ #
25
+ # and later at some point,
26
+ #
27
+ # CanisParser[:custom]
28
+ #
29
+ class CanisParser
30
+ class << self
31
+ # hash storing a filename and classname per content_type
32
+ def content_types
33
+ #@content_types ||= {}
34
+ unless @content_types
35
+ @content_types = {}
36
+ #map(:tmux => [ 'canis/core/util/defaultcolorparser', 'DefaultColorParser'])
37
+ #map(:ansi => [ 'canis/core/util/ansiparser', 'AnsiParser'] )
38
+ @content_types[:tmux] = [ 'canis/core/util/defaultcolorparser', 'DefaultColorParser']
39
+ @content_types[:ansi] = [ 'canis/core/util/ansiparser', 'AnsiParser']
40
+ end
41
+ return @content_types
42
+ end
43
+ # hash storing a parser instance per content_type
44
+ def instances
45
+ @instances ||= {}
46
+ end
47
+ # Used by user to define a new parser
48
+ # map( :tmux => ['filename', 'klassname'] )
49
+ def map(params)
50
+ content_types.update params
51
+ end
52
+
53
+ # Used by user to retrieve a parser instance, creating one if not present
54
+ # CanisParser[:tmux]
55
+ def [](name)
56
+ $log.debug " [] got #{name} "
57
+ raise "nil received by [] " unless name
58
+ instances[name] ||= new(content_types[name])
59
+ #instances[name] ||= create(content_types[name])
60
+ end
61
+ def create args
62
+ filename = args.first
63
+ klassname = args[1]
64
+ $log.debug " canisparser create got #{args} "
65
+ require filename
66
+ clazz = Object.const_get(klassname).new
67
+ $log.debug " created #{clazz.class} "
68
+ # clazz = 'Foo::Bar'.split('::').inject(Object) {|o,c| o.const_get c}
69
+ return clazz
70
+ end
71
+ end
72
+ ## WARNING - this creates a CanisParser class which we really can't use.
73
+ # So we need to delegate to the color parse we created.
74
+ # create and return a parser instance
75
+ # Canisparser.new filename, klassname
76
+ # Usually, *not* called by user, since this instance is not cached. Use +map+
77
+ # and then +[]+ instead for creating and cacheing.
78
+ def initialize *args
79
+ args = args.flatten
80
+ filename = args.first
81
+ klassname = args[1]
82
+ $log.debug " canisparser init got #{args} "
83
+ raise "Canisparser init got nil" unless filename
84
+ require filename
85
+ clazz = Object.const_get(klassname).new
86
+ # clazz = 'Foo::Bar'.split('::').inject(Object) {|o,c| o.const_get c}
87
+ #return clazz
88
+ @clazz = clazz
89
+ end
90
+ # delegate call to color parser
91
+ def parse_format s, *args, &block
92
+ @clazz.parse_format(s, *args, &block)
93
+ end
94
+ # delegate all call to color parser
95
+ def method_missing meth, *args, &block
96
+ #$log.debug " canisparser got method_missing for #{meth}, sending to #{@clazz.class} "
97
+ @clazz.send( meth, *args, &block)
98
+ end
99
+ end
100
+ end