rouge 0.2.0 → 0.2.1

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/Gemfile CHANGED
@@ -15,3 +15,4 @@ gem 'sinatra'
15
15
 
16
16
  # docs
17
17
  gem 'yard'
18
+ gem 'github-markup'
@@ -30,8 +30,11 @@ load load_dir.join('rouge/lexers/tex.rb')
30
30
  load load_dir.join('rouge/lexers/markdown.rb')
31
31
  load load_dir.join('rouge/lexers/yaml.rb')
32
32
 
33
+ load load_dir.join('rouge/lexers/sql.rb')
34
+
33
35
  load load_dir.join('rouge/lexers/make.rb')
34
36
  load load_dir.join('rouge/lexers/shell.rb')
37
+ load load_dir.join('rouge/lexers/viml.rb')
35
38
 
36
39
  load load_dir.join('rouge/lexers/javascript.rb')
37
40
  load load_dir.join('rouge/lexers/css.rb')
@@ -17,7 +17,7 @@ module Rouge
17
17
  exit 0
18
18
  end
19
19
 
20
- unless %w(highlight style).include?(argv.first)
20
+ unless %w(highlight style list --help -h help).include?(argv.first)
21
21
  argv.unshift 'highlight'
22
22
  end
23
23
 
@@ -30,7 +30,7 @@ module Rouge
30
30
  :desc => ('Which lexer to use. If not provided, rougify will try to ' +
31
31
  'guess based on --mimetype, the filename, and the file ' +
32
32
  'contents.')
33
- option :formatter, :aliases => '-f', :default => 'html',
33
+ option :formatter, :aliases => '-f', :default => 'terminal256',
34
34
  :desc => ('Which formatter to use.')
35
35
  option :mimetype, :aliases => '-m',
