rouge 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Python < RegexLexer
4
+ desc "The Python programming language (python.org)"
4
5
  tag 'python'
5
6
  aliases 'py'
6
7
  filenames '*.py', '*.pyw', '*.sc', 'SConstruct', 'SConscript', '*.tac'
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Ruby < RegexLexer
4
+ desc "The Ruby programming language (ruby-lang.org)"
4
5
  tag 'ruby'
5
6
  aliases 'rb'
6
7
  filenames '*.rb', '*.ruby', '*.rbw', '*.rake', '*.gemspec',
@@ -142,7 +143,7 @@ module Rouge
142
143
  (module)
143
144
  (\s+)
144
145
  ([a-zA-Z_][a-zA-Z0-9_]*(::[a-zA-Z_][a-zA-Z0-9_]*)*)
145
- ) do
146
+ )x do
146
147
  group 'Keyword'
147
148
  group 'Text'
148
149
  group 'Name.Namespace'
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Scheme < RegexLexer
4
+ desc "The Scheme variant of Lisp"
5
+
4
6
  tag 'scheme'
5
7
  filenames '*.scm', '*.ss', '*.rkt'
6
8
  mimetypes 'text/x-scheme', 'application/x-scheme'
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Shell < RegexLexer
4
+ desc "Various shell languages, including sh and bash"
5
+
4
6
  tag 'shell'
5
7
  aliases 'bash', 'zsh', 'ksh', 'sh'
6
8
  filenames '*.sh', '*.bash', '*.zsh', '*.ksh'
