wee-pm 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README +60 -0
- data/TODO +9 -0
- data/bin/wee-pm +114 -0
- data/bin/wee-pm-pdf +49 -0
- data/lib/wee-pm/colorize.rb +475 -0
- data/lib/wee-pm/colorize_filter.rb +22 -0
- data/lib/wee-pm/converter.rb +104 -0
- data/lib/wee-pm/presentation.rb +152 -0
- data/lib/wee-pm/presentation_maker.rb +395 -0
- data/lib/wee-pm/slideshtml.rb +204 -0
- data/lib/wee-pm/utils.rb +40 -0
- data/wee-pm.gemspec +25 -0
- metadata +71 -0
data/README
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
= Presentation Maker
|
2
|
+
|
3
|
+
Copyright (c) 2005, 2007 by Michael Neumann (mneumann@ntecs.de).
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
== Dependencies
|
7
|
+
|
8
|
+
* ruby 1.8.x
|
9
|
+
* Wee 0.10.0 (gem install wee)
|
10
|
+
* vim (for colorizing sources)
|
11
|
+
* html2ps (for creating the Postscript output)
|
12
|
+
* ps2pdf (for creating the PDF output)
|
13
|
+
|
14
|
+
== Start
|
15
|
+
|
16
|
+
cd directory-where-all-your-presentation-related-files-reside
|
17
|
+
wee-pm presentation-file
|
18
|
+
|
19
|
+
Then point your browser to: http://localhost:2000/
|
20
|
+
|
21
|
+
== Navigation
|
22
|
+
|
23
|
+
* Page-Up/-Down: Previous/Next slide/overlay.
|
24
|
+
|
25
|
+
* Key 's': toggle slide/overlay mode.
|
26
|
+
|
27
|
+
* Key 'e': enter edit mode.
|
28
|
+
|
29
|
+
* Next overlay/slide: Click with the mouse on the slide-title.
|
30
|
+
|
31
|
+
* Switch to edit-mode: Position the mouse into the top-left corner of the
|
32
|
+
frame, you'll notice a hover-effect. Then click.
|
33
|
+
|
34
|
+
== Presentation file format
|
35
|
+
|
36
|
+
Pure rdoc! Each level-one heading ("=") generates a slide.
|
37
|
+
|
38
|
+
== RDoc extensions
|
39
|
+
|
40
|
+
To colorize sourcecode, use a verbatim block like this:
|
41
|
+
|
42
|
+
!!colorize:ruby
|
43
|
+
def method_a
|
44
|
+
end
|
45
|
+
|
46
|
+
Note that you'll need +vim+ to be installed on your system.
|
47
|
+
|
48
|
+
== Generating PDF
|
49
|
+
|
50
|
+
wee-pm-pdf presentation-file > pdf-file
|
51
|
+
|
52
|
+
You can tweak the generated PDF file, by editing bin/wee-pm-pdf. For
|
53
|
+
example, if you want to have a PDF that is not intended for printing and
|
54
|
+
as such could ommit the URLs to be shown as text, set SHOW_URL to false
|
55
|
+
in bin/wee-pm-pdf.
|
56
|
+
|
57
|
+
If you need Postscript, then have a look at bin/wee-pm-pdf, and remove
|
58
|
+
the "| ps2pdf - -" part in the IO.popen line. But you generally don't
|
59
|
+
want this, as the PDF output allows easier navigating, and the links are
|
60
|
+
clickable (if you use AcroRead).
|
data/TODO
ADDED
data/bin/wee-pm
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rubygems'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'wee'
|
9
|
+
require 'wee/pageless'
|
10
|
+
require 'wee/utils/helper'
|
11
|
+
require 'wee/utils/cache'
|
12
|
+
require 'wee/utils/autoreload'
|
13
|
+
require 'wee/adaptors/webrick'
|
14
|
+
begin
|
15
|
+
require 'wee-pm/presentation_maker'
|
16
|
+
rescue LoadError
|
17
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib')
|
18
|
+
end
|
19
|
+
require 'wee-pm/presentation_maker'
|
20
|
+
|
21
|
+
# Overrides for Wee 0.10.0 to get be able to mount
|
22
|
+
# an application as "/".
|
23
|
+
class Wee::Request
|
24
|
+
def initialize(app_path, path, headers, fields, cookies)
|
25
|
+
unless app_path == '/'
|
26
|
+
raise ArgumentError, app_path if app_path[-1] == ?/
|
27
|
+
end
|
28
|
+
@app_path, @path, @headers, @cookies = app_path, path, headers, cookies
|
29
|
+
parse_fields(fields)
|
30
|
+
parse_path
|
31
|
+
end
|
32
|
+
|
33
|
+
def build_url(hash={})
|
34
|
+
default = {
|
35
|
+
:request_handler_id => self.request_handler_id,
|
36
|
+
:page_id => self.page_id,
|
37
|
+
:info => self.info
|
38
|
+
}
|
39
|
+
hash = default.update(hash)
|
40
|
+
|
41
|
+
request_handler_id = hash[:request_handler_id]
|
42
|
+
page_id = hash[:page_id]
|
43
|
+
callback_id = hash[:callback_id]
|
44
|
+
info = hash[:info]
|
45
|
+
|
46
|
+
raise ArgumentError if request_handler_id.nil? and not page_id.nil?
|
47
|
+
if not pageless?
|
48
|
+
raise ArgumentError if page_id.nil? and not callback_id.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
# build request path, e.g. /___/req-id/page-id
|
52
|
+
req_path = make_request_path(request_handler_id, page_id)
|
53
|
+
|
54
|
+
# build the whole url
|
55
|
+
if @app_path == '/'
|
56
|
+
url = ""
|
57
|
+
if info
|
58
|
+
url << '/'
|
59
|
+
url << info
|
60
|
+
end
|
61
|
+
url << req_path
|
62
|
+
|
63
|
+
url << '/' if info.nil? and req_path.empty?
|
64
|
+
|
65
|
+
url << ('?' + callback_id) if callback_id
|
66
|
+
else
|
67
|
+
url = ""
|
68
|
+
url << @app_path
|
69
|
+
|
70
|
+
raise if url[-1] == ?/ # sanity check
|
71
|
+
|
72
|
+
if info
|
73
|
+
url << '/'
|
74
|
+
url << info
|
75
|
+
end
|
76
|
+
url << req_path
|
77
|
+
|
78
|
+
url << '/' if info.nil? and req_path.empty?
|
79
|
+
|
80
|
+
url << ('?' + callback_id) if callback_id
|
81
|
+
end
|
82
|
+
|
83
|
+
return url
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class DispatchHandler < WEBrick::HTTPServlet::AbstractServlet
|
88
|
+
def initialize(server, application, file_dir)
|
89
|
+
super(server)
|
90
|
+
@app_handler = Wee::WEBrickAdaptor.new(server, '/', application, Wee::PagelessRequest)
|
91
|
+
@file_handler = WEBrick::HTTPServlet::FileHandler.new(server, file_dir)
|
92
|
+
end
|
93
|
+
|
94
|
+
def do_GET(req, res)
|
95
|
+
(req.path == '/' ? @app_handler : @file_handler).do_GET(req, res)
|
96
|
+
end
|
97
|
+
|
98
|
+
def do_POST(req, res)
|
99
|
+
(req.path == '/' ? @app_handler : @file_handler).do_POST(req, res)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def run(presentation_file)
|
104
|
+
comp = proc { PresentationMaker.new(presentation_file) };
|
105
|
+
def comp.new; call end
|
106
|
+
app = Wee::Utils.app_for(comp,
|
107
|
+
:session => Wee::PagelessSession,
|
108
|
+
:application => Wee::PagelessApplication)
|
109
|
+
Wee::WEBrickAdaptor.
|
110
|
+
mount('/', DispatchHandler, app, '.').
|
111
|
+
start
|
112
|
+
end
|
113
|
+
|
114
|
+
run(ARGV[0])
|
data/bin/wee-pm-pdf
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rubygems'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'wee-pm/presentation'
|
10
|
+
rescue LoadError
|
11
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '../lib')
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'wee-pm/presentation'
|
15
|
+
require 'wee-pm/converter'
|
16
|
+
require 'tempfile'
|
17
|
+
|
18
|
+
SHOW_URL = true
|
19
|
+
|
20
|
+
pres = Presentation.from_string(File.read(ARGV[0]))
|
21
|
+
|
22
|
+
rc = Tempfile.new('html2psrc')
|
23
|
+
rc << <<EOS
|
24
|
+
@html2ps { showurl: #{ SHOW_URL ? 1 : 0 }; seq-number: 1; }
|
25
|
+
titlepage { content: "<div align=center><h1><big>$[title]</big></h1><h3>$[author]</h3><h4>$[email]</h4></div>" }
|
26
|
+
EOS
|
27
|
+
rc.close(false)
|
28
|
+
|
29
|
+
io = IO.popen("/usr/bin/perl /usr/local/bin/html2ps --toc hb -f #{ rc.path } --titlepage --hyphenate --underline --web b --colour --frame --landscape | ps2pdf - -", 'w+')
|
30
|
+
io << "<html><head><title>#{ pres.title }</title>\n"
|
31
|
+
io << %[<meta name="Title" content="#{pres.title}"/>]
|
32
|
+
io << %[<meta name="Author" content="#{pres.author}"/>]
|
33
|
+
io << %[<meta name="Email" content="#{pres.email}"/>]
|
34
|
+
io << "</head><body>"
|
35
|
+
io << pres.style || ""
|
36
|
+
pres.slides.each do |slide|
|
37
|
+
slide.converter = PsHtmlConverter
|
38
|
+
io << slide.style || ""
|
39
|
+
io << "<h1>#{ slide.title }</h1>\n"
|
40
|
+
slide.render_on(io, slide.number_of_overlays)
|
41
|
+
unless slide.annotations.strip.empty?
|
42
|
+
io << "<hr>"
|
43
|
+
slide.render_annotations_on(io)
|
44
|
+
end
|
45
|
+
io << "<!--NewPage-->\n"
|
46
|
+
end
|
47
|
+
io << "</body></html>\n"
|
48
|
+
io.close_write
|
49
|
+
puts io.read
|
@@ -0,0 +1,475 @@
|
|
1
|
+
#!/usr/local/bin/ruby
|
2
|
+
|
3
|
+
# Colorize Source Code using Vim
|
4
|
+
#
|
5
|
+
# by Michael Neumann (mneumann@ntecs.de)
|
6
|
+
#
|
7
|
+
# Freeware.
|
8
|
+
|
9
|
+
# Use --terminal=xterm-color for coloring output when called by a CGI script (Apache).
|
10
|
+
#
|
11
|
+
# TODO:
|
12
|
+
# - Make sure caching works with --headers and --mode option.
|
13
|
+
# Currently it's assumed that caching is used with the same options
|
14
|
+
# all the time except --lang or --strip-ws
|
15
|
+
# - remove too old entries in the cache?
|
16
|
+
|
17
|
+
require "getopts"
|
18
|
+
require "tempfile"
|
19
|
+
require "md5"
|
20
|
+
|
21
|
+
def usage
|
22
|
+
STDERR.puts "USAGE: #{ $0 }
|
23
|
+
[--mode=gui|text] (default: text)
|
24
|
+
[--lang=vim_lang] (default: __auto__)
|
25
|
+
[--strip-ws]
|
26
|
+
[--cache [--cache-prefix=prefix]] (default: cache-prefix=/tmp/_colorize)
|
27
|
+
[--headers]
|
28
|
+
[--terminal=...] (default: __none__; which terminal to use for vim)
|
29
|
+
[input-file [output-file]] (default: stdin stdout)
|
30
|
+
[--help]"
|
31
|
+
exit 1
|
32
|
+
end
|
33
|
+
|
34
|
+
# remove leading and trailing empty lines
|
35
|
+
def strip_ws(str)
|
36
|
+
# find first non-empty line
|
37
|
+
first_non_empty = 0
|
38
|
+
str.each_with_index do |line, i|
|
39
|
+
if line.strip != ""
|
40
|
+
first_non_empty = i
|
41
|
+
break
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# find last non-empty line
|
46
|
+
last_non_empty = 0
|
47
|
+
str.each_with_index do |line, i|
|
48
|
+
if line.strip != ""
|
49
|
+
last_non_empty = i
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
return str.to_a[first_non_empty..last_non_empty].join("")
|
54
|
+
end
|
55
|
+
|
56
|
+
def gen_cache_name(content, lang)
|
57
|
+
md5 = MD5.new(content)
|
58
|
+
$OPT["cache-prefix"] + ".#{ md5 }.#{ lang }"
|
59
|
+
end
|
60
|
+
|
61
|
+
getopts(nil, "mode:text", "lang:__auto__", "headers", "terminal:xterm",
|
62
|
+
"strip-ws", "cache", "cache-prefix:/tmp/_colorize", "help")
|
63
|
+
|
64
|
+
if ARGV.size > 2 or $OPT["help"]
|
65
|
+
usage
|
66
|
+
else
|
67
|
+
|
68
|
+
# generate temporary 2html_michael.vim file
|
69
|
+
f = Tempfile.new("2html_michael.vim")
|
70
|
+
f << DATA.read
|
71
|
+
f.close(false)
|
72
|
+
|
73
|
+
input_file, output_file = ARGV
|
74
|
+
|
75
|
+
if input_file.nil?
|
76
|
+
# read input from STDIN
|
77
|
+
inp = Tempfile.new("input")
|
78
|
+
inp << STDIN.read
|
79
|
+
inp.close(false)
|
80
|
+
input_file = inp.path
|
81
|
+
end
|
82
|
+
|
83
|
+
if output_file.nil?
|
84
|
+
of = Tempfile.new("colorize")
|
85
|
+
of.close(false)
|
86
|
+
output_file = of.path
|
87
|
+
else
|
88
|
+
of = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
vim =
|
92
|
+
case $OPT["mode"]
|
93
|
+
when "gui"
|
94
|
+
'/usr/local/bin/gvim -f'
|
95
|
+
when "text"
|
96
|
+
if $OPT["terminal"] == "__none__" or $OPT["terminal"].empty?
|
97
|
+
'/usr/local/bin/vim'
|
98
|
+
else
|
99
|
+
"/usr/local/bin/vim -T #{ $OPT['terminal'] }"
|
100
|
+
end
|
101
|
+
else
|
102
|
+
raise
|
103
|
+
end
|
104
|
+
|
105
|
+
lang =
|
106
|
+
case $OPT["lang"]
|
107
|
+
when "__auto__"
|
108
|
+
""
|
109
|
+
else
|
110
|
+
%{ +"setf #{ $OPT['lang'] }" }
|
111
|
+
end
|
112
|
+
|
113
|
+
headers =
|
114
|
+
if $OPT["headers"] then
|
115
|
+
""
|
116
|
+
else
|
117
|
+
%{ +"let html_no_header=''" }
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
vim_command = %{#{ vim } +"syn on" +"set nonumber" #{ headers } #{ lang } +"set runtimepath=#{ File.dirname f.path } " +"run #{ File.basename f.path }" +"w! #{ output_file }" +"q!" +"q!" #{ input_file } > /dev/null 2> /dev/null}
|
124
|
+
|
125
|
+
if $OPT["cache"] then
|
126
|
+
# TODO: doesn't work together with --headers
|
127
|
+
cn = gen_cache_name(File.readlines(input_file).to_s, $OPT["lang"])
|
128
|
+
if File.exists? cn
|
129
|
+
# result is in cache
|
130
|
+
`cp #{ cn } #{ output_file }`
|
131
|
+
else
|
132
|
+
# generate we have to generate the cache file
|
133
|
+
`#{ vim_command }`
|
134
|
+
`cp #{ output_file } #{ cn }`
|
135
|
+
end
|
136
|
+
else
|
137
|
+
# no caching
|
138
|
+
`#{ vim_command }`
|
139
|
+
end
|
140
|
+
|
141
|
+
if of != nil
|
142
|
+
str = File.readlines(output_file).to_s
|
143
|
+
STDOUT <<
|
144
|
+
if $OPT["strip-ws"]
|
145
|
+
strip_ws(str)
|
146
|
+
else
|
147
|
+
str
|
148
|
+
end
|
149
|
+
else
|
150
|
+
if $OPT["strip-ws"]
|
151
|
+
str = File.readlines(output_file).to_s
|
152
|
+
File.open(output_file, "w+") {|f| f << strip_ws(str) }
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
|
158
|
+
__END__
|
159
|
+
" Vim syntax support file
|
160
|
+
" Maintainer: Bram Moolenaar <Bram@vim.org>
|
161
|
+
" Last Change: 2002 Jul 10
|
162
|
+
" (modified by David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>)
|
163
|
+
" (modified by Michael Neumann <mneumann@ntecs.de>)
|
164
|
+
|
165
|
+
" Transform a file into HTML, using the current syntax highlighting.
|
166
|
+
|
167
|
+
" Number lines when explicitely requested or when `number' is set
|
168
|
+
if exists("html_number_lines")
|
169
|
+
let s:numblines = html_number_lines
|
170
|
+
else
|
171
|
+
let s:numblines = &number
|
172
|
+
endif
|
173
|
+
|
174
|
+
" When not in gui we can only guess the colors.
|
175
|
+
if has("gui_running")
|
176
|
+
let s:whatterm = "gui"
|
177
|
+
else
|
178
|
+
let s:whatterm = "cterm"
|
179
|
+
if &t_Co == 99999 " to active this section, use == 8
|
180
|
+
let s:cterm_color0 = "#808080"
|
181
|
+
let s:cterm_color1 = "#ff6060"
|
182
|
+
let s:cterm_color2 = "#00ff00"
|
183
|
+
let s:cterm_color3 = "#ffff00"
|
184
|
+
let s:cterm_color4 = "#8080ff"
|
185
|
+
let s:cterm_color5 = "#ff40ff"
|
186
|
+
let s:cterm_color6 = "#00ffff"
|
187
|
+
let s:cterm_color7 = "#ffffff"
|
188
|
+
else
|
189
|
+
let s:cterm_color0 = "#000000"
|
190
|
+
let s:cterm_color1 = "#c00000"
|
191
|
+
let s:cterm_color2 = "#008000"
|
192
|
+
let s:cterm_color3 = "#804000"
|
193
|
+
let s:cterm_color4 = "#0000c0"
|
194
|
+
let s:cterm_color5 = "#c000c0"
|
195
|
+
let s:cterm_color6 = "#008080"
|
196
|
+
let s:cterm_color7 = "#c0c0c0"
|
197
|
+
let s:cterm_color8 = "#808080"
|
198
|
+
let s:cterm_color9 = "#ff6060"
|
199
|
+
let s:cterm_color10 = "#00ff00"
|
200
|
+
let s:cterm_color11 = "#ffff00"
|
201
|
+
let s:cterm_color12 = "#8080ff"
|
202
|
+
let s:cterm_color13 = "#ff40ff"
|
203
|
+
let s:cterm_color14 = "#00ffff"
|
204
|
+
let s:cterm_color15 = "#ffffff"
|
205
|
+
endif
|
206
|
+
endif
|
207
|
+
|
208
|
+
" Return good color specification: in GUI no transformation is done, in
|
209
|
+
" terminal return RGB values of known colors and empty string on unknown
|
210
|
+
if s:whatterm == "gui"
|
211
|
+
function! s:HtmlColor(color)
|
212
|
+
return a:color
|
213
|
+
endfun
|
214
|
+
else
|
215
|
+
function! s:HtmlColor(color)
|
216
|
+
if exists("s:cterm_color" . a:color)
|
217
|
+
execute "return s:cterm_color" . a:color
|
218
|
+
else
|
219
|
+
return ""
|
220
|
+
endif
|
221
|
+
endfun
|
222
|
+
endif
|
223
|
+
|
224
|
+
if !exists("html_use_css")
|
225
|
+
" Return opening HTML tag for given highlight id
|
226
|
+
function! s:HtmlOpening(id)
|
227
|
+
let a = ""
|
228
|
+
if synIDattr(a:id, "inverse")
|
229
|
+
" For inverse, we always must set both colors (and exchange them)
|
230
|
+
let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
|
231
|
+
let a = a . '<span style="background-color: ' . ( x != "" ? x : s:fgc ) . '">'
|
232
|
+
let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
|
233
|
+
let a = a . '<font color="' . ( x != "" ? x : s:bgc ) . '">'
|
234
|
+
else
|
235
|
+
let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
|
236
|
+
if x != "" | let a = a . '<span style="background-color: ' . x . '">' | endif
|
237
|
+
let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
|
238
|
+
if x != "" | let a = a . '<font color="' . x . '">' | endif
|
239
|
+
endif
|
240
|
+
if synIDattr(a:id, "bold") | let a = a . "<b>" | endif
|
241
|
+
if synIDattr(a:id, "italic") | let a = a . "<i>" | endif
|
242
|
+
if synIDattr(a:id, "underline") | let a = a . "<u>" | endif
|
243
|
+
return a
|
244
|
+
endfun
|
245
|
+
|
246
|
+
" Return closing HTML tag for given highlight id
|
247
|
+
function s:HtmlClosing(id)
|
248
|
+
let a = ""
|
249
|
+
if synIDattr(a:id, "underline") | let a = a . "</u>" | endif
|
250
|
+
if synIDattr(a:id, "italic") | let a = a . "</i>" | endif
|
251
|
+
if synIDattr(a:id, "bold") | let a = a . "</b>" | endif
|
252
|
+
if synIDattr(a:id, "inverse")
|
253
|
+
let a = a . '</font></span>'
|
254
|
+
else
|
255
|
+
let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
|
256
|
+
if x != "" | let a = a . '</font>' | endif
|
257
|
+
let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
|
258
|
+
if x != "" | let a = a . '</span>' | endif
|
259
|
+
endif
|
260
|
+
return a
|
261
|
+
endfun
|
262
|
+
endif
|
263
|
+
|
264
|
+
" Return CSS style describing given highlight id (can be empty)
|
265
|
+
function! s:CSS1(id)
|
266
|
+
let a = ""
|
267
|
+
if synIDattr(a:id, "inverse")
|
268
|
+
" For inverse, we always must set both colors (and exchange them)
|
269
|
+
let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
|
270
|
+
let a = a . "color: " . ( x != "" ? x : s:bgc ) . "; "
|
271
|
+
let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
|
272
|
+
let a = a . "background-color: " . ( x != "" ? x : s:fgc ) . "; "
|
273
|
+
else
|
274
|
+
let x = s:HtmlColor(synIDattr(a:id, "fg#", s:whatterm))
|
275
|
+
if x != "" | let a = a . "color: " . x . "; " | endif
|
276
|
+
let x = s:HtmlColor(synIDattr(a:id, "bg#", s:whatterm))
|
277
|
+
if x != "" | let a = a . "background-color: " . x . "; " | endif
|
278
|
+
endif
|
279
|
+
if synIDattr(a:id, "bold") | let a = a . "font-weight: bold; " | endif
|
280
|
+
if synIDattr(a:id, "italic") | let a = a . "font-style: italic; " | endif
|
281
|
+
if synIDattr(a:id, "underline") | let a = a . "text-decoration: underline; " | endif
|
282
|
+
return a
|
283
|
+
endfun
|
284
|
+
|
285
|
+
" Set some options to make it work faster.
|
286
|
+
" Expand tabs in original buffer to get 'tabstop' correctly used.
|
287
|
+
" Don't report changes for :substitute, there will be many of them.
|
288
|
+
let s:old_title = &title
|
289
|
+
let s:old_icon = &icon
|
290
|
+
let s:old_et = &l:et
|
291
|
+
let s:old_report = &report
|
292
|
+
let s:old_search = @/
|
293
|
+
set notitle noicon
|
294
|
+
setlocal et
|
295
|
+
set report=1000000
|
296
|
+
|
297
|
+
" Split window to create a buffer with the HTML file.
|
298
|
+
if expand("%") == ""
|
299
|
+
new Untitled.html
|
300
|
+
else
|
301
|
+
new %.html
|
302
|
+
endif
|
303
|
+
set modifiable
|
304
|
+
%d
|
305
|
+
let s:old_paste = &paste
|
306
|
+
set paste
|
307
|
+
|
308
|
+
" The DTD
|
309
|
+
if exists("html_use_css")
|
310
|
+
exe "normal a<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n \"http://www.w3.org/TR/html4/strict.dtd\">\n\e"
|
311
|
+
endif
|
312
|
+
|
313
|
+
" HTML header, with the title and generator ;-). Left free space for the CSS,
|
314
|
+
" to be filled at the end.
|
315
|
+
if !exists("html_no_header")
|
316
|
+
exe "normal a<html>\n<head>\n<title>\e"
|
317
|
+
exe "normal a" . expand("%:p:~") . "</title>\n\e"
|
318
|
+
exe "normal a<meta name=\"Generator\" content=\"Vim/" . version/100 . "." . version %100 . "\">\n\e"
|
319
|
+
if exists("html_use_css")
|
320
|
+
exe "normal a<style type=\"text/css\">\n<!--\n-->\n</style>\n\e"
|
321
|
+
endif
|
322
|
+
exe "normal a</head>\n<body>\n<pre>\n\e"
|
323
|
+
endif
|
324
|
+
|
325
|
+
wincmd p
|
326
|
+
|
327
|
+
" List of all id's
|
328
|
+
let s:idlist = ","
|
329
|
+
|
330
|
+
let s:expandedtab = ' '
|
331
|
+
while strlen(s:expandedtab) < &ts
|
332
|
+
let s:expandedtab = s:expandedtab . ' '
|
333
|
+
endwhile
|
334
|
+
|
335
|
+
" Loop over all lines in the original text
|
336
|
+
let s:end = line("$")
|
337
|
+
let s:lnum = 1
|
338
|
+
while s:lnum <= s:end
|
339
|
+
|
340
|
+
" Get the current line
|
341
|
+
let s:line = getline(s:lnum)
|
342
|
+
let s:len = strlen(s:line)
|
343
|
+
let s:new = ""
|
344
|
+
|
345
|
+
if s:numblines
|
346
|
+
let s:new = '<span class="lnr">' . strpart(' ', 0, strlen(line("$")) - strlen(s:lnum)) . s:lnum . '</span> '
|
347
|
+
endif
|
348
|
+
|
349
|
+
" Loop over each character in the line
|
350
|
+
let s:col = 1
|
351
|
+
while s:col <= s:len
|
352
|
+
let s:startcol = s:col " The start column for processing text
|
353
|
+
let s:id = synID(s:lnum, s:col, 1)
|
354
|
+
let s:col = s:col + 1
|
355
|
+
" Speed loop (it's small - that's the trick)
|
356
|
+
" Go along till we find a change in synID
|
357
|
+
while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile
|
358
|
+
|
359
|
+
" Output the text with the same synID, with class set to c{s:id}
|
360
|
+
let s:id = synIDtrans(s:id)
|
361
|
+
let s:new = s:new . '<span class="c' . s:id . '">' . substitute(substitute(substitute(substitute(substitute(strpart(s:line, s:startcol - 1, s:col - s:startcol), '&', '\&', 'g'), '<', '\<', 'g'), '>', '\>', 'g'), '"', '\"', 'g'), "\x0c", '<hr class="PAGE-BREAK">', 'g') . '</span>'
|
362
|
+
" Add the class to class list if it's not there yet
|
363
|
+
if stridx(s:idlist, "," . s:id . ",") == -1
|
364
|
+
let s:idlist = s:idlist . s:id . ","
|
365
|
+
endif
|
366
|
+
|
367
|
+
if s:col > s:len
|
368
|
+
break
|
369
|
+
endif
|
370
|
+
endwhile
|
371
|
+
|
372
|
+
" Expand tabs
|
373
|
+
let s:pad=0
|
374
|
+
let s:start = 0
|
375
|
+
let s:idx = stridx(s:line, "\t")
|
376
|
+
while s:idx >= 0
|
377
|
+
let s:i = &ts - ((s:start + s:pad + s:idx) % &ts)
|
378
|
+
let s:new = substitute(s:new, '\t', strpart(s:expandedtab, 0, s:i), '')
|
379
|
+
let s:pad = s:pad + s:i - 1
|
380
|
+
let s:start = s:start + s:idx + 1
|
381
|
+
let s:idx = stridx(strpart(s:line, s:start), "\t")
|
382
|
+
endwhile
|
383
|
+
|
384
|
+
exe "normal \<C-W>pa" . strtrans(s:new) . "\n\e\<C-W>p"
|
385
|
+
let s:lnum = s:lnum + 1
|
386
|
+
+
|
387
|
+
endwhile
|
388
|
+
" Finish with the last line
|
389
|
+
if !exists("html_no_header")
|
390
|
+
exe "normal \<C-W>pa</pre>\n</body>\n</html>\e"
|
391
|
+
else
|
392
|
+
exe "normal \<C-W>p"
|
393
|
+
end
|
394
|
+
|
395
|
+
" Now, when we finally know which, we define the colors and styles
|
396
|
+
if exists("html_use_css")
|
397
|
+
8
|
398
|
+
endif
|
399
|
+
|
400
|
+
" Find out the background and foreground color.
|
401
|
+
let s:fgc = s:HtmlColor(synIDattr(highlightID("Normal"), "fg#", s:whatterm))
|
402
|
+
let s:bgc = s:HtmlColor(synIDattr(highlightID("Normal"), "bg#", s:whatterm))
|
403
|
+
if s:fgc == ""
|
404
|
+
let s:fgc = ( &background == "dark" ? "#ffffff" : "#000000" )
|
405
|
+
endif
|
406
|
+
if s:bgc == ""
|
407
|
+
let s:bgc = ( &background == "dark" ? "#000000" : "#ffffff" )
|
408
|
+
endif
|
409
|
+
|
410
|
+
" Normal/global attributes
|
411
|
+
" For Netscape 4, set <body> attributes too, though, strictly speaking, it's
|
412
|
+
" incorrect.
|
413
|
+
if exists("html_use_css")
|
414
|
+
execute "normal A\npre { color: " . s:fgc . "; background-color: " . s:bgc . "; }\e"
|
415
|
+
yank
|
416
|
+
put
|
417
|
+
execute "normal ^cwbody\e"
|
418
|
+
else
|
419
|
+
execute '%s:<body>:<body ' . 'bgcolor="' . s:bgc . '" text="' . s:fgc . '">'
|
420
|
+
endif
|
421
|
+
|
422
|
+
" Line numbering attributes
|
423
|
+
if s:numblines
|
424
|
+
if exists("html_use_css")
|
425
|
+
execute "normal A\n.lnr { " . s:CSS1(highlightID("LineNr")) . "}\e"
|
426
|
+
else
|
427
|
+
execute '%s+<span class="lnr">\([^<]*\)</span>+' . s:HtmlOpening(highlightID("LineNr")) . '\1' . s:HtmlClosing(highlightID("LineNr")) . '+g'
|
428
|
+
endif
|
429
|
+
endif
|
430
|
+
|
431
|
+
" Gather attributes for all other classes
|
432
|
+
let s:idlist = strpart(s:idlist, 1)
|
433
|
+
while s:idlist != ""
|
434
|
+
let s:attr = ""
|
435
|
+
let s:col = stridx(s:idlist, ",")
|
436
|
+
let s:id = strpart(s:idlist, 0, s:col)
|
437
|
+
let s:idlist = strpart(s:idlist, s:col + 1)
|
438
|
+
let s:attr = s:CSS1(s:id)
|
439
|
+
" If the class has some attributes, export the style, otherwise DELETE all
|
440
|
+
" its occurences to make the HTML shorter
|
441
|
+
if s:attr != ""
|
442
|
+
if exists("html_use_css")
|
443
|
+
execute "normal A\n.c" . s:id . " { " . s:attr . "}"
|
444
|
+
else
|
445
|
+
execute '%s+<span class="c' . s:id . '">\([^<]*\)</span>+' . s:HtmlOpening(s:id) . '\1' . s:HtmlClosing(s:id) . '+g'
|
446
|
+
endif
|
447
|
+
else
|
448
|
+
execute '%s+<span class="c' . s:id . '">\([^<]*\)</span>+\1+g'
|
449
|
+
8
|
450
|
+
endif
|
451
|
+
endwhile
|
452
|
+
|
453
|
+
" Cleanup
|
454
|
+
%s:\s\+$::e
|
455
|
+
|
456
|
+
" Restore old settings
|
457
|
+
let &report = s:old_report
|
458
|
+
let &title = s:old_title
|
459
|
+
let &icon = s:old_icon
|
460
|
+
let &paste = s:old_paste
|
461
|
+
let @/ = s:old_search
|
462
|
+
wincmd p
|
463
|
+
let &l:et = s:old_et
|
464
|
+
wincmd p
|
465
|
+
|
466
|
+
" Save a little bit of memory (worths doing?)
|
467
|
+
unlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search
|
468
|
+
unlet s:whatterm s:idlist s:lnum s:end s:fgc s:bgc
|
469
|
+
unlet! s:col s:id s:attr s:len s:line s:new s:did_retab s:numblines
|
470
|
+
delfunc s:HtmlColor
|
471
|
+
delfunc s:CSS1
|
472
|
+
if !exists("html_use_css")
|
473
|
+
delfunc s:HtmlOpening
|
474
|
+
delfunc s:HtmlClosing
|
475
|
+
endif
|