present 0.0.2

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.
@@ -0,0 +1,4 @@
1
+ == 0.0.1 / 2008-08-31
2
+
3
+ * initial release
4
+
data/README ADDED
@@ -0,0 +1,41 @@
1
+
2
+ = present
3
+
4
+ Presentation tool for terminal.
5
+
6
+ == Description
7
+
8
+ This program is for terminal addicts.
9
+ You can present your slide by using your favorite terminal.
10
+
11
+ == Installation
12
+
13
+ === Archive Installation
14
+
15
+ rake install
16
+
17
+ === Gem Installation
18
+
19
+ gem install present
20
+
21
+
22
+ == Features/Problems
23
+
24
+
25
+ == Synopsis
26
+
27
+ present [options] file [duration] [page]
28
+
29
+ `file` specifies presentation file. there is an example in the sample/ dir.
30
+
31
+ `duration` specifies expected duration in minute. This is optional. The
32
+ default value is 5 min.
33
+
34
+ `page` specifies the page number which will be started from. This is
35
+ optional. The default value is 1.
36
+
37
+ == Copyright
38
+
39
+ Author:: Genki Takiuchi <genki@s21g.com>
40
+ Copyright:: Copyright (c) 2008 Genki Takiuchi
41
+ License::
@@ -0,0 +1,149 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'rake/contrib/sshpublisher'
10
+ require 'fileutils'
11
+
12
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
13
+ require 'present'
14
+ include FileUtils
15
+
16
+ NAME = "present"
17
+ AUTHOR = "Genki Takiuchi"
18
+ EMAIL = "genki@s21g.com"
19
+ DESCRIPTION = "Presentation tool for terminal."
20
+ RUBYFORGE_PROJECT = "cocktail-party"
21
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
22
+ BIN_FILES = %w(present)
23
+
24
+ VERS = Present::VERSION
25
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
26
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
27
+ RDOC_OPTS = [
28
+ '--title', "#{NAME} documentation",
29
+ "--charset", "utf-8",
30
+ "--opname", "index.html",
31
+ "--line-numbers",
32
+ "--main", "README",
33
+ "--inline-source",
34
+ ]
35
+
36
+ task :default => [:test]
37
+ task :package => [:clean]
38
+
39
+ Rake::TestTask.new("test") do |t|
40
+ t.libs << "test"
41
+ t.pattern = "test/**/*_test.rb"
42
+ t.verbose = true
43
+ end
44
+
45
+ spec = Gem::Specification.new do |s|
46
+ s.name = NAME
47
+ s.version = VERS
48
+ s.platform = Gem::Platform::RUBY
49
+ s.has_rdoc = true
50
+ s.extra_rdoc_files = ["README", "ChangeLog"]
51
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
52
+ s.summary = DESCRIPTION
53
+ s.description = DESCRIPTION
54
+ s.author = AUTHOR
55
+ s.email = EMAIL
56
+ s.homepage = HOMEPATH
57
+ s.executables = BIN_FILES
58
+ s.rubyforge_project = RUBYFORGE_PROJECT
59
+ s.bindir = "bin"
60
+ s.require_path = "lib"
61
+ #s.autorequire = ""
62
+ s.test_files = Dir["test/*_test.rb"]
63
+
64
+ #s.add_dependency('activesupport', '>=1.3.1')
65
+ s.add_dependency('ncurses')
66
+ s.add_dependency('text')
67
+ s.add_dependency('escape')
68
+ #s.required_ruby_version = '>= 1.8.2'
69
+
70
+ s.files = %w(README ChangeLog Rakefile) +
71
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
72
+ Dir.glob("ext/**/*.{h,c,rb}") +
73
+ Dir.glob("examples/**/*.rb") +
74
+ Dir.glob("tools/*.rb") +
75
+ Dir.glob("rails/*.rb")
76
+
77
+ s.extensions = FileList["ext/**/extconf.rb"].to_a
78
+ end
79
+
80
+ Rake::GemPackageTask.new(spec) do |p|
81
+ p.need_tar = true
82
+ p.gem_spec = spec
83
+ end
84
+
85
+ task :install do
86
+ name = "#{NAME}-#{VERS}.gem"
87
+ sh %{rake package}
88
+ sh %{sudo gem install pkg/#{name}}
89
+ end
90
+
91
+ task :uninstall => [:clean] do
92
+ sh %{sudo gem uninstall #{NAME}}
93
+ end
94
+
95
+
96
+ Rake::RDocTask.new do |rdoc|
97
+ rdoc.rdoc_dir = 'html'
98
+ rdoc.options += RDOC_OPTS
99
+ rdoc.template = "resh"
100
+ #rdoc.template = "#{ENV['template']}.rb" if ENV['template']
101
+ if ENV['DOC_FILES']
102
+ rdoc.rdoc_files.include(ENV['DOC_FILES'].split(/,\s*/))
103
+ else
104
+ rdoc.rdoc_files.include('README', 'ChangeLog')
105
+ rdoc.rdoc_files.include('lib/**/*.rb')
106
+ rdoc.rdoc_files.include('ext/**/*.c')
107
+ end
108
+ end
109
+
110
+ desc "Publish to RubyForge"
111
+ task :rubyforge => [:rdoc, :package] do
112
+ require 'rubyforge'
113
+ Rake::RubyForgePublisher.new(RUBYFORGE_PROJECT, 'takiuchi').upload
114
+ end
115
+
116
+ desc 'Package and upload the release to rubyforge.'
117
+ task :release => [:clean, :package] do |t|
118
+ v = ENV["VERSION"] or abort "Must supply VERSION=x.y.z"
119
+ abort "Versions don't match #{v} vs #{VERS}" unless v == VERS
120
+ pkg = "pkg/#{NAME}-#{VERS}"
121
+
122
+ require 'rubyforge'
123
+ rf = RubyForge.new.configure
124
+ puts "Logging in"
125
+ rf.login
126
+
127
+ c = rf.userconfig
128
+ # c["release_notes"] = description if description
129
+ # c["release_changes"] = changes if changes
130
+ c["preformatted"] = true
131
+
132
+ files = [
133
+ "#{pkg}.tgz",
134
+ "#{pkg}.gem"
135
+ ].compact
136
+
137
+ puts "Releasing #{NAME} v. #{VERS}"
138
+ rf.add_release RUBYFORGE_PROJECT, NAME, VERS, *files
139
+ end
140
+
141
+ desc 'Show information about the gem.'
142
+ task :debug_gem do
143
+ puts spec.to_ruby
144
+ end
145
+
146
+ desc 'Update gem spec'
147
+ task :gemspec do
148
+ open("#{NAME}.gemspec", 'w').write spec.to_ruby
149
+ end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ $:.unshift File.join(File.dirname(__FILE__), '../lib')
3
+ require 'optparse'
4
+ require 'present'
5
+
6
+ Version = Present::VERSION
7
+ opt = OptionParser.new
8
+ opt.banner = "Usage: present [options] file [duration] [page]"
9
+ opt.on_tail('-v', '--version', 'Show version.'){puts opt.ver; exit}
10
+ opt.order!(ARGV)
11
+
12
+ Present.new(*ARGV).start
@@ -0,0 +1,227 @@
1
+ require 'rubygems'
2
+ require 'ncurses'
3
+ require 'text'
4
+ require 'escape'
5
+ require 'nkf'
6
+ require 'present/page'
7
+
8
+ class Present
9
+ VERSION = '0.0.2'
10
+ TIOCGWINSZ = 0x5413
11
+
12
+ def initialize(path, timer = 5, page = 1)
13
+ @source = path
14
+ @script = NKF.nkf('-e', open(path).read)
15
+ @stanzas = @script.split(/\n\n+/)
16
+ str = [0, 0, 0, 0].pack("SSSS")
17
+ if $stdin.ioctl(TIOCGWINSZ, str) >= 0 then
18
+ @rows, @cols, xpixels, ypixels = str.unpack("SSSS")
19
+ else
20
+ @rows, @cols = 13, 40
21
+ end
22
+ @pages = @stanzas.map{|stanza| Page.new(stanza, self)}
23
+ @page = page.to_i - 1
24
+ @timer = timer.to_i * 60
25
+ end
26
+
27
+ def start
28
+ Ncurses.initscr
29
+ Ncurses.raw
30
+ Ncurses.cbreak
31
+ Ncurses.noecho
32
+ Ncurses.start_color
33
+ Ncurses.refresh
34
+ @win = Ncurses::WINDOW.new @rows - 1, @cols, 0, 0
35
+ @win.keypad true
36
+ Ncurses.nodelay @win, 1
37
+ @status = Ncurses::WINDOW.new 1, @cols + 1, @rows - 1, 0
38
+ @status.color_set 1, nil
39
+ @start = Time.now
40
+ @colors = {}
41
+ register_pair Ncurses::COLOR_BLACK, Ncurses::COLOR_WHITE
42
+ while page = @pages[@page]
43
+ @row = @rows / 4
44
+ paginate
45
+ page.start
46
+
47
+ begin
48
+ input = @win.getch
49
+ case input
50
+ when 27, ?q; return # exit
51
+ when ?:; scan_command
52
+ when ?k, ?h, 259, 260; @page = [@page - 1, 0].max
53
+ when ?<; @page = 0
54
+ when ?>; @page = @pages.size - 1
55
+ when ?j, ?l, 10, 13, 32, 258, 261
56
+ @page = [@page + 1, @pages.size - 1].min
57
+ when ?r; reload
58
+ else
59
+ sleep 0.1
60
+ paginate
61
+ end
62
+ end while input == -1
63
+ end
64
+ ensure
65
+ Ncurses.endwin
66
+ end
67
+
68
+ def figlet(font, cols, text)
69
+ font = 'term' if mb?(text)
70
+ cmd = Escape.shell_command(['figlet', '-f', "#{font}.flf", '-w', cols.to_s])
71
+ IO.popen(cmd, 'r+') do |io|
72
+ io.write text
73
+ io.close_write
74
+ io.read
75
+ end
76
+ end
77
+
78
+ def reload
79
+ Ncurses.endwin
80
+ exec "#{$0} #{@source} #{@timer/60} #{@page + 1}"
81
+ end
82
+
83
+ def center(text, options = {})
84
+ return if text.empty?
85
+ font = options[:font] || 'mini'
86
+ text = figlet font, @cols, text
87
+ rows, cols = sizeof(text)
88
+ top = (@rows - rows)/2
89
+ left = (@cols - cols)/2
90
+ @win.attron Ncurses::A_BOLD
91
+ text = text.split("\n").each_with_index do |line, i|
92
+ mvwprintw top + i, left, line
93
+ end
94
+ @win.attroff Ncurses::A_BOLD
95
+ end
96
+
97
+ def caption(text, options = {})
98
+ return if text.empty?
99
+ font = options[:font] || 'mini'
100
+ text = figlet font, @cols, text
101
+ rows, cols = sizeof(text)
102
+ top = (@rows - rows - 2)/2
103
+ left = (@cols - cols)/2
104
+ @win.attron Ncurses::A_BOLD
105
+ text = text.split("\n").each_with_index do |line, i|
106
+ mvwprintw top + i, left, line
107
+ end
108
+ @win.attroff Ncurses::A_BOLD
109
+ @row = top + rows + 1
110
+ end
111
+
112
+ def line(text, options = {})
113
+ return @row += 1 if text.empty?
114
+ font = options[:font] || 'term'
115
+ @row = options[:row] if options[:row]
116
+ @row += options[:padding] if options[:padding]
117
+ text = figlet font, @cols, text
118
+ rows, cols = sizeof(text)
119
+ left = options[:left] || (@cols - cols)/2
120
+ left = @cols - cols - options[:right] if right = options[:right]
121
+ @win.attron Ncurses::A_BOLD if options[:bold]
122
+ text = text.split("\n").each_with_index do |line, i|
123
+ mvwprintw @row + i, left, line
124
+ end
125
+ @win.attroff Ncurses::A_BOLD if options[:bold]
126
+ @row += rows + options[:margin].to_i
127
+ end
128
+
129
+ def color(front, back = Ncurses::COLOR_BLACK)
130
+ if front =~ /^\d+$/
131
+ pair_id = front.to_i
132
+ elsif front.is_a?(String)
133
+ front = eval "Ncurses::COLOR_#{front.upcase}"
134
+ end
135
+ if back.is_a?(String)
136
+ back = eval "Ncurses::COLOR_#{back.upcase}"
137
+ end
138
+ pair_id ||= register_pair front, back
139
+ @win.color_set pair_id, nil
140
+ end
141
+
142
+ def wait(time)
143
+ if time == 0.0
144
+ case input = @status.getch
145
+ when ?j, 32, 10, 13, 27
146
+ else Ncurses.ungetch input
147
+ end
148
+ else
149
+ sleep time
150
+ end
151
+ end
152
+
153
+ def sizeof(text)
154
+ lines = text.split("\n")
155
+ cols = lines.map{|line| line.length}.max
156
+ [lines.size, cols]
157
+ end
158
+
159
+ def mb?(text)
160
+ text.split(//u).size != text.length
161
+ end
162
+
163
+ def paginate
164
+ @status.mvwprintw 0, 0, " " * @cols
165
+ pages = @pages.size
166
+ k = pages.to_s.length
167
+ j = 2 + k*2
168
+ @status.mvwprintw 0, 0, "%#{k}d/%#{k}d|" % [@page + 1, pages]
169
+ cols = @cols - 6 - j
170
+ q = cols % pages
171
+ r = q > 0 ? pages / q : 0
172
+ w = [cols / pages, 1].max
173
+ w += 1 if r > 0 && @page % r == r - 1
174
+ x = (@page*cols + pages/2) / pages
175
+ @status.mvwprintw 0, x + j, "*" * w
176
+ time = Time.now.to_i - @start.to_i
177
+ min, sec = time / 60, time % 60
178
+ @status.mvwprintw 0, cols + j, "|%02d:%02d" % [min, sec]
179
+ @status.refresh
180
+ end
181
+
182
+ def scan_command
183
+ @status.mvwprintw 0, 0, " "*@cols
184
+ @status.mvwprintw 0, 0, ':'
185
+ buf = []
186
+ begin
187
+ case input = @status.getch
188
+ when 10, 13; break
189
+ when 27; return nil
190
+ when 127; buf.pop
191
+ else buf << input
192
+ end
193
+ @status.mvwprintw 0, 1, " "*(@cols - 1)
194
+ @status.mvwprintw 0, 1, buf.pack('C*')
195
+ @status.refresh
196
+ end while input > 0
197
+ command, *args = buf.pack('C*').split(/\s+/)
198
+ command = "do_#{command}"
199
+ send command, *args rescue nil if respond_to? command
200
+ end
201
+
202
+ def register_pair(front, back)
203
+ key = [front, back]
204
+ return @colors[key] if @colors[key]
205
+ pair_id = @colors.size + 1
206
+ Ncurses.init_pair pair_id, front, back
207
+ @colors[key] = pair_id
208
+ end
209
+
210
+ def method_missing(method, *args, &block)
211
+ @win.send method, *args, &block
212
+ end
213
+
214
+ def do_go(page)
215
+ @page = [[0, page.to_i - 1].max, @pages.size - 1].min
216
+ end
217
+
218
+ def do_sh
219
+ Ncurses.endwin
220
+ system ENV['SHELL'] || 'sh'
221
+ Ncurses.resetty
222
+ end
223
+
224
+ def do_q
225
+ exit
226
+ end
227
+ end
@@ -0,0 +1,55 @@
1
+ class Present
2
+ class Page
3
+ def initialize(stanza, screen)
4
+ @lines = stanza.split("\n")
5
+ @screen = screen
6
+ end
7
+
8
+ def start
9
+ @screen.clear
10
+ stack = [['cap', '']]
11
+ execute_command = proc do
12
+ command, text = stack.pop
13
+ dispatch_command command, text
14
+ @screen.refresh
15
+ end
16
+ @lines.each do |line|
17
+ text, command = line.split(/\s+/, 2).reverse
18
+ if command
19
+ execute_command.call
20
+ stack.push [command, text]
21
+ else
22
+ stack.last[1] += "\n#{text}"
23
+ end
24
+ end
25
+ execute_command.call
26
+ end
27
+
28
+ private
29
+ def dispatch_command(command, text)
30
+ case command
31
+ when '='
32
+ @screen.caption text
33
+ when '-'
34
+ @screen.line text
35
+ when '<'
36
+ @screen.line text, :left => 1, :padding => 1
37
+ when '>'
38
+ @screen.line text, :right => 1, :padding => 1
39
+ when /(\++)(\-?)/
40
+ @screen.line '- ' + text, :left => $1.length*2 - 1,
41
+ :padding => $2.empty? ? 1 : 0
42
+ when '*'
43
+ @screen.line text, :row => 1, :bold => true
44
+ when '.'
45
+ @screen.center text.empty? ? "fin" : text, :font => 'mini'
46
+ when '#'
47
+ @screen.center text, :font => 'mini'
48
+ when '%'
49
+ @screen.color *text.split(/\s+/)
50
+ when ','
51
+ @screen.wait text.to_f
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ require "test/unit"
4
+ class PresentTest < Test::Unit::TestCase
5
+ end
@@ -0,0 +1,3 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/present'
3
+
metadata ADDED
@@ -0,0 +1,102 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: present
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Genki Takiuchi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-08-31 00:00:00 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: ncurses
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: text
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: escape
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ description: Presentation tool for terminal.
46
+ email: genki@s21g.com
47
+ executables:
48
+ - present
49
+ extensions: []
50
+
51
+ extra_rdoc_files:
52
+ - README
53
+ - ChangeLog
54
+ files:
55
+ - README
56
+ - ChangeLog
57
+ - Rakefile
58
+ - bin/present
59
+ - test/test_helper.rb
60
+ - test/present_test.rb
61
+ - lib/present
62
+ - lib/present/page.rb
63
+ - lib/present.rb
64
+ has_rdoc: true
65
+ homepage: http://cocktail-party.rubyforge.org
66
+ post_install_message:
67
+ rdoc_options:
68
+ - --title
69
+ - present documentation
70
+ - --charset
71
+ - utf-8
72
+ - --opname
73
+ - index.html
74
+ - --line-numbers
75
+ - --main
76
+ - README
77
+ - --inline-source
78
+ - --exclude
79
+ - ^(examples|extras)/
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ version:
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: "0"
93
+ version:
94
+ requirements: []
95
+
96
+ rubyforge_project: cocktail-party
97
+ rubygems_version: 1.2.0
98
+ signing_key:
99
+ specification_version: 2
100
+ summary: Presentation tool for terminal.
101
+ test_files:
102
+ - test/present_test.rb