cheap-impression-presenter 1.0.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.
- checksums.yaml +7 -0
- data/AUTHORS +1 -0
- data/INSTALL.md +13 -0
- data/LICENSE +674 -0
- data/README.md +71 -0
- data/Rakefile +26 -0
- data/chimp.gemspec +25 -0
- data/lib/ChimpParser-Grammar.rb +60 -0
- data/lib/ChimpParser.rb +215 -0
- data/lib/ChimpPlugin.rb +7 -0
- data/lib/output/screen.rb +248 -0
- data/lib/plugins/figlet.rb +23 -0
- data/lib/plugins/lnums.rb +14 -0
- data/lib/plugins/sixel.rb +33 -0
- data/tools/chimp +29 -0
- metadata +84 -0
data/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
CHIMP - Cheap IMpression Presenter
|
|
2
|
+
==================================
|
|
3
|
+
|
|
4
|
+
__ _____
|
|
5
|
+
___ / /___ / _ \ \ ___
|
|
6
|
+
/ __| |/ _ \ | | | | |__ \
|
|
7
|
+
| (__| | (_) | | |_| | |__) |
|
|
8
|
+
\___| |\_!!(_|_)!!__| |___/
|
|
9
|
+
\_\ /_/
|
|
10
|
+
|
|
11
|
+
Make a cheap impression. Present via terminal.
|
|
12
|
+
|
|
13
|
+
```gem install chimp```
|
|
14
|
+
|
|
15
|
+
It has a simple syntax:
|
|
16
|
+
|
|
17
|
+
#what: the title of presentation
|
|
18
|
+
|
|
19
|
+
--- splits slides
|
|
20
|
+
|
|
21
|
+
+++ slides parts to appear
|
|
22
|
+
|
|
23
|
+
!!Bold Text!!
|
|
24
|
+
``Red Text``
|
|
25
|
+
%%Blue Text%%
|
|
26
|
+
|
|
27
|
+
Everything else is in plugins. The following plugins are existing for now:
|
|
28
|
+
|
|
29
|
+
* Sixel: display graphics in the terminal: `` ```sixel name.png``.
|
|
30
|
+
* Figlet: display fancy ascii text: `` ```figlet FANCY_TEXT``.
|
|
31
|
+
* Line Numbers: display line numbers beforce any text.
|
|
32
|
+
~~~text
|
|
33
|
+
```figlet
|
|
34
|
+
Line
|
|
35
|
+
Line
|
|
36
|
+
Line
|
|
37
|
+
```
|
|
38
|
+
~~~
|
|
39
|
+
|
|
40
|
+
During presenting you can use the usual button for navigating. In addition, you
|
|
41
|
+
can use ``q`` to quit the presentation, and ``r`` to refresh the screen.
|
|
42
|
+
|
|
43
|
+
Check out the examples.
|
|
44
|
+
|
|
45
|
+
History & Thanks
|
|
46
|
+
================
|
|
47
|
+
|
|
48
|
+
Amy Hoy allowed me to use the logo for CHIMP all the way back in 2009. The
|
|
49
|
+
CHIMP was written as an icebreaker for the curucamp, which was a ruby
|
|
50
|
+
un-conference in 2009 in Vienna. We had fun, and many cool people from the
|
|
51
|
+
community attended.
|
|
52
|
+
|
|
53
|
+
I am still using the CHIMP for scientifc presentations, and as sixel terminals
|
|
54
|
+
finally are more common, I tried to polish it up (2025) and make it available
|
|
55
|
+
for easy consumption. Maybe you like it. I use it because I can create
|
|
56
|
+
presentations faster than in PP, KN, other programs. Most of the work goes
|
|
57
|
+
into graphics anyway, which I create with dedicated tools.
|
|
58
|
+
|
|
59
|
+
Drop me a note if you want to be a contributor, or send me merge request if you
|
|
60
|
+
have created some plugins. Creating plugins is very simple :-)
|
|
61
|
+
|
|
62
|
+
Missing Features
|
|
63
|
+
================
|
|
64
|
+
|
|
65
|
+
Presenting is nice. A PDF output mode would be useful. To send the presentation
|
|
66
|
+
to people in one file.
|
|
67
|
+
|
|
68
|
+
LICENSE
|
|
69
|
+
=======
|
|
70
|
+
|
|
71
|
+
GPL 3.0 or later.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rubygems/package_task'
|
|
3
|
+
|
|
4
|
+
spec = eval(File.read('chimp.gemspec'))
|
|
5
|
+
Gem::PackageTask.new(spec) do |pkg|
|
|
6
|
+
pkg.need_zip = true
|
|
7
|
+
pkg.need_tar = true
|
|
8
|
+
puts `ls -al pkg/*`
|
|
9
|
+
`rm pkg/* -rf`
|
|
10
|
+
`ln -sf #{pkg.name}.gem pkg/chimp.gem`
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
task :push => :gem do |r|
|
|
14
|
+
`gem push pkg/chimp.gem`
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
task :install => :gem do |r|
|
|
18
|
+
`gem install pkg/chimp.gem`
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# task :release => :gem do |r|
|
|
22
|
+
# GIT_COMMITTER_DATE="$(git show develop --format=%aD | head -1)" \
|
|
23
|
+
# git tag -a "v1.7.0" develop -m "tag v1.7.0" \
|
|
24
|
+
# && git push --tags origin develop \
|
|
25
|
+
# && git --no-pager tag --list --format='%(refname) %(taggerdate)'
|
|
26
|
+
# end
|
data/chimp.gemspec
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
Gem::Specification.new do |s|
|
|
2
|
+
s.name = "cheap-impression-presenter"
|
|
3
|
+
s.version = "1.0.0"
|
|
4
|
+
s.platform = Gem::Platform::RUBY
|
|
5
|
+
s.license = "GPL-3.0-or-later"
|
|
6
|
+
s.summary = "CHIMP - Make a cheap impression. Present via terminal."
|
|
7
|
+
|
|
8
|
+
s.description = "see https://github.com/etm/chimp"
|
|
9
|
+
|
|
10
|
+
s.files = Dir['{example/*.txt,example/*.png,example/*.svg,tools/**/*,lib/**/*,}'] + %w(LICENSE INSTALL.md Rakefile chimp.gemspec AUTHORS)
|
|
11
|
+
s.require_path = 'lib'
|
|
12
|
+
s.extra_rdoc_files = ['README.md','INSTALL.md']
|
|
13
|
+
s.bindir = 'tools'
|
|
14
|
+
s.executables = ['chimp']
|
|
15
|
+
|
|
16
|
+
s.required_ruby_version = '>=2.7.0'
|
|
17
|
+
|
|
18
|
+
s.authors = ['Juergen eTM Mangler']
|
|
19
|
+
|
|
20
|
+
s.email = 'juergen.mangler@gmail.com'
|
|
21
|
+
s.homepage = 'https://github.com/etm/chimp'
|
|
22
|
+
|
|
23
|
+
s.add_runtime_dependency 'tty-screen', '~> 0.8'
|
|
24
|
+
s.add_runtime_dependency 'pastel', '~> 0.8'
|
|
25
|
+
end
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
require_relative 'ChimpParser'
|
|
2
|
+
|
|
3
|
+
module Chimp
|
|
4
|
+
class Parser
|
|
5
|
+
|
|
6
|
+
class SimpleGrammar < Grammar
|
|
7
|
+
#### Patterns ####
|
|
8
|
+
#### Name of pattern has to be the first parameter to pattern ####
|
|
9
|
+
#### According to the names the methods are selected ####
|
|
10
|
+
|
|
11
|
+
P_SLIDES = Pattern.new("P_SLIDES", /---+.*?(\z|\n)|\A/, /^(?=---+)|\z/)
|
|
12
|
+
P_WHAT = Pattern.new("P_WHAT", /^#\s*what:\s*/, /[\t ]*(\n|\z)/)
|
|
13
|
+
P_INCREMENTAL = Pattern.new("P_INCREMENTAL", /\+\+\++.*?(\z|\n)|\A/, /^(?=\+\+\++)|\z/)
|
|
14
|
+
P_RANGE = Pattern.new("P_RANGE", /^```([a-z0-9_]+,)*[a-z0-9_]+[\t ]*/, /^```[\t ]*(\n|\z)/)
|
|
15
|
+
P_INCLUDE = Pattern.new("P_INCLUDE", /^```([a-z0-9_]+,)*[a-z0-9_]+[\t ]+/, /[\t ]*(\n|\z)/)
|
|
16
|
+
P_CENTER = Pattern.new("P_CENTER", /^~~/, /[\t ]*(\n|\z)/)
|
|
17
|
+
P_STRONG = Pattern.new("P_STRONG", /!!/, /!!/)
|
|
18
|
+
P_RED = Pattern.new("P_RED", /''/, /''/)
|
|
19
|
+
P_BLUE = Pattern.new("P_BLUE", /%%/, /%%/)
|
|
20
|
+
P_STRONGRED = Pattern.new("P_STRONGRED", /(!!''|''!!)/, /(''!!|!!'')/)
|
|
21
|
+
P_STRONGBLUE = Pattern.new("P_STRONGBLUE", /(!!%%|%%!!)/, /(%%!!|!!%%)/)
|
|
22
|
+
|
|
23
|
+
#### Grammar ####
|
|
24
|
+
#### ROOT must exist and holds the main first level patterns ####
|
|
25
|
+
#### G + patternname is selected to look up nested patterns ####
|
|
26
|
+
#### If G + patternname not exists, [] is assumend ####
|
|
27
|
+
|
|
28
|
+
ROOT = [ P_WHAT, P_SLIDES ]
|
|
29
|
+
GP_SLIDES = [ P_INCREMENTAL ]
|
|
30
|
+
GP_INCREMENTAL = [ P_CENTER, P_RANGE, P_INCLUDE, P_STRONGRED, P_STRONGBLUE, P_STRONG, P_RED, P_BLUE ]
|
|
31
|
+
|
|
32
|
+
### Optional functions called when a pattern occurs (m + patternname) ####
|
|
33
|
+
def mP_CENTER(ts,ti,te)
|
|
34
|
+
@tree.last.data = ti.length
|
|
35
|
+
ti
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def mP_INCLUDE(ts,ti,te)
|
|
39
|
+
@tree.last.data = {}
|
|
40
|
+
@tree.last.data[:name] = ts[3..-1].strip.split(',')[0]
|
|
41
|
+
@tree.last.data[:parameters] = ts[3..-1].strip.split(',')[1..-1]
|
|
42
|
+
@tree.last.data[:additional] = @parameters
|
|
43
|
+
@tree.last.data[:what] = ti.lstrip
|
|
44
|
+
''
|
|
45
|
+
end
|
|
46
|
+
def mP_RANGE(ts,ti,te)
|
|
47
|
+
@tree.last.data = {}
|
|
48
|
+
@tree.last.data[:name] = ts[3..-1].strip.split(',')[0]
|
|
49
|
+
@tree.last.data[:parameters] = ts[3..-1].strip.split(',')[1..-1]
|
|
50
|
+
@tree.last.data[:what] = ti.lstrip
|
|
51
|
+
''
|
|
52
|
+
end
|
|
53
|
+
def mP_WHAT(ts,ti,te)
|
|
54
|
+
@tree.last.data = ti
|
|
55
|
+
''
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
data/lib/ChimpParser.rb
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
require 'strscan'
|
|
2
|
+
require 'pp'
|
|
3
|
+
|
|
4
|
+
module Chimp
|
|
5
|
+
class Parser
|
|
6
|
+
class OpenTag
|
|
7
|
+
attr_reader :ttype, :level
|
|
8
|
+
attr_accessor :data, :close, :userdata
|
|
9
|
+
def initialize(ttype,level)
|
|
10
|
+
@ttype = ttype
|
|
11
|
+
@data = nil
|
|
12
|
+
@close = -1
|
|
13
|
+
@userdata = nil
|
|
14
|
+
@level = level
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
class CloseTag
|
|
18
|
+
attr_reader :ttype, :open, :position_in_markup, :level
|
|
19
|
+
def initialize(ttype,open,position_in_markup,level)
|
|
20
|
+
@ttype = ttype
|
|
21
|
+
@open = open
|
|
22
|
+
@position_in_markup = position_in_markup
|
|
23
|
+
@level = level
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
class TagEvent < Exception; end
|
|
28
|
+
class TagSkipEvent < Exception; end
|
|
29
|
+
class TagMoveEvent < Exception; end
|
|
30
|
+
class TagContentSkipEvent < Exception; end
|
|
31
|
+
|
|
32
|
+
class Output
|
|
33
|
+
def finish_prepare
|
|
34
|
+
end
|
|
35
|
+
def finish_output
|
|
36
|
+
""
|
|
37
|
+
end
|
|
38
|
+
def string(data)
|
|
39
|
+
data
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
class Grammar
|
|
44
|
+
attr_reader :tree # a list which pretends to be a tree :-)
|
|
45
|
+
|
|
46
|
+
class Pattern
|
|
47
|
+
attr_reader :ptype, :pstart, :pend, :bol
|
|
48
|
+
def initialize(ptype, pstart, pend, bol=false)
|
|
49
|
+
@ptype = ptype
|
|
50
|
+
@pstart = pstart
|
|
51
|
+
@pend = pend
|
|
52
|
+
@bol = bol
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def initialize
|
|
57
|
+
@tree = []
|
|
58
|
+
@parameters = {}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def Grammar.parse(text,params = {})
|
|
62
|
+
new.parse(text,params)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def parse(text,params = {})
|
|
66
|
+
@parameters = params
|
|
67
|
+
gparse(text,self.class::constants.include?(:ROOT) ? self.class::ROOT : [])
|
|
68
|
+
self
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def inspect
|
|
72
|
+
out = ""; indent = ""
|
|
73
|
+
@tree.each do |c|
|
|
74
|
+
indent = indent[0..-3] if c.class == CloseTag
|
|
75
|
+
out << indent + c.inspect + "\n"
|
|
76
|
+
indent << " " if c.class == OpenTag
|
|
77
|
+
end
|
|
78
|
+
out
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def output(output)
|
|
82
|
+
out = ''; i = 0
|
|
83
|
+
while @tree.length > i
|
|
84
|
+
c = @tree[i]
|
|
85
|
+
begin
|
|
86
|
+
met = case
|
|
87
|
+
when c.class == String
|
|
88
|
+
data = c
|
|
89
|
+
output.method("string")
|
|
90
|
+
when c.class == OpenTag
|
|
91
|
+
data = c.data
|
|
92
|
+
output.method("mO" + c.ttype)
|
|
93
|
+
when c.class == CloseTag
|
|
94
|
+
data = @tree[c.open].data
|
|
95
|
+
output.method("mC" + c.ttype)
|
|
96
|
+
end
|
|
97
|
+
out << case met.arity
|
|
98
|
+
when 0; met.call
|
|
99
|
+
when 1; met.call(data)
|
|
100
|
+
when 2; met.call(c,@tree)
|
|
101
|
+
when 3; met.call(c,@tree,i)
|
|
102
|
+
when 4; met.call(c,@tree,i,data)
|
|
103
|
+
else
|
|
104
|
+
""
|
|
105
|
+
end.to_s
|
|
106
|
+
|
|
107
|
+
i += 1
|
|
108
|
+
rescue NameError => e
|
|
109
|
+
i += 1
|
|
110
|
+
rescue TagSkipEvent
|
|
111
|
+
i = c.close + 1 if c.class == OpenTag
|
|
112
|
+
rescue TagContentSkipEvent
|
|
113
|
+
i = c.close if c.class == OpenTag
|
|
114
|
+
rescue TagMoveEvent => e
|
|
115
|
+
i = e.message.to_i
|
|
116
|
+
ensure
|
|
117
|
+
begin
|
|
118
|
+
unless @tree.length > i
|
|
119
|
+
met = output.method("finish_output")
|
|
120
|
+
out << case met.arity
|
|
121
|
+
when 0; met.call
|
|
122
|
+
when 1; met.call(@tree)
|
|
123
|
+
else
|
|
124
|
+
""
|
|
125
|
+
end.to_s
|
|
126
|
+
end
|
|
127
|
+
rescue TagMoveEvent => e
|
|
128
|
+
i = e.message.to_i
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
out
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def prepare(output)
|
|
136
|
+
@tree.each_with_index do |c,i|
|
|
137
|
+
begin
|
|
138
|
+
if c.class == OpenTag
|
|
139
|
+
met = output.method("mP" + c.ttype)
|
|
140
|
+
case met.arity
|
|
141
|
+
when 0; met.call
|
|
142
|
+
when 1; met.call(c.data)
|
|
143
|
+
when 2; met.call(c,@tree)
|
|
144
|
+
when 3; met.call(c,@tree,i)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
rescue NameError
|
|
148
|
+
rescue TagSkipEvent
|
|
149
|
+
rescue TagContentSkipEvent
|
|
150
|
+
rescue TagMoveEvent
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
output.method("finish_prepare").call
|
|
154
|
+
self
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def gparse(text,grammar,position_in_markup=0,level=0)
|
|
158
|
+
return if text.nil?
|
|
159
|
+
s = StringScanner.new(text)
|
|
160
|
+
while !s.eos?
|
|
161
|
+
success = false
|
|
162
|
+
grammar.each do |pat|
|
|
163
|
+
if s.match?(pat.pstart)
|
|
164
|
+
pos = s.pos
|
|
165
|
+
bol = (pos == 0) ? true : s.string[pos-1] == "\n"
|
|
166
|
+
ts = s.scan(pat.pstart)
|
|
167
|
+
te = if s.eos?
|
|
168
|
+
"" =~ pat.pend ? "" : nil
|
|
169
|
+
else
|
|
170
|
+
(pat.bol && !bol) ? nil : s.scan_until(pat.pend)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
if te.nil?
|
|
174
|
+
s.pos = pos
|
|
175
|
+
else
|
|
176
|
+
ti = te.sub(pat.pend,"")
|
|
177
|
+
te = te[ti.length..-1]
|
|
178
|
+
@tree << ot = OpenTag.new(pat.ptype,level)
|
|
179
|
+
tpos = @tree.length-1
|
|
180
|
+
inner = begin
|
|
181
|
+
self.method("m" + pat.ptype).call(ts,ti,te)
|
|
182
|
+
rescue NameError
|
|
183
|
+
ti
|
|
184
|
+
rescue TagEvent
|
|
185
|
+
@tree.pop
|
|
186
|
+
s.pos = pos
|
|
187
|
+
next
|
|
188
|
+
rescue TagSkipEvent
|
|
189
|
+
@tree.pop
|
|
190
|
+
success = true
|
|
191
|
+
next
|
|
192
|
+
end
|
|
193
|
+
gparse(inner,self.class::constants.include?(("G" + pat.ptype).to_sym) ? self.class::const_get(("G" + pat.ptype).to_sym) : [],position_in_markup+pos+ts.length,level+1)
|
|
194
|
+
@tree << CloseTag.new(pat.ptype,tpos,position_in_markup+s.pos,level)
|
|
195
|
+
ot.close = @tree.length-1
|
|
196
|
+
success = true
|
|
197
|
+
break
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
unless success
|
|
202
|
+
if @tree.last.class == String
|
|
203
|
+
@tree.last << s.getch
|
|
204
|
+
else
|
|
205
|
+
@tree << s.getch
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
private :gparse
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
end
|
|
215
|
+
end
|
data/lib/ChimpPlugin.rb
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
require 'pastel'
|
|
2
|
+
require 'tty-screen'
|
|
3
|
+
require 'io/console'
|
|
4
|
+
|
|
5
|
+
module Window #{{{
|
|
6
|
+
class WinchError < Exception; end
|
|
7
|
+
def self::init()
|
|
8
|
+
self::clear
|
|
9
|
+
$stdout << "\e[?25l"
|
|
10
|
+
$stdout.flush
|
|
11
|
+
Signal.trap("WINCH") do
|
|
12
|
+
raise WinchError, 'nope'
|
|
13
|
+
end
|
|
14
|
+
nil
|
|
15
|
+
end
|
|
16
|
+
def self::finish()
|
|
17
|
+
self::clear
|
|
18
|
+
self::set_pos 0, 0
|
|
19
|
+
$stdout << "\e[?25h"
|
|
20
|
+
$stdout.flush
|
|
21
|
+
nil
|
|
22
|
+
end
|
|
23
|
+
def self::getch()
|
|
24
|
+
loop do
|
|
25
|
+
case $stdin.getch
|
|
26
|
+
when 'r' then return :refresh
|
|
27
|
+
when 'q' then return :exit
|
|
28
|
+
when "\r" then return :enter
|
|
29
|
+
when "\e"
|
|
30
|
+
case $stdin.getch
|
|
31
|
+
when '['
|
|
32
|
+
case $stdin.getch
|
|
33
|
+
when 'A' then return :previous
|
|
34
|
+
when 'B' then return :next
|
|
35
|
+
when 'C' then return :next
|
|
36
|
+
when 'D' then return :previous
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
def self::lines()
|
|
43
|
+
TTY::Screen.lines
|
|
44
|
+
end
|
|
45
|
+
def self::columns()
|
|
46
|
+
TTY::Screen.columns
|
|
47
|
+
end
|
|
48
|
+
def self::clear()
|
|
49
|
+
$stdout << "\e[2J"
|
|
50
|
+
$stdout.flush
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
def self::set_pos(x,y)
|
|
54
|
+
$stdout << "\e[#{y};#{x}H"
|
|
55
|
+
$stdout.flush
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
def self::print(a)
|
|
59
|
+
$stdout.write a
|
|
60
|
+
$stdout.flush
|
|
61
|
+
end
|
|
62
|
+
def self::get_pos
|
|
63
|
+
res = ''
|
|
64
|
+
$stdin.raw do |stdin|
|
|
65
|
+
$stdout << "\e[6n"
|
|
66
|
+
$stdout.flush
|
|
67
|
+
while (c = $stdin.getc) != 'R'
|
|
68
|
+
res << c if c
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
m = res.match /(?<column>\d+);(?<row>\d+)/
|
|
72
|
+
[ Integer(m[:row]), Integer(m[:column]) ]
|
|
73
|
+
rescue WinchErrror
|
|
74
|
+
[0,0]
|
|
75
|
+
end
|
|
76
|
+
end #}}}
|
|
77
|
+
|
|
78
|
+
module Chimp
|
|
79
|
+
class Parser
|
|
80
|
+
|
|
81
|
+
class Screen < Output
|
|
82
|
+
#### Optional functions called when a tree is tranformed to output ####
|
|
83
|
+
#### mO + patternname for opening tags ####
|
|
84
|
+
#### mC + patternname for closing tags ####
|
|
85
|
+
|
|
86
|
+
def initialize() #{{{
|
|
87
|
+
@scounter = @ccounter = 0
|
|
88
|
+
@what = ''
|
|
89
|
+
@last = 0
|
|
90
|
+
@skip = -1
|
|
91
|
+
|
|
92
|
+
@format = Pastel.new
|
|
93
|
+
@screen = Window
|
|
94
|
+
|
|
95
|
+
@screen.init
|
|
96
|
+
end #}}}
|
|
97
|
+
|
|
98
|
+
def finish_output #{{{
|
|
99
|
+
@screen.set_pos 0, @screen.lines
|
|
100
|
+
@screen.print ' ' * (@screen.columns - 5)
|
|
101
|
+
@screen.set_pos 0, @screen.lines
|
|
102
|
+
end #}}}
|
|
103
|
+
|
|
104
|
+
def mPP_WHAT(data)
|
|
105
|
+
@what = data
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def mPP_SLIDES(c,tree)
|
|
109
|
+
#{{{
|
|
110
|
+
@scounter += 1
|
|
111
|
+
@ccounter += 1
|
|
112
|
+
c.userdata = @ccounter
|
|
113
|
+
#}}}
|
|
114
|
+
end
|
|
115
|
+
def mOP_SLIDES(c,tree)
|
|
116
|
+
#{{{
|
|
117
|
+
@screen.clear
|
|
118
|
+
lines = @screen.lines
|
|
119
|
+
columns = @screen.columns
|
|
120
|
+
### print mark
|
|
121
|
+
@screen.set_pos columns-1, 30
|
|
122
|
+
@screen.print "\e[1;37m^\e[0m"
|
|
123
|
+
### print footer
|
|
124
|
+
@screen.set_pos 0, lines-1
|
|
125
|
+
@screen.print "-"*columns
|
|
126
|
+
@screen.set_pos 0, lines
|
|
127
|
+
@screen.print @what
|
|
128
|
+
num = "#{c.userdata}/#{@scounter}"
|
|
129
|
+
@screen.set_pos columns-num.length, lines
|
|
130
|
+
@screen.print num
|
|
131
|
+
@screen.set_pos 0, 0
|
|
132
|
+
#}}}
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def mPP_INCREMENTAL(c,tree,i)
|
|
136
|
+
@last = c.close
|
|
137
|
+
end
|
|
138
|
+
def mOP_INCREMENTAL(c,tree)
|
|
139
|
+
x, y = @screen.get_pos
|
|
140
|
+
c.userdata = { :x => x, :y => y }
|
|
141
|
+
end
|
|
142
|
+
def mCP_INCREMENTAL(c,tree,i)
|
|
143
|
+
return if @skip > i
|
|
144
|
+
@skip = -1
|
|
145
|
+
begin
|
|
146
|
+
if @last == i
|
|
147
|
+
lines = @screen.lines
|
|
148
|
+
columns = @screen.columns
|
|
149
|
+
@screen.set_pos 0, lines
|
|
150
|
+
@screen.print "Press 'q' to finish making a cheap impression..."
|
|
151
|
+
end
|
|
152
|
+
begin
|
|
153
|
+
ch = @screen.getch
|
|
154
|
+
rescue Window::WinchError
|
|
155
|
+
ch = :refresh
|
|
156
|
+
end
|
|
157
|
+
end while @last == i && ![:previous, :exit, :refresh].include?(ch)
|
|
158
|
+
case ch
|
|
159
|
+
when :previous
|
|
160
|
+
#{{{
|
|
161
|
+
pos = c.open-1
|
|
162
|
+
tag = tree[pos]
|
|
163
|
+
if tag.ttype == "P_SLIDES"
|
|
164
|
+
if pos == 0
|
|
165
|
+
raise TagMoveEvent, pos
|
|
166
|
+
else
|
|
167
|
+
raise TagMoveEvent, tree[pos-1].open
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
if tag.ttype == "P_INCREMENTAL"
|
|
171
|
+
pos = tag.open
|
|
172
|
+
tag = tree[pos]
|
|
173
|
+
columns = @screen.columns
|
|
174
|
+
#### get current position
|
|
175
|
+
x, y = @screen.get_pos
|
|
176
|
+
#### how many spaces needed
|
|
177
|
+
howmuch = ((y - tag.userdata[:y] + 1) * columns) - (columns - x) - tag.userdata[:x]
|
|
178
|
+
@screen.set_pos tag.userdata[:x], tag.userdata[:y]
|
|
179
|
+
@screen.print x.to_s + ',' + y.to_s
|
|
180
|
+
@screen.print ' ' * howmuch
|
|
181
|
+
@screen.set_pos tag.userdata[:x], tag.userdata[:y]
|
|
182
|
+
####
|
|
183
|
+
raise TagMoveEvent, pos
|
|
184
|
+
end
|
|
185
|
+
#}}}
|
|
186
|
+
when :refresh
|
|
187
|
+
#{{{
|
|
188
|
+
(c.open-1).downto(0) do |b|
|
|
189
|
+
if tree[b].class == OpenTag && tree[b].ttype == "P_SLIDES"
|
|
190
|
+
@skip = i
|
|
191
|
+
raise TagMoveEvent, b
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
#}}}
|
|
195
|
+
when :exit
|
|
196
|
+
@screen.finish
|
|
197
|
+
exit
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
def mOP_INCLUDE(data)
|
|
201
|
+
require File::dirname(__FILE__) + "/../plugins/#{data[:name]}.rb"
|
|
202
|
+
eval('Chimp::Plugin::' + data[:name].upcase).new.process(data[:what],data[:parameters],@screen,data[:additional])
|
|
203
|
+
end
|
|
204
|
+
def mOP_RANGE(data)
|
|
205
|
+
require File::dirname(__FILE__) + "/../plugins/#{data[:name]}.rb"
|
|
206
|
+
eval('Chimp::Plugin::' + data[:name].upcase).new.process(data[:what],data[:parameters],@screen,data[:additional])
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def mOP_STRONG(data); @screen.print "\e[1m"; end
|
|
210
|
+
def mCP_STRONG(data); @screen.print "\e[0m"; end
|
|
211
|
+
def mOP_RED(data); @screen.print "\e[0;31m"; end
|
|
212
|
+
def mCP_RED(data); @screen.print "\e[0m"; end
|
|
213
|
+
def mOP_BLUE(data); @screen.print "\e[0;34m"; end
|
|
214
|
+
def mCP_BLUE(data); @screen.print "\e[0m"; end
|
|
215
|
+
def mOP_STRONGRED(data); @screen.print "\e[1;31m"; end
|
|
216
|
+
def mCP_STRONGRED(data); @screen.print "\e[0m"; end
|
|
217
|
+
def mOP_STRONGBLUE(data); @screen.print "\e[1;34m"; end
|
|
218
|
+
def mCP_STRONGBLUE(data); @screen.print "\e[0m"; end
|
|
219
|
+
|
|
220
|
+
def mOP_CENTER(data)
|
|
221
|
+
len = @screen.columns
|
|
222
|
+
if len-data > 0
|
|
223
|
+
@screen.print ' ' * ((len - data) / 2)
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
def mCP_CENTER(data)
|
|
227
|
+
@screen.print "\n"
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def string(data)
|
|
231
|
+
@screen.print(data)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def p(what)
|
|
235
|
+
#{{{
|
|
236
|
+
lines = @screen.lines
|
|
237
|
+
@screen.set_pos 0, lines-1
|
|
238
|
+
@screen.print what.inspect
|
|
239
|
+
x, y = @screen.get_pos
|
|
240
|
+
@screen.set_pos x, y
|
|
241
|
+
@screen.getch
|
|
242
|
+
#}}}
|
|
243
|
+
end
|
|
244
|
+
private :p
|
|
245
|
+
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Chimp
|
|
2
|
+
module Plugin
|
|
3
|
+
class FIGLET < Base
|
|
4
|
+
def process(what,parameters,screen,additional)
|
|
5
|
+
if parameters.include? 'right'
|
|
6
|
+
pos = screen.get_pos
|
|
7
|
+
len = screen.columns
|
|
8
|
+
`figlet #{what}`.each_line do |l|
|
|
9
|
+
screen.print " " * (len-l.length+1) + l
|
|
10
|
+
end
|
|
11
|
+
screen.set_pos *pos
|
|
12
|
+
elsif parameters.include? 'center'
|
|
13
|
+
len = screen.columns
|
|
14
|
+
`figlet #{what}`.each_line do |l|
|
|
15
|
+
screen.print " " * ((len-l.length+1)/2) + l
|
|
16
|
+
end
|
|
17
|
+
else
|
|
18
|
+
screen.print `figlet #{what}`
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|