@@ -0,0 +1,137 @@
1
+ module Rouge
2
+ module Lexers
3
+ class SQL < RegexLexer
4
+ desc "Structured Query Language, for relational databases"
5
+ tag 'sql'
6
+ filenames '*.sql'
7
+ mimetypes 'text/x-sql'
8
+
9
+ def self.keywords
10
+ @keywords ||= Set.new %w(
11
+ ABORT ABS ABSOLUTE ACCESS ADA ADD ADMIN AFTER AGGREGATE ALIAS
12
+ ALL ALLOCATE ALTER ANALYSE ANALYZE AND ANY ARE AS ASC ASENSITIVE
13
+ ASSERTION ASSIGNMENT ASYMMETRIC AT ATOMIC AUTHORIZATION
14
+ AVG BACKWARD BEFORE BEGIN BETWEEN BITVAR BIT_LENGTH BOTH
15
+ BREADTH BY C CACHE CALL CALLED CARDINALITY CASCADE CASCADED
16
+ CASE CAST CATALOG CATALOG_NAME CHAIN CHARACTERISTICS
17
+ CHARACTER_LENGTH CHARACTER_SET_CATALOG CHARACTER_SET_NAME
18
+ CHARACTER_SET_SCHEMA CHAR_LENGTH CHECK CHECKED CHECKPOINT
19
+ CLASS CLASS_ORIGIN CLOB CLOSE CLUSTER COALSECE COBOL COLLATE
20
+ COLLATION COLLATION_CATALOG COLLATION_NAME COLLATION_SCHEMA
21
+ COLUMN COLUMN_NAME COMMAND_FUNCTION COMMAND_FUNCTION_CODE
22
+ COMMENT COMMIT COMMITTED COMPLETION CONDITION_NUMBER
23
+ CONNECT CONNECTION CONNECTION_NAME CONSTRAINT CONSTRAINTS
24
+ CONSTRAINT_CATALOG CONSTRAINT_NAME CONSTRAINT_SCHEMA
25
+ CONSTRUCTOR CONTAINS CONTINUE CONVERSION CONVERT COPY
26
+ CORRESPONTING COUNT CREATE CREATEDB CREATEUSER CROSS CUBE
27
+ CURRENT CURRENT_DATE CURRENT_PATH CURRENT_ROLE CURRENT_TIME
28
+ CURRENT_TIMESTAMP CURRENT_USER CURSOR CURSOR_NAME CYCLE DATA
29
+ DATABASE DATETIME_INTERVAL_CODE DATETIME_INTERVAL_PRECISION
30
+ DAY DEALLOCATE DECLARE DEFAULT DEFAULTS DEFERRABLE DEFERRED
31
+ DEFINED DEFINER DELETE DELIMITER DELIMITERS DEREF DESC DESCRIBE
32
+ DESCRIPTOR DESTROY DESTRUCTOR DETERMINISTIC DIAGNOSTICS
33
+ DICTIONARY DISCONNECT DISPATCH DISTINCT DO DOMAIN DROP
34
+ DYNAMIC DYNAMIC_FUNCTION DYNAMIC_FUNCTION_CODE EACH ELSE
35
+ ENCODING ENCRYPTED END END-EXEC EQUALS ESCAPE EVERY EXCEPT
36
+ ESCEPTION EXCLUDING EXCLUSIVE EXEC EXECUTE EXISTING EXISTS
37
+ EXPLAIN EXTERNAL EXTRACT FALSE FETCH FINAL FIRST FOR FORCE
38
+ FOREIGN FORTRAN FORWARD FOUND FREE FREEZE FROM FULL FUNCTION
39
+ G GENERAL GENERATED GET GLOBAL GO GOTO GRANT GRANTED GROUP
40
+ GROUPING HANDLER HAVING HIERARCHY HOLD HOST IDENTITY IGNORE
41
+ ILIKE IMMEDIATE IMMUTABLE IMPLEMENTATION IMPLICIT IN INCLUDING
42
+ INCREMENT INDEX INDITCATOR INFIX INHERITS INITIALIZE INITIALLY
43
+ INNER INOUT INPUT INSENSITIVE INSERT INSTANTIABLE INSTEAD
44
+ INTERSECT INTO INVOKER IS ISNULL ISOLATION ITERATE JOIN KEY
45
+ KEY_MEMBER KEY_TYPE LANCOMPILER LANGUAGE LARGE LAST LATERAL
46
+ LEADING LEFT LENGTH LESS LEVEL LIKE LIMIT LISTEN LOAD LOCAL
47
+ LOCALTIME LOCALTIMESTAMP LOCATION LOCATOR LOCK LOWER MAP MATCH
48
+ MAX MAXVALUE MESSAGE_LENGTH MESSAGE_OCTET_LENGTH MESSAGE_TEXT
49
+ METHOD MIN MINUTE MINVALUE MOD MODE MODIFIES MODIFY MONTH
50
+ MORE MOVE MUMPS NAMES NATIONAL NATURAL NCHAR NCLOB NEW NEXT
51
+ NO NOCREATEDB NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL
52
+ NULL NULLABLE NULLIF OBJECT OCTET_LENGTH OF OFF OFFSET OIDS
53
+ OLD ON ONLY OPEN OPERATION OPERATOR OPTION OPTIONS OR ORDER
54
+ ORDINALITY OUT OUTER OUTPUT OVERLAPS OVERLAY OVERRIDING
55
+ OWNER PAD PARAMETER PARAMETERS PARAMETER_MODE PARAMATER_NAME
56
+ PARAMATER_ORDINAL_POSITION PARAMETER_SPECIFIC_CATALOG
57
+ PARAMETER_SPECIFIC_NAME PARAMATER_SPECIFIC_SCHEMA PARTIAL PASCAL
58
+ PENDANT PLACING PLI POSITION POSTFIX PRECISION PREFIX PREORDER
59
+ PREPARE PRESERVE PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE
60
+ PUBLIC READ READS RECHECK RECURSIVE REF REFERENCES REFERENCING
61
+ REINDEX RELATIVE RENAME REPEATABLE REPLACE RESET RESTART
62
+ RESTRICT RESULT RETURN RETURNED_LENGTH RETURNED_OCTET_LENGTH
63
+ RETURNED_SQLSTATE RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP
64
+ ROUTINE ROUTINE_CATALOG ROUTINE_NAME ROUTINE_SCHEMA ROW ROWS
65
+ ROW_COUNT RULE SAVE_POINT SCALE SCHEMA SCHEMA_NAME SCOPE SCROLL
66
+ SEARCH SECOND SECURITY SELECT SELF SENSITIVE SERIALIZABLE
67
+ SERVER_NAME SESSION SESSION_USER SET SETOF SETS SHARE SHOW
68
+ SIMILAR SIMPLE SIZE SOME SOURCE SPACE SPECIFIC SPECIFICTYPE
69
+ SPECIFIC_NAME SQL SQLCODE SQLERROR SQLEXCEPTION SQLSTATE
70
+ SQLWARNINIG STABLE START STATE STATEMENT STATIC STATISTICS
71
+ STDIN STDOUT STORAGE STRICT STRUCTURE STYPE SUBCLASS_ORIGIN
72
+ SUBLIST SUBSTRING SUM SYMMETRIC SYSID SYSTEM SYSTEM_USER
73
+ TABLE TABLE_NAME TEMP TEMPLATE TEMPORARY TERMINATE THAN THEN
74
+ TIMESTAMP TIMEZONE_HOUR TIMEZONE_MINUTE TO TOAST TRAILING
75
+ TRANSATION TRANSACTIONS_COMMITTED TRANSACTIONS_ROLLED_BACK
76
+ TRANSATION_ACTIVE TRANSFORM TRANSFORMS TRANSLATE TRANSLATION
77
+ TREAT TRIGGER TRIGGER_CATALOG TRIGGER_NAME TRIGGER_SCHEMA TRIM
78
+ TRUE TRUNCATE TRUSTED TYPE UNCOMMITTED UNDER UNENCRYPTED UNION
79
+ UNIQUE UNKNOWN UNLISTEN UNNAMED UNNEST UNTIL UPDATE UPPER
80
+ USAGE USER USER_DEFINED_TYPE_CATALOG USER_DEFINED_TYPE_NAME
81
+ USER_DEFINED_TYPE_SCHEMA USING VACUUM VALID VALIDATOR VALUES
82
+ VARIABLE VERBOSE VERSION VIEW VOLATILE WHEN WHENEVER WHERE
83
+ WITH WITHOUT WORK WRITE YEAR ZONE
84
+ )
85
+ end
86
+
87
+ state :root do
88
+ rule /\s+/m, 'Text'
89
+ rule /--.*?\n/, 'Comment.Single'
90
+ rule %r(/\*), 'Comment.Multiline', :multiline_comments
91
+ rule /\d+/, 'Literal.Number.Integer'
92
+ rule /'/, 'Literal.String.Single', :single_string
93
+ rule /"/, 'Name.Variable', :double_string
94
+ rule /`/, 'Name.Variable', :backtick
95
+
96
+ rule /\w[\w\d]*/ do |m|
97
+ if self.class.keywords.include? m[0].upcase
98
+ token 'Keyword'
99
+ else
100
+ token 'Name'
101
+ end
102
+ end
103
+
104
+ rule %r([+*/<>=~!@#%^&|?^-]), 'Operator'
105
+ rule /[;:()\[\],.]/, 'Punctuation'
106
+ end
107
+
108
+ state :multiline_comments do
109
+ rule %r(/[*]), 'Comment.Multiline', :multiline_comments
110
+ rule %r([*]/), 'Comment.Multiline', :pop!
111
+ rule %r([^/*]+), 'Comment.Multiline'
112
+ rule %r([/*]), 'Comment.Multiline'
113
+ end
114
+
115
+ state :backtick do
116
+ rule /\\./, 'Literal.String.Escape'
117
+ rule /``/, 'Literal.String.Escape'
118
+ rule /`/, 'Name.Variable', :pop!
119
+ rule /[^\\`]+/, 'Name.Variable'
120
+ end
121
+
122
+ state :single_string do
123
+ rule /\\./, 'Literal.String.Escape'
124
+ rule /''/, 'Literal.String.Escape'
125
+ rule /'/, 'Literal.String.Single', :pop!
126
+ rule /[^\\']+/, 'Literal.String.Single'
127
+ end
128
+
129
+ state :double_string do
130
+ rule /\\./, 'Literal.String.Escape'
131
+ rule /""/, 'Literal.String.Escape'
132
+ rule /"/, 'Name.Variable', :pop!
133
+ rule /[^\\"]+/, 'Name.Variable'
134
+ end
135
+ end
136
+ end
137
+ end
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class TCL < RegexLexer
4
+ desc "The Tool Command Language (tcl.tk)"
4
5
  tag 'tcl'
5
6
  filenames '*.tcl'
6
7
  mimetypes 'text/x-tcl', 'text/x-script.tcl', 'application/x-tcl'
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class TeX < RegexLexer
4
+ desc "The TeX typesetting system"
4
5
  tag 'tex'
5
6
  aliases 'TeX', 'LaTeX', 'latex'
6
7
 
@@ -1,6 +1,8 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class Text < Lexer
4
+ desc "A boring lexer that doesn't highlight anything"
5
+
4
6
  tag 'text'
5
7
  filenames '*.txt'
6
8
  mimetypes 'text/plain'
@@ -0,0 +1,98 @@
1
+ module Rouge
2
+ module Lexers
3
+ class VimL < RegexLexer
4
+ desc "VimL, the scripting language for the Vim editor (vim.org)"
5
+ tag 'viml'
6
+ aliases 'vim', 'vimscript', 'ex'
7
+ filenames '*.vim', '*.vba', '.vimrc', '.exrc', '.gvimrc',
8
+ '_vimrc', '_exrc', '_gvimrc' # _ names for windows
9
+
10
+ mimetypes 'text/x-vim'
11
+
12
+ def self.keywords
13
+ load Pathname.new(__FILE__).dirname.join('viml/keywords.rb')
14
+ self.keywords
15
+ end
16
+
17
+ state :root do
18
+ rule /^(\s*)(".*?)$/ do
19
+ group 'Text'; group 'Comment'
20
+ end
21
+
22
+ rule /^\s*\\/, 'Literal.String.Escape'
23
+
24
+ rule /[ \t]+/, 'Text'
25
+
26
+ # TODO: regexes can have other delimiters
27
+ rule %r(/(\\\\|\\/|[^\n/])*/), 'Literal.String.Regex'
28
+ rule %r("(\\\\|\\"|[^\n"])*"), 'Literal.String.Double'
29
+ rule %r('(\\\\|\\'|[^\n'])*'), 'Literal.String.Single'
30
+
31
+ # if it's not a string, it's a comment.
32
+ rule /(?<=\s)"[^-:.%#=*].*?$/, 'Comment'
33
+
34
+ rule /-?\d+/, 'Literal.Number'
35
+ rule /#[0-9a-f]{6}/i, 'Literal.Number.Hex'
36
+ rule /^:/, 'Punctuation'
37
+ rule /[():<>+=!\[\]{}\|,~.-]/, 'Punctuation'
38
+ rule /\b(let|if|else|endif|elseif|fun|function|endfunction)\b/,
39
+ 'Keyword'
40
+
41
+ rule /\b(NONE|bold|italic|underline|dark|light)\b/, 'Name.Builtin'
42
+
43
+ rule /[absg]:\w+\b/, 'Name.Variable'
44
+ rule /\b\w+\b/, 'Postprocess.Name'
45
+
46
+ # no errors in VimL!
47
+ rule /./m, 'Text'
48
+ end
49
+
50
+ postprocess 'Postprocess.Name' do |tok, name|
51
+ keywords = self.class.keywords
52
+
53
+ if mapping_contains?(keywords[:command], name)
54
+ token 'Keyword', name
55
+ elsif mapping_contains?(keywords[:option], name)
56
+ token 'Name.Builtin', name
57
+ elsif mapping_contains?(keywords[:auto], name)
58
+ token 'Name.Builtin', name
59
+ else
60
+ token 'Text', name
61
+ end
62
+ end
63
+
64
+ def mapping_contains?(mapping, word)
65
+ shortest, longest = find_likely_mapping(mapping, word)
66
+
67
+ word.start_with?(shortest) and longest.start_with?(word)
68
+ end
69
+
70
+ # binary search through the mappings to find the one that's likely
71
+ # to actually work.
72
+ def find_likely_mapping(mapping, word)
73
+ min = 0
74
+ max = mapping.size
75
+
76
+ until max == min
77
+ mid = (max + min) / 2
78
+
79
+ cmp, _ = mapping[mid]
80
+
81
+ case word <=> cmp
82
+ when 1
83
+ # too low
84
+ min = mid + 1
85
+ when -1
86
+ # too high
87
+ max = mid
88
+ when 0
89
+ # just right, abort!
90
+ return mapping[mid]
91
+ end
92
+ end
93
+
94
+ mapping[max - 1]
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,11 @@
1
+ # DO NOT EDIT: automatically generated by `rake vimkeywords`.
2
+ # see tasks/vim.rake for more info.
3
+ module Rouge
4
+ module Lexers
5
+ class VimL
6
+ def self.keywords
7
+ @keywords ||= {:command=>[[":p", ":p"], ["Allargs", "Allargs"], ["DiffOrig", "DiffOrig"], ["Error", "Error"], ["Man", "Man"], ["MyCommand", "MyCommand"], ["Mycmd", "Mycmd"], ["N", "N"], ["N", "Next"], ["P", "P"], ["P", "Print"], ["Ren", "Ren"], ["Rena", "Rena"], ["Renu", "Renu"], ["TOhtml", "TOhtml"], ["X", "X"], ["XMLent", "XMLent"], ["XMLns", "XMLns"], ["a", "a"], ["ab", "ab"], ["abc", "abclear"], ["abo", "aboveleft"], ["al", "all"], ["ar", "ar"], ["ar", "args"], ["arga", "argadd"], ["argd", "argdelete"], ["argdo", "argdo"], ["arge", "argedit"], ["argg", "argglobal"], ["argl", "arglocal"], ["argu", "argument"], ["as", "ascii"], ["au", "au"], ["b", "buffer"], ["bN", "bNext"], ["ba", "ball"], ["bad", "badd"], ["bar", "bar"], ["bd", "bdelete"], ["bel", "belowright"], ["bf", "bfirst"], ["bl", "blast"], ["bm", "bmodified"], ["bn", "bnext"], ["bo", "botright"], ["bp", "bprevious"], ["br", "br"], ["br", "brewind"], ["brea", "break"], ["breaka", "breakadd"], ["breakd", "breakdel"], ["breakl", "breaklist"], ["bro", "browse"], ["browseset", "browseset"], ["bu", "bu"], ["buf", "buf"], ["bufdo", "bufdo"], ["buffers", "buffers"], ["bun", "bunload"], ["bw", "bwipeout"], ["c", "c"], ["c", "change"], ["cN", "cN"], ["cN", "cNext"], ["cNf", "cNf"], ["cNf", "cNfile"], ["cabc", "cabclear"], ["cad", "cad"], ["cad", "caddexpr"], ["caddb", "caddbuffer"], ["caddf", "caddfile"], ["cal", "call"], ["cat", "catch"], ["cb", "cbuffer"], ["cc", "cc"], ["ccl", "cclose"], ["cd", "cd"], ["ce", "center"], ["cex", "cexpr"], ["cf", "cfile"], ["cfir", "cfirst"], ["cg", "cgetfile"], ["cgetb", "cgetbuffer"], ["cgete", "cgetexpr"], ["changes", "changes"], ["chd", "chdir"], ["che", "checkpath"], ["checkt", "checktime"], ["cl", "cl"], ["cl", "clist"], ["cla", "clast"], ["clo", "close"], ["cmapc", "cmapclear"], ["cmdname", "cmdname"], ["cn", "cn"], ["cn", "cnext"], ["cnew", "cnewer"], ["cnf", "cnf"], ["cnf", "cnfile"], ["co", "copy"], ["col", "colder"], ["colo", "colorscheme"], ["com", "com"], ["comc", "comclear"], ["comment", "comment"], ["comp", "compiler"], ["con", "con"], ["con", "continue"], ["conf", "confirm"], ["cope", "copen"], ["count", "count"], ["cp", "cprevious"], ["cpf", "cpfile"], ["cq", "cquit"], ["cr", "crewind"], ["cs", "cs"], ["cscope", "cscope"], ["cstag", "cstag"], ["cuna", "cunabbrev"], ["cw", "cwindow"], ["d", "d"], ["d", "delete"], ["de", "de"], ["debug", "debug"], ["debugg", "debuggreedy"], ["del", "del"], ["delc", "delcommand"], ["delf", "delf"], ["delf", "delfunction"], ["delm", "delmarks"], ["di", "di"], ["di", "display"], ["diffg", "diffget"], ["diffo", "diffo"], ["diffoff", "diffoff"], ["diffp", "diffp"], ["diffpatch", "diffpatch"], ["diffpu", "diffput"], ["diffsplit", "diffsplit"], ["difft", "difft"], ["diffthis", "diffthis"], ["diffu", "diffupdate"], ["dig", "dig"], ["dig", "digraphs"], ["dj", "djump"], ["dl", "dlist"], ["do", "do"], ["doau", "doau"], ["dr", "drop"], ["ds", "dsearch"], ["dsp", "dsplit"], ["dwim", "dwim"], ["e", "e"], ["e", "edit"], ["e:e", "e:e"], ["e:e:e", "e:e:e"], ["e:e:r", "e:e:r"], ["ea", "ea"], ["earlier", "earlier"], ["ec", "ec"], ["echoe", "echoerr"], ["echom", "echomsg"], ["echon", "echon"], ["el", "else"], ["elsei", "elseif"], ["em", "emenu"], ["emenu", "emenu"], ["en", "en"], ["en", "endif"], ["endf", "endf"], ["endf", "endfunction"], ["endfo", "endfor"], ["endfun", "endfun"], ["endt", "endtry"], ["endw", "endwhile"], ["ene", "enew"], ["ex", "ex"], ["exi", "exit"], ["exu", "exusage"], ["f", "f"], ["f", "file"], ["filename", "filename"], ["files", "files"], ["filet", "filet"], ["filetype", "filetype"], ["fin", "fin"], ["fin", "find"], ["fina", "finally"], ["fini", "finish"], ["fir", "first"], ["fix", "fixdel"], ["fo", "fold"], ["foldc", "foldclose"], ["foldd", "folddoopen"], ["folddoc", "folddoclosed"], ["foldo", "foldopen"], ["for", "for"], ["fu", "fu"], ["fu", "function"], ["fun", "fun"], ["g", "g"], ["get", "get"], ["go", "goto"], ["gr", "grep"], ["grepa", "grepadd"], ["gs", "gs"], ["gui", "gui"], ["gvim", "gvim"], ["h", "h"], ["h", "help"], ["ha", "hardcopy"], ["helpf", "helpfind"], ["helpg", "helpgrep"], ["helpt", "helptags"], ["hi", "hi"], ["hid", "hide"], ["his", "history"], ["i", "i"], ["ia", "ia"], ["iabc", "iabclear"], ["if", "if"], ["ij", "ijump"], ["il", "ilist"], ["imapc", "imapclear"], ["in", "in"], ["index", "index"], ["intro", "intro"], ["is", "isearch"], ["isp", "isplit"], ["iuna", "iunabbrev"], ["j", "join"], ["ju", "jumps"], ["k", "k"], ["kee", "keepmarks"], ["keepa", "keepa"], ["keepalt", "keepalt"], ["keepj", "keepjumps"], ["l", "l"], ["l", "list"], ["lN", "lN"], ["lN", "lNext"], ["lNf", "lNf"], ["lNf", "lNfile"], ["la", "la"], ["la", "last"], ["lad", "lad"], ["lad", "laddexpr"], ["laddb", "laddbuffer"], ["laddf", "laddfile"], ["lan", "lan"], ["lan", "language"], ["lat", "lat"], ["later", "later"], ["lb", "lbuffer"], ["lc", "lcd"], ["lch", "lchdir"], ["lcl", "lclose"], ["lcs", "lcs"], ["lcscope", "lcscope"], ["le", "left"], ["lefta", "leftabove"], ["let", "let"], ["lex", "lexpr"], ["lf", "lfile"], ["lfir", "lfirst"], ["lg", "lgetfile"], ["lgetb", "lgetbuffer"], ["lgete", "lgetexpr"], ["lgr", "lgrep"], ["lgrepa", "lgrepadd"], ["lh", "lhelpgrep"], ["ll", "ll"], ["lla", "llast"], ["lli", "llist"], ["lmak", "lmake"], ["lmapc", "lmapclear"], ["lne", "lne"], ["lne", "lnext"], ["lnew", "lnewer"], ["lnf", "lnf"], ["lnf", "lnfile"], ["lo", "lo"], ["lo", "loadview"], ["loadk", "loadk"], ["loadkeymap", "loadkeymap"], ["loc", "lockmarks"], ["locale", "locale"], ["lockv", "lockvar"], ["lol", "lolder"], ["lop", "lopen"], ["lp", "lprevious"], ["lpf", "lpfile"], ["lr", "lrewind"], ["ls", "ls"], ["lt", "ltag"], ["lua", "lua"], ["luado", "luado"], ["luafile", "luafile"], ["lv", "lvimgrep"], ["lvimgrepa", "lvimgrepadd"], ["lw", "lwindow"], ["m", "move"], ["ma", "ma"], ["ma", "mark"], ["main", "main"], ["main", "main"], ["mak", "make"], ["marks", "marks"], ["mat", "match"], ["menut", "menut"], ["menut", "menutranslate"], ["mes", "mes"], ["messages", "messages"], ["mk", "mk"], ["mk", "mkexrc"], ["mkdir", "mkdir"], ["mks", "mksession"], ["mksp", "mkspell"], ["mkv", "mkv"], ["mkv", "mkvimrc"], ["mkvie", "mkview"], ["mo", "mo"], ["mod", "mode"], ["mv", "mv"], ["mz", "mz"], ["mz", "mzscheme"], ["mzf", "mzfile"], ["n", "n"], ["n", "n"], ["n", "next"], ["nb", "nbkey"], ["nbc", "nbclose"], ["nbs", "nbstart"], ["ne", "ne"], ["new", "new"], ["nkf", "nkf"], ["nmapc", "nmapclear"], ["noa", "noa"], ["noautocmd", "noautocmd"], ["noh", "nohlsearch"], ["nu", "number"], ["o", "o"], ["o", "open"], ["ol", "oldfiles"], ["omapc", "omapclear"], ["on", "only"], ["opt", "options"], ["ownsyntax", "ownsyntax"], ["p", "p"], ["p", "print"], ["p:", "p:"], ["p:", "p:"], ["p:gs", "p:gs"], ["p:h", "p:h"], ["p:h:h", "p:h:h"], ["p:r", "p:r"], ["p:t", "p:t"], ["pat", "pat"], ["pat", "pat"], ["pc", "pclose"], ["pe", "pe"], ["pe", "perl"], ["ped", "pedit"], ["perld", "perldo"], ["po", "pop"], ["popu", "popu"], ["popu", "popup"], ["pp", "ppop"], ["pr", "pr"], ["pre", "preserve"], ["prev", "previous"], ["pro", "pro"], ["prof", "profile"], ["profd", "profdel"], ["promptf", "promptfind"], ["promptr", "promptrepl"], ["ps", "psearch"], ["ptN", "ptN"], ["ptN", "ptNext"], ["pta", "ptag"], ["ptf", "ptfirst"], ["ptj", "ptjump"], ["ptl", "ptlast"], ["ptn", "ptn"], ["ptn", "ptnext"], ["ptp", "ptprevious"], ["ptr", "ptrewind"], ["pts", "ptselect"], ["pu", "put"], ["pw", "pwd"], ["py", "py"], ["py", "python"], ["py3", "py3"], ["py3", "py3"], ["py3file", "py3file"], ["pyf", "pyfile"], ["python3", "python3"], ["q", "q"], ["q", "quit"], ["qa", "qall"], ["quita", "quitall"], ["quote", "quote"], ["r", "r"], ["r", "r"], ["r", "read"], ["r:e", "r:e"], ["r:r", "r:r"], ["r:r:r", "r:r:r"], ["re", "re"], ["rec", "recover"], ["red", "red"], ["red", "redo"], ["redi", "redir"], ["redr", "redraw"], ["redraws", "redrawstatus"], ["reg", "registers"], ["res", "resize"], ["ret", "retab"], ["retu", "return"], ["rew", "rewind"], ["ri", "right"], ["rightb", "rightbelow"], ["ru", "ru"], ["ru", "runtime"], ["rub", "ruby"], ["rubyd", "rubydo"], ["rubyf", "rubyfile"], ["rundo", "rundo"], ["rv", "rviminfo"], ["s", "s"], ["s", "s"], ["s", "s"], ["s", "s"], ["sN", "sNext"], ["sa", "sargument"], ["sal", "sall"], ["san", "sandbox"], ["sav", "saveas"], ["sb", "sbuffer"], ["sbN", "sbNext"], ["sba", "sball"], ["sbf", "sbfirst"], ["sbl", "sblast"], ["sbm", "sbmodified"], ["sbn", "sbnext"], ["sbp", "sbprevious"], ["sbr", "sbrewind"], ["scrip", "scrip"], ["scrip", "scriptnames"], ["scripte", "scriptencoding"], ["scs", "scs"], ["scscope", "scscope"], ["se", "set"], ["setf", "setfiletype"], ["setg", "setglobal"], ["setl", "setlocal"], ["sf", "sfind"], ["sfir", "sfirst"], ["sh", "shell"], ["si", "si"], ["sig", "sig"], ["sign", "sign"], ["sil", "silent"], ["sim", "simalt"], ["sl", "sl"], ["sl", "sleep"], ["sla", "slast"], ["sm", "smagic"], ["sm", "smap"], ["sme", "sme"], ["smenu", "smenu"], ["sn", "snext"], ["sni", "sniff"], ["sno", "snomagic"], ["snoreme", "snoreme"], ["snoremenu", "snoremenu"], ["so", "so"], ["so", "source"], ["sor", "sort"], ["sp", "split"], ["spe", "spe"], ["spe", "spellgood"], ["spelld", "spelldump"], ["spelli", "spellinfo"], ["spellr", "spellrepall"], ["spellu", "spellundo"], ["spellw", "spellwrong"], ["spr", "sprevious"], ["sre", "srewind"], ["st", "st"], ["st", "stop"], ["sta", "stag"], ["star", "star"], ["star", "startinsert"], ["start", "start"], ["startg", "startgreplace"], ["startr", "startreplace"], ["stj", "stjump"], ["stopi", "stopinsert"], ["sts", "stselect"], ["sub", "sub"], ["sub", "sub"], ["sun", "sunhide"], ["sunme", "sunme"], ["sunmenu", "sunmenu"], ["sus", "suspend"], ["sv", "sview"], ["sw", "swapname"], ["sy", "sy"], ["syn", "syn"], ["sync", "sync"], ["syncbind", "syncbind"], ["synlist", "synlist"], ["t", "t"], ["t:r", "t:r"], ["tN", "tN"], ["tN", "tNext"], ["ta", "ta"], ["ta", "tag"], ["tab", "tab"], ["tabN", "tabN"], ["tabN", "tabNext"], ["tabc", "tabclose"], ["tabd", "tabdo"], ["tabe", "tabedit"], ["tabf", "tabfind"], ["tabfir", "tabfirst"], ["tabl", "tablast"], ["tabm", "tabmove"], ["tabn", "tabnext"], ["tabnew", "tabnew"], ["tabo", "tabonly"], ["tabp", "tabprevious"], ["tabr", "tabrewind"], ["tabs", "tabs"], ["tags", "tags"], ["tc", "tcl"], ["tcld", "tcldo"], ["tclf", "tclfile"], ["te", "tearoff"], ["tf", "tfirst"], ["th", "throw"], ["tj", "tjump"], ["tl", "tlast"], ["tm", "tm"], ["tm", "tmenu"], ["tn", "tn"], ["tn", "tnext"], ["to", "topleft"], ["tp", "tprevious"], ["tr", "tr"], ["tr", "trewind"], ["try", "try"], ["ts", "tselect"], ["tu", "tu"], ["tu", "tunmenu"], ["u", "u"], ["u", "undo"], ["un", "un"], ["una", "unabbreviate"], ["undoj", "undojoin"], ["undol", "undolist"], ["unh", "unhide"], ["unl", "unl"], ["unlo", "unlockvar"], ["uns", "unsilent"], ["up", "update"], ["v", "v"], ["ve", "ve"], ["ve", "version"], ["verb", "verbose"], ["version", "version"], ["version", "version"], ["vert", "vertical"], ["vi", "vi"], ["vi", "visual"], ["vie", "view"], ["vim", "vimgrep"], ["vimgrepa", "vimgrepadd"], ["viu", "viusage"], ["vmapc", "vmapclear"], ["vne", "vnew"], ["vs", "vsplit"], ["w", "w"], ["w", "write"], ["wN", "wNext"], ["wa", "wall"], ["wh", "while"], ["win", "win"], ["win", "winsize"], ["winc", "wincmd"], ["windo", "windo"], ["winp", "winpos"], ["wn", "wnext"], ["wp", "wprevious"], ["wq", "wq"], ["wqa", "wqall"], ["ws", "wsverb"], ["wundo", "wundo"], ["wv", "wviminfo"], ["x", "x"], ["x", "xit"], ["xa", "xall"], ["xmapc", "xmapclear"], ["xme", "xme"], ["xmenu", "xmenu"], ["xnoreme", "xnoreme"], ["xnoremenu", "xnoremenu"], ["xterm", "xterm"], ["xunme", "xunme"], ["xunmenu", "xunmenu"], ["xwininfo", "xwininfo"], ["y", "yank"]], :option=>[], :auto=>[["BufAdd", "BufAdd"], ["BufCreate", "BufCreate"], ["BufDelete", "BufDelete"], ["BufEnter", "BufEnter"], ["BufFilePost", "BufFilePost"], ["BufFilePre", "BufFilePre"], ["BufHidden", "BufHidden"], ["BufLeave", "BufLeave"], ["BufNew", "BufNew"], ["BufNewFile", "BufNewFile"], ["BufRead", "BufRead"], ["BufReadCmd", "BufReadCmd"], ["BufReadPost", "BufReadPost"], ["BufReadPre", "BufReadPre"], ["BufUnload", "BufUnload"], ["BufWinEnter", "BufWinEnter"], ["BufWinLeave", "BufWinLeave"], ["BufWipeout", "BufWipeout"], ["BufWrite", "BufWrite"], ["BufWriteCmd", "BufWriteCmd"], ["BufWritePost", "BufWritePost"], ["BufWritePre", "BufWritePre"], ["Cmd", "Cmd"], ["CmdwinEnter", "CmdwinEnter"], ["CmdwinLeave", "CmdwinLeave"], ["ColorScheme", "ColorScheme"], ["CursorHold", "CursorHold"], ["CursorHoldI", "CursorHoldI"], ["CursorMoved", "CursorMoved"], ["CursorMovedI", "CursorMovedI"], ["EncodingChanged", "EncodingChanged"], ["FileAppendCmd", "FileAppendCmd"], ["FileAppendPost", "FileAppendPost"], ["FileAppendPre", "FileAppendPre"], ["FileChangedRO", "FileChangedRO"], ["FileChangedShell", "FileChangedShell"], ["FileChangedShellPost", "FileChangedShellPost"], ["FileEncoding", "FileEncoding"], ["FileReadCmd", "FileReadCmd"], ["FileReadPost", "FileReadPost"], ["FileReadPre", "FileReadPre"], ["FileType", "FileType"], ["FileWriteCmd", "FileWriteCmd"], ["FileWritePost", "FileWritePost"], ["FileWritePre", "FileWritePre"], ["FilterReadPost", "FilterReadPost"], ["FilterReadPre", "FilterReadPre"], ["FilterWritePost", "FilterWritePost"], ["FilterWritePre", "FilterWritePre"], ["FocusGained", "FocusGained"], ["FocusLost", "FocusLost"], ["FuncUndefined", "FuncUndefined"], ["GUIEnter", "GUIEnter"], ["GUIFailed", "GUIFailed"], ["InsertChange", "InsertChange"], ["InsertCharPre", "InsertCharPre"], ["InsertEnter", "InsertEnter"], ["InsertLeave", "InsertLeave"], ["MenuPopup", "MenuPopup"], ["QuickFixCmdPost", "QuickFixCmdPost"], ["QuickFixCmdPre", "QuickFixCmdPre"], ["RemoteReply", "RemoteReply"], ["SessionLoadPost", "SessionLoadPost"], ["ShellCmdPost", "ShellCmdPost"], ["ShellFilterPost", "ShellFilterPost"], ["SourceCmd", "SourceCmd"], ["SourcePre", "SourcePre"], ["SpellFileMissing", "SpellFileMissing"], ["StdinReadPost", "StdinReadPost"], ["StdinReadPre", "StdinReadPre"], ["SwapExists", "SwapExists"], ["Syntax", "Syntax"], ["TabEnter", "TabEnter"], ["TabLeave", "TabLeave"], ["TermChanged", "TermChanged"], ["TermResponse", "TermResponse"], ["User", "User"], ["UserGettingBored", "UserGettingBored"], ["VimEnter", "VimEnter"], ["VimLeave", "VimLeave"], ["VimLeavePre", "VimLeavePre"], ["VimResized", "VimResized"], ["WinEnter", "WinEnter"], ["WinLeave", "WinLeave"], ["event", "event"]]}
8
+ end
9
+ end
10
+ end
11
+ end
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class XML < RegexLexer
4
+ desc %q(<desc for="this-lexer">XML</desc>)
4
5
  tag 'xml'
5
6
  filenames *%w(*.xml *.xsl *.rss *.xslt *.xsd *.wsdl)
6
7
  mimetypes *%w(
@@ -1,6 +1,7 @@
1
1
  module Rouge
2
2
  module Lexers
3
3
  class YAML < RegexLexer
4
+ desc "Yaml Ain't Markup Language (yaml.org)"
4
5
  tag 'yaml'
5
6
  aliases 'yml'
6
7
 
@@ -123,7 +124,7 @@ module Rouge
123
124
  # indented line in the block context
124
125
  state :block_line do
125
126
  # line end
126
- rule /[ ]*(?=#|$)/, 'Text', :pop!
127
+ rule /[ ]*(?=#|$)/, 'Text', :pop!
127
128
  rule /[ ]+/, 'Text'
128
129
  # tags, anchors, and aliases
129
130
  mixin :descriptors
@@ -145,8 +146,8 @@ module Rouge
145
146
 
146
147
  # a tag in the form '!', '!suffix' or '!handle!suffix'
147
148
  rule %r(
148
- !(?:[\w-]+)? #handle
149
- (?:![\w;/?:@&=+$,.!~*\'()\[\]%-]+)? #suffix
149
+ (?:![\w-]+)? # handle
150
+ !(?:[\w;/?:@&=+$,.!~*\'()\[\]%-]*) # suffix
150
151
  )x, 'Keyword.Type'
151
152
 
152
153
  # an anchor
@@ -1,13 +1,18 @@
1
1
  module Rouge
2
+ # @abstract
3
+ # A stateful lexer that uses sets of regular expressions to
4
+ # tokenize a string. Most lexers are instances of RegexLexer.
2
5
  class RegexLexer < Lexer
6
+ # A rule is a tuple of a regular expression to test, and a callback
7
+ # to perform if the test succeeds.
8
+ #
9
+ # @see StateDSL#rule
3
10
  class Rule
4
11
  attr_reader :callback
5
- attr_reader :next_state
6
12
  attr_reader :re
7
- def initialize(re, callback, next_state)
13
+ def initialize(re, callback)
8
14
  @re = re
9
15
  @callback = callback
10
- @next_state = next_state
11
16
  end
12
17
 
13
18
  def inspect
@@ -15,22 +20,17 @@ module Rouge
15
20
  end
16
21
  end
17
22
 
23
+ # a State is a named set of rules that can be tested for or
24
+ # mixed in.
25
+ #
26
+ # @see RegexLexer.state
18
27
  class State
19
28
  attr_reader :name
20
- def initialize(lexer_class, name, &defn)
21
- @lexer_class = lexer_class
29
+ def initialize(name, &defn)
22
30
  @name = name
23
31
  @defn = defn
24
32
  end
25
33
 
26
- def relative_state(state_name=nil, &b)
27
- if state_name
28
- @lexer_class.get_state(state_name)
29
- else
30
- State.new(@lexer_class, b.inspect, &b).load!
31
- end
32
- end
33
-
34
34
  def rules
35
35
  @rules ||= []
36
36
  end
@@ -49,6 +49,25 @@ module Rouge
49
49
  @rules = rules
50
50
  end
51
51
 
52
+ # Define a new rule for this state.
53
+ #
54
+ # @overload rule(re, token, next_state=nil)
55
+ # @overload rule(re, &callback)
56
+ #
57
+ # @param [Regexp] re
58
+ # a regular expression for this rule to test.
59
+ # @param [String] tok
60
+ # the token type to yield if `re` matches.
61
+ # @param [#to_s] next_state
62
+ # (optional) a state to push onto the stack if `re` matches.
63
+ # If `next_state` is `:pop!`, the state stack will be popped
64
+ # instead.
65
+ # @param [Proc] callback
66
+ # a block that will be evaluated in the context of the lexer
67
+ # if `re` matches. This block has access to a number of lexer
68
+ # methods, including {RegexLexer#push}, {RegexLexer#pop!},
69
+ # {RegexLexer#token}, and {RegexLexer#delegate}. The first
70
+ # argument can be used to access the match groups.
52
71
  def rule(re, tok=nil, next_state=nil, &callback)
53
72
  if block_given?
54
73
  next_state = tok
@@ -66,22 +85,29 @@ module Rouge
66
85
  end
67
86
  end
68
87
 
69
- rules << Rule.new(re, callback, next_state)
88
+ rules << Rule.new(re, callback)
70
89
  end
71
90
 
91
+ # Mix in the rules from another state into this state. The rules
92
+ # from the mixed-in state will be tried in order before moving on
93
+ # to the rest of the rules in this state.
72
94
  def mixin(lexer_name)
73
95
  rules << lexer_name.to_s
74
96
  end
75
97
  end
76
98
 
99
+ # The states hash for this lexer.
100
+ # @see state
77
101
  def self.states
78
102
  @states ||= {}
79
103
  end
80
104
 
81
- @start_procs = []
105
+ # The routines to run at the beginning of a fresh lex.
106
+ # @see start
82
107
  def self.start_procs
83
108
  @start_procs ||= InheritableList.new(superclass.start_procs)
84
109
  end
110
+ @start_procs = []
85
111
 
86
112
  # Specify an action to be run every fresh lex.
87
113
  #
@@ -91,20 +117,33 @@ module Rouge
91
117
  start_procs << b
92
118
  end
93
119
 
120
+ # Specify a filter to be applied as the lexer yields tokens.
121
+ #
122
+ # @param toktype
123
+ # The token type to postprocess
124
+ # @yield [tok, val]
125
+ # The token and the matched value. The block will be evaluated in
126
+ # the context of the lexer, and it must yield an equivalent
127
+ # token/value pair, usually by calling #token.
94
128
  def self.postprocess(toktype, &b)
95
129
  postprocesses << [Token[toktype], b]
96
130
  end
97
131
 
98
- @postprocesses = []
132
+ # where the postprocess blocks are stored.
133
+ # @see postprocess
99
134
  def self.postprocesses
100
135
  @postprocesses ||= InheritableList.new(superclass.postprocesses)
101
136
  end
137
+ @postprocesses = []
102
138
 
139
+ # Define a new state for this lexer with the given name.
140
+ # The block will be evaluated in the context of a {StateDSL}.
103
141
  def self.state(name, &b)
104
142
  name = name.to_s
105
- states[name] = State.new(self, name, &b)
143
+ states[name] = State.new(name, &b)
106
144
  end
107
145
 
146
+ # @private
108
147
  def self.get_state(name)
109
148
  return name if name.is_a? State
110
149
 
@@ -113,41 +152,55 @@ module Rouge
113
152
  state.load!
114
153
  end
115
154
 
116
- def self.[](name)
117
- get_state(name)
118
- end
119
-
120
- def get_state(name)
121
- self.class.get_state(name)
155
+ # @private
156
+ def get_state(state_name)
157
+ self.class.get_state(state_name)
122
158
  end
123
159
 
160
+ # The state stack. This is initially the single state `[:root]`.
161
+ # It is an error for this stack to be empty.
162
+ # @see #state
124
163
  def stack
125
164
  @stack ||= [get_state(:root)]
126
165
  end
127
166
 
167
+ # The current state - i.e. one on top of the state stack.
168
+ #
169
+ # NB: if the state stack is empty, this will throw an error rather
170
+ # than returning nil.
128
171
  def state
129
172
  stack.last or raise 'empty stack!'
130
173
  end
131
174
 
175
+ # reset this lexer to its initial state. This runs all of the
176
+ # start_procs.
132
177
  def reset!
133
- @scan_state = nil
178
+ @stack = nil
134
179
 
135
180
  self.class.start_procs.each do |pr|
136
181
  instance_eval(&pr)
137
182
  end
138
183
  end
139
184
 
185
+ # This implements the lexer protocol, by yielding [token, value] pairs.
186
+ #
187
+ # The process for lexing works as follows, until the stream is empty:
188
+ #
189
+ # 1. We look at the state on top of the stack (which by default is
190
+ # `[:root]`).
191
+ # 2. Each rule in that state is tried until one is successful. If one
192
+ # is found, that rule's callback is evaluated - which may yield
193
+ # tokens and manipulate the state stack. Otherwise, one character
194
+ # is consumed with an `'Error'` token, and we continue at (1.)
195
+ #
196
+ # @see #step #step (where (2.) is implemented)
140
197
  def stream_tokens(stream, &b)
141
198
  stream_without_postprocessing(stream) do |tok, val|
142
199
  _, processor = self.class.postprocesses.find { |t, _| t == tok }
143
200
 
144
201
  if processor
145
- # TODO: DRY this up with run_callback
146
- Enumerator.new do |y|
147
- @output_stream = y
202
+ with_output_stream(b) do
148
203
  instance_exec(tok, val, &processor)
149
- end.each do |newtok, newval|
150
- yield Token[newtok], newval
151
204
  end
152
205
  else
153
206
  yield tok, val
@@ -170,6 +223,11 @@ module Rouge
170
223
  end
171
224
  end
172
225
 
226
+ # Runs one step of the lex. Rules in the current state are tried
227
+ # until one matches, at which point its callback is called.
228
+ #
229
+ # @return true if a rule was tried successfully
230
+ # @return false otherwise.
173
231
  def step(state, stream, &b)
174
232
  state.rules.each do |rule|
175
233
  return true if run_rule(rule, stream, &b)
@@ -178,6 +236,7 @@ module Rouge
178
236
  false
179
237
  end
180
238
 
239
+ # @private
181
240
  def run_rule(rule, stream, &b)
182
241
  case rule
183
242
  when String
@@ -190,26 +249,26 @@ module Rouge
190
249
  scan(stream, rule.re) do
191
250
  debug { " got #{stream[0].inspect}" }
192
251
 
193
- run_callback(stream, &rule.callback).each do |tok, res|
194
- debug { " yielding #{tok.to_s.inspect}, #{res.inspect}" }
195
- b.call(Token[tok], res)
196
- end
252
+ run_callback(stream, rule.callback, &b)
197
253
  end
198
254
  end
199
255
  end
200
256
 
201
- def run_callback(stream, &callback)
202
- Enumerator.new do |y|
203
- @output_stream = y
257
+ # @private
258
+ def run_callback(stream, callback, &output_stream)
259
+ with_output_stream(output_stream) do
204
260
  @group_count = 0
205
261
  @last_match = stream
206
262
  instance_exec(stream, &callback)
207
263
  @last_match = nil
208
- @output_stream = nil
209
264
  end
210
265
  end
211
266
 
212
- MAX_NULL_STEPS = 5
267
+ # The number of successive scans permitted without consuming
268
+ # the input stream. If this is exceeded, the match fails.
269
+ MAX_NULL_SCANS = 5
270
+
271
+ # @private
213
272
  def scan(scanner, re, &b)
214
273
  # XXX HACK XXX
215
274
  # StringScanner's implementation of ^ is b0rken.
@@ -219,7 +278,7 @@ module Rouge
219
278
 
220
279
  @null_steps ||= 0
221
280
 
222
- if @null_steps >= MAX_NULL_STEPS
281
+ if @null_steps >= MAX_NULL_SCANS
223
282
  debug { " too many scans without consuming the string!" }
224
283
  return false
225
284
  end
@@ -240,6 +299,13 @@ module Rouge
240
299
  return false
241
300
  end
242
301
 
302
+ # Yield a token.
303
+ #
304
+ # @param tok
305
+ # the token type
306
+ # @param val
307
+ # (optional) the string value to yield. If absent, this defaults
308
+ # to the entire last match.
243
309
  def token(tok, val=:__absent__)
244
310
  val = @last_match[0] if val == :__absent__
245
311
  val ||= ''
@@ -249,10 +315,21 @@ module Rouge
249
315
  @output_stream << [Token[tok], val] unless val.empty?
250
316
  end
251
317
 
318
+ # Yield a token with the next matched group. Subsequent calls
319
+ # to this method will yield subsequent groups.
252
320
  def group(tok)
253
321
  token(tok, @last_match[@group_count += 1])
254
322
  end
255
323
 
324
+ # Delegate the lex to another lexer. The #lex method will be called
325
+ # with `:continue` set to true, so that #reset! will not be called.
326
+ # In this way, a single lexer can be repeatedly delegated to while
327
+ # maintaining its own internal state stack.
328
+ #
329
+ # @param [#lex] lexer
330
+ # The lexer or lexer class to delegate to
331
+ # @param [String] text
332
+ # The text to delegate. This defaults to the last matched string.
256
333
  def delegate(lexer, text=nil)
257
334
  debug { " delegating to #{lexer.inspect}" }
258
335
  text ||= @last_match[0]
@@ -263,18 +340,25 @@ module Rouge
263
340
  end
264
341
  end
265
342
 
343
+ # Push a state onto the stack. If no state name is given and you've
344
+ # passed a block, a state will be dynamically created using the
345
+ # {StateDSL}.
266
346
  def push(state_name=nil, &b)
267
- # use the top of the stack by default
268
- if state_name || b
269
- push_state = state.relative_state(state_name, &b)
347
+ push_state = if state_name
348
+ get_state(state_name)
349
+ elsif block_given?
350
+ State.new(b.inspect, &b).load!
270
351
  else
271
- push_state = self.state
352
+ # use the top of the stack by default
353
+ self.state
272
354
  end
273
355
 
274
356
  debug { " pushing #{push_state.name}" }
275
357
  stack.push(push_state)
276
358
  end
277
359
 
360
+ # Pop the state stack. If a number is passed in, it will be popped
361
+ # that number of times.
278
362
  def pop!(times=1)
279
363
  raise 'empty stack!' if stack.empty?
280
364
 
@@ -282,19 +366,34 @@ module Rouge
282
366
  times.times { stack.pop }
283
367
  end
284
368
 
369
+ # reset the stack back to `[:root]`.
285
370
  def reset_stack
286
371
  debug { ' resetting stack' }
287
372
  stack.clear
288
373
  stack.push get_state(:root)
289
374
  end
290
375
 
376
+ # Check if `state_name` is in the state stack.
291
377
  def in_state?(state_name)
292
378
  stack.map(&:name).include? state_name.to_s
293
379
  end
294
380
 
381
+ # Check if `state_name` is the state on top of the state stack.
295
382
  def state?(state_name)
296
383
  state_name.to_s == state.name
297
384
  end
298
385
 
386
+ private
387
+ def with_output_stream(output_stream, &b)
388
+ @output_stream = Yielder.new do |tok, val|
389
+ debug { " yielding #{tok.to_s.inspect}, #{val.inspect}" }
390
+ output_stream.call(Token[tok], val)
391
+ end
392
+
393
+ yield
394
+
395
+ ensure
396
+ @output_stream = nil
397
+ end
299
398
  end
300
399
  end