36
36
  :desc => ('a mimetype that Rouge will use to guess the correct lexer. ' +
@@ -71,6 +71,22 @@ module Rouge
71
71
  puts theme.new(options).render
72
72
  end
73
73
 
74
+ desc 'list', 'list the available lexers, formatters, and styles'
75
+ def list
76
+ puts "== Available Lexers =="
77
+ all_lexers = Lexer.all
78
+ max_len = all_lexers.map { |l| l.tag.size }.max
79
+
80
+ Lexer.all.each do |lexer|
81
+ desc = "#{lexer.desc}"
82
+ if lexer.aliases.any?
83
+ desc << " [aliases: #{lexer.aliases.join(',')}]"
84
+ end
85
+ puts "%s: %s" % [lexer.tag, desc]
86
+ puts
87
+ end
88
+ end
89
+
74
90
  private
75
91
  # TODO: does Thor do this for me?
76
92
  def normalize_hash_keys(hash)
@@ -1,7 +1,10 @@
1
1
  module Rouge
2
+ # A Formatter takes a token stream and formats it for human viewing.
2
3
  class Formatter
3
4
  REGISTRY = {}
4
5
 
6
+ # Specify or get the unique tag for this formatter. This is used
7
+ # for specifying a formatter in `rougify`.
5
8
  def self.tag(tag=nil)
6
9
  return @tag unless tag
7
10
  REGISTRY[tag] = self
@@ -9,14 +12,18 @@ module Rouge
9
12
  @tag = tag
10
13
  end
11
14
 
15
+ # Find a formatter class given a unique tag.
12
16
  def self.find(tag)
13
17
  REGISTRY[tag]
14
18
  end
15
19
 
20
+ # Format a token stream.
16
21
  def render(tokens)
17
22
  enum_for(:stream, tokens).to_a.join
18
23
  end
19
24
 
25
+ # @abstract
26
+ # yield strings that, when concatenated, form the formatted output
20
27
  def stream(tokens, &b)
21
28
  raise 'abstract'
22
29
  end
@@ -3,13 +3,17 @@ require 'cgi'
3
3
 
4
4
  module Rouge
5
5
  module Formatters
6
+ # Transforms a token stream into HTML output.
6
7
  class HTML < Formatter
7
8
  tag 'html'
8
9
 
10
+ # @option opts :css_class
11
+ # A css class to be used for the generated <pre> tag.
9
12
  def initialize(opts={})
10
13
  @css_class = opts[:css_class] || 'highlight'
11
14
  end
12
15
 
16
+ # @yield the html output.
13
17
  def stream(tokens, &b)
14
18
  yield "<pre class=#{@css_class.inspect}>"
15
19
  tokens.each do |tok, val|
@@ -1,11 +1,17 @@
1
1
  module Rouge
2
2
  module Formatters
3
+ # A formatter for 256-color terminals
3
4
  class Terminal256 < Formatter
4
5
  tag 'terminal256'
5
6
 
7
+ # @private
6
8
  attr_reader :theme
9
+
10
+
11
+ # @option opts :theme
12
+ # (default is thankful_eyes) the theme to render with.
7
13
  def initialize(opts={})
8
- @theme = opts[:theme] || Themes::ThankfulEyes
14
+ @theme = opts[:theme] || 'thankful_eyes'
9
15
  @theme = Theme.find(@theme) if @theme.is_a? String
10
16
  end
11
17
 
@@ -95,7 +101,7 @@ module Rouge
95
101
  end
96
102
  end
97
103
 
98
- # private
104
+ private
99
105
  def escape(attrs)
100
106
  return '' if attrs.empty?
101
107
  "\e[#{attrs.join(';')}m"
@@ -2,6 +2,8 @@
2
2
  require 'strscan'
3
3
 
4
4
  module Rouge
5
+ # @abstract
6
+ # A lexer transforms text into a stream of `[token, chunk]` pairs.
5
7
  class Lexer
6
8
  class << self
7
9
  # Lexes `stream` with the given options. The lex is delegated to a
@@ -23,6 +25,20 @@ module Rouge
23
25
  registry[name.to_s]
24
26
  end
25
27
 
28
+ # Specify or get this lexer's description.
29
+ def desc(arg=:absent)
30
+ if arg == :absent
31
+ @desc
32
+ else
33
+ @desc = arg
34
+ end
35
+ end
36
+
37
+ # @return a list of all lexers.
38
+ def all
39
+ registry.values.uniq
40
+ end
41
+
26
42
  # Guess which lexer to use based on a hash of info.
27
43
  #
28
44
  # @option info :mimetype
@@ -82,6 +98,7 @@ module Rouge
82
98
  best_match
83
99
  end
84
100
 
101
+ # @private
85
102
  def register(name, lexer)
86
103
  registry[name.to_s] = lexer
87
104
  end
@@ -100,7 +117,7 @@ module Rouge
100
117
  return @tag if t.nil?
101
118
 
102
119
  @tag = t.to_s
103
- aliases @tag
120
+ Lexer.register(@tag, self)
104
121
  end
105
122
 
106
123
  # Used to specify alternate names this lexer class may be found by.
@@ -113,10 +130,12 @@ module Rouge
113
130
  #
114
131
  # Lexer.find('eruby') # => Erb
115
132
  def aliases(*args)
133
+ args.map!(&:to_s)
116
134
  args.each { |arg| Lexer.register(arg, self) }
135
+ (@aliases ||= []).concat(args)
117
136
  end
118
137
 
119
- # Specify a list of filename globs associated with this lexer
138
+ # Specify a list of filename globs associated with this lexer.
120
139
  #
121
140
  # @example
122
141
  # class Ruby < Lexer
@@ -144,16 +163,27 @@ module Rouge
144
163
 
145
164
  # -*- instance methods -*- #
146
165
 
166
+ # Create a new lexer with the given options. Individual lexers may
167
+ # specify extra options. The only current globally accepted option
168
+ # is `:debug`.
169
+ #
170
+ # @option opts :debug
171
+ # Prints debug information to stdout. The particular info depends
172
+ # on the lexer in question. In regex lexers, this will log the
173
+ # state stack at the beginning of each step, along with each regex
174
+ # tried and each stream consumed. Try it, it's pretty useful.
147
175
  def initialize(opts={})
148
176
  options(opts)
149
177
  end
150
178
 
179
+ # get and/or specify the options for this lexer.
151
180
  def options(o={})
152
181
  (@options ||= {}).merge!(o)
153
182
 
154
183
  self.class.default_options.merge(@options)
155
184
  end
156
185
 
186
+ # get or specify one option for this lexer
157
187
  def option(k, v=:absent)
158
188
  if v == :absent
159
189
  options[k]
@@ -209,7 +239,7 @@ module Rouge
209
239
 
210
240
  # @abstract
211
241
  #
212
- # Yield [token, chunk] pairs, given a prepared input stream. This
242
+ # Yield `[token, chunk]` pairs, given a prepared input stream. This
213
243
  # must be implemented.
214
244
  #
215
245
  # @param [StringScanner] stream
@@ -220,7 +250,7 @@ module Rouge
220
250
 
221
251
  # @abstract
222
252
  #
223
- # return a number between 0 and 1 indicating the likelihood that
253
+ # Return a number between 0 and 1 indicating the likelihood that
224
254
  # the text given should be lexed with this lexer. The default
225
255
  # implementation returns 0.
226
256
  #
@@ -5,6 +5,8 @@ module Rouge
5
5
  filenames '*.c', '*.h', '*.idc'
6
6
  mimetypes 'text/x-chdr', 'text/x-csrc'
7
7
 
8
+ desc "The C programming language"
9
+
8
10
  # optional comment or whitespace
9
11
  ws = %r((?:\s|//.*?\n|/[*].*?[*]/)+)
10
12
  id = /[a-zA-Z_][a-zA-Z0-9_]*/
@@ -55,6 +57,7 @@ module Rouge
55
57
  rule /__(?:#{__reserved.join('|')})\b/, 'Keyword.Reserved'
56
58
  rule /(?:true|false|NULL)\b/, 'Name.Builtin'
57
59
  rule id, 'Name'
60
+ rule /\s+/m, 'Text'
58
61
  end
59
62
 
60
63
  state :case do
@@ -4,6 +4,7 @@ require 'set'
4
4
  module Rouge
5
5
  module Lexers
6
6
  class CommonLisp < RegexLexer
7
+ desc "The Common Lisp variant of Lisp (common-lisp.net)"
7
8
  tag 'common_lisp'
8
9
  aliases 'cl', 'common-lisp'
9
10
 
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Cpp < RegexLexer
4
+ desc "The C++ programming language"
5
+
4
6
  tag 'cpp'
5
7
  aliases 'c++'
6
8
  # the many varied filenames of c++ source files...
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class CSS < RegexLexer
4
+ desc "Cascading Style Sheets, used to style web pages"
5
+
4
6
  tag 'css'
5
7
  filenames '*.css'
6
8
  mimetypes 'text/css'
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Diff < RegexLexer
4
+ desc "Lexes unified diffs or patches"
5
+
4
6
  tag 'diff'
5
7
  aliases 'patch', 'udiff'
6
8
  filenames '*.diff', '*.patch'
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class ERB < TemplateLexer
4
+ desc "Embedded ruby template files"
5
+
4
6
  tag 'erb'
5
7
  aliases 'eruby', 'rhtml'
6
8
 
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Factor < RegexLexer
4
+ desc "Factor, the practical stack language (factorcode.org)"
4
5
  tag 'factor'
5
6
  filenames '*.factor'
6
7
  mimetypes 'text/x-factor'
@@ -1,6 +1,10 @@
1
1
  module Rouge
2
2
  module Lexers
3
+ # A lexer for the Haml templating system for Ruby.
4
+ # @see http://haml.info
3
5
  class Haml < RegexLexer
6
+ desc "The Haml templating system for Ruby (haml.info)"
7
+
4
8
  tag 'haml'
5
9
  aliases 'HAML'
6
10
 
@@ -11,9 +15,10 @@ module Rouge
11
15
  return 0.1 if text.start_with? '!!!'
12
16
  end
13
17
 
14
- # option :filters is a hash of filter name to lexer of how
15
- # various filters should be highlighted. By default, :javascript
16
- # and :stylesheet are supported.
18
+ # @option opts :filters
19
+ # A hash of filter name to lexer of how various filters should be
20
+ # highlighted. By default, :javascript, :css, :ruby, and :erb
21
+ # are supported.
17
22
  def initialize(opts={})
18
23
  (opts.delete(:filters) || {}).each do |name, lexer|
19
24
  unless lexer.respond_to? :lex
@@ -41,10 +46,10 @@ module Rouge
41
46
  'css' => CSS.new(options),
42
47
  'ruby' => ruby,
43
48
  'erb' => ERB.new(options),
49
+ 'markdown' => Markdown.new(options),
44
50
  # TODO
45
51
  # 'sass' => Sass.new(options),
46
52
  # 'textile' => Textile.new(options),
47
- # 'markdown' => Markdown.new(options),
48
53
  # 'maruku' => Maruku.new(options),
49
54
  }
50
55
  end
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Haskell < RegexLexer
4
+ desc "The Haskell programming language (haskell.org)"
5
+
4
6
  tag 'haskell'
5
7
  aliases 'hs'
6
8
  filenames '*.hs'
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class HTML < RegexLexer
4
+ desc "HTML, the markup language of the web"
4
5
  tag 'html'
5
6
  filenames '*.htm', '*.html', '*.xhtml', '*.xslt'
6
7
  mimetypes 'text/html', 'application/xhtml+xml'
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Java < RegexLexer
4
+ desc "The Java programming language (java.com)"
5
+
4
6
  tag 'java'
5
7
  filenames '*.java'
6
8
  mimetypes 'text/x-java'
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Javascript < RegexLexer
4
+ desc "JavaScript, the browser scripting language"
5
+
4
6
  tag 'javascript'
5
7
  aliases 'js'
6
8
  filenames '*.js'
@@ -94,6 +96,7 @@ module Rouge
94
96
  end
95
97
 
96
98
  class JSON < RegexLexer
99
+ desc "JavaScript Object Notation (json.org)"
97
100
  tag 'json'
98
101
  filenames '*.json'
99
102
  mimetypes 'application/json'
@@ -102,7 +105,7 @@ module Rouge
102
105
  # so I'd think this wouldn't be too bad, but for large documents this
103
106
  # could mean doing two full lexes.
104
107
  def self.analyze_text(text)
105
- text.lexes_cleanly?(self) ? 0.8 : 0
108
+ return 0.8 if text =~ /\A\s*{/m && text.lexes_cleanly?(self)
106
109
  end
107
110
 
108
111
  state :root do
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Make < RegexLexer
4
+ desc "Makefile syntax"
4
5
  tag 'make'
5
6
  aliases 'makefile', 'mf', 'gnumake', 'bsdmake'
6
7
  filenames '*.make', 'Makefile', 'makefile', 'Makefile.*', 'GNUmakefile'
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Markdown < RegexLexer
4
+ desc "Markdown, a light-weight markup language for authors"
5
+
4
6
  tag 'markdown'
5
7
  aliases 'md', 'mkd'
6
8
  filenames '*.markdown', '*.md', '*.mkd'
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Perl < RegexLexer
4
+ desc "The Perl scripting language (perl.org)"
5
+
4
6
  tag 'perl'
5
7
  aliases 'pl'
6
8
 
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class PHP < TemplateLexer
4
+ desc "The PHP scripting language (php.net)"
4
5
  tag 'php'
5
6
  aliases 'php', 'php3', 'php4', 'php5'
6
7
  filenames '*.php', '*.php[345]'
@@ -18,12 +19,15 @@ module Rouge
18
19
  super(opts)
19
20
  end
20
21
 
22
+ def self.builtins
23
+ load Pathname.new(__FILE__).dirname.join('php/builtins.rb')
24
+ self.builtins
25
+ end
26
+
21
27
  def builtins
22
28
  return [] unless @funcnamehighlighting
23
29
 
24
30
  @builtins ||= Set.new.tap do |builtins|
25
- require Pathname.new(__FILE__).dirname.join('php/builtins.rb')
26
-
27
31
  self.class.builtins.each do |mod, fns|
28
32
  next if @disabledmodules.include? mod
29
33
  builtins.merge(fns)