if not modules then modules = { } end modules ['pret-pas'] = { version = 1.0, comment = "custom pretty printer for Pascal code", author = "Stefan Müller, Chemnitz DE", copyright = "Stefan Müller", license = "see context related readme files" } local visualizer = buffers.newvisualizer("pas") -- reserved words taken from http://www.freepascal.org/docs-html/ref/refse3.html visualizer.reservedwords = { -- Turbo Pascal "absolute", "and", "array", "asm", "begin", "case", "const", "constructor", "destructor", "div", "do", "downto", "else", "end", "file", "for", "function", "goto", "if", "implementation", "in", "inherited", "inline", "interface", "label", "mod", "nil", "not", "object", "of", "on", "operator", "or", "packed", "procedure", "program", "record", "reintroduce", "repeat", "self", "set", "shl", "shr", "string", "then", "to", "type", "unit", "until", "uses", "var", "while", "with", "xor", -- Free Pascal -- these are not bold type (keeping them, just in case) -- "dispose", "exit", "false", "new", "true", -- Object Pascal "as", "class", "dispinterface", "except", "exports", "finalization", "finally", "initialization", "inline", "is", "library", "on", "out", "packed", "property", "raise", "resourcestring", "threadvar", "try", -- Modifiers -- some of these are only bold in specific places (this is deliberately -- ignored) "absolute", "abstract", "alias", "assembler", "cdecl", "cppdecl", "default", "export", "external", "far", "far16", "forward", "index", "local", "name", "near", "nostackframe", "oldfpccall", "override", "pascal", "private", "protected", "public", "published", "read", "register", "reintroduce", "safecall", "softfloat", "stdcall", "virtual", "write" } local known_words = { } for k,v in next, visualizer.reservedwords do known_words[v] = k end local colors = { "prettyone", -- red: compiler directive, symbol "prettytwo", -- green: assembler (dark green) "prettythree", -- blue: comment, number (dark blue) "prettyfour", -- yellow } local states = { ['"']=1, ["'"]=1, ["[["] = 1, ["]]"] = 1, ['+']=1, ['-']=1, ['*']=1, ['/']=1, ['%']=1, ['^']=1, ["("] = 3, [")"] = 3, ["["] = 3, ["]"] = 3, ['--']=4, } local function flush_pas_word(word) if word then local id = known_words[word] if id then tex.sprint(tex.ctxcatcodes,"\{\\bf ") tex.write(word) tex.sprint(tex.ctxcatcodes,"\}") else tex.write(word) end end end local incomment, inlongstring = false, false local incompdirec, inasm = false, false function visualizer.reset() incomment, inlongstring = false, false incompdirec, inasm = false, false end local function written(state, c, i) if c == " " then state = buffers.finishstate(state) tex.sprint(tex.ctxcatcodes,"\\obs") elseif c == "\t" then state = buffers.finishstate(state) tex.sprint(tex.ctxcatcodes,"\\obs") if buffers.visualizers.enabletab then tex.sprint(tex.ctxcatcodes,rep("\\obs ",i%buffers.visualizers.tablength)) end else tex.write(c) end return state, 0 end function visualizer.flush_line(str, nested) local state, instr, inesc, word = 0, false, false, nil buffers.currentcolors = colors --state = buffers.changestate(1, state) for c in string.utfcharacters(str) do if string.find(c, "^[%a%_]$") then -- char belongs to identifier if word then word = word .. c else word = c end --state = buffers.changestate(2, state) elseif string.find(c, "^[%d]$") then if word and (#word > 1) then -- number, that belongs to identifier word = word .. c else -- number state = buffers.changestate(3, state) tex.write(c) end --state = buffers.changestate(3, state) else flush_pas_word(word) word = nil if c == " " then state = buffers.finishstate(state) tex.sprint(tex.ctxcatcodes,"\\obs") elseif c == "\t" then state = buffers.finishstate(state) tex.sprint(tex.ctxcatcodes,"\\obs") if buffers.visualizers.enabletab then tex.sprint(tex.ctxcatcodes,rep("\\obs ",buffers.visualizers.tablength)) end else -- symbol state = buffers.changestate(1, state) tex.write(c) end end --tex.write(c) state = buffers.finishstate(state) end flush_pas_word(word) word = nil --[[ local code, comment = string.match(str,"^(.-)%-%-%[%[(.*)$") if comment then -- process the code and then flush the comment elseif incomment then comment, code = string.match(str,"^(.-)%]%](.*)$") if comment then -- flush the comment and then process the code for c in string.utfcharacters(comment) do if c == " " then tex.sprint(tex.ctxcatcodes,"\\obs") else tex.write(c) end end state = buffers.changestate(states['--'], state) tex.write("KKK") state = buffers.finishstate(state) incomment = false else for c in string.utfcharacters(str) do if c == " " then tex.sprint(tex.ctxcatcodes,"\\obs") else tex.write(c) end end end comment = nil else code = str end if code and code ~= "" then local pre, post = string.match(code,"^(.-)%-%-(.*)$") if pre then code = pre end local p, s, i = nil, nil, 0 for c in string.utfcharacters(code) do i = i + 1 if instr then if p then tex.write(p) p = nil end if c == s then if inesc then tex.write(c) inesc = false else state = buffers.changestate(states[c],state) instr = false tex.write(c) state = buffers.finishstate(state) end s = nil else if c == "\\" then inesc = not inesc else inesc = false end state, i = written(state,c,i) end elseif c == "[" then if word then tex.write(word) word = nil end if p == "[" then inlongstring = true state = buffers.changestate(states["NRA"],state) tex.write(p,c) state = buffers.finishstate(state) p = nil else if p then state, i = written(state,p,i) end p = c end elseif c == "]" then if word then tex.write(word) word = nil end if p == "]" then inlongstring = false state = buffers.changestate(states["KKK"],state) tex.write(p,c) state = buffers.finishstate(state) p = nil else if p then state, i = written(state,p,i) end p = c end else if p then state = buffers.changestate(states[p],state) tex.write(p) state = buffers.finishstate(state) p = nil end if c == " " or c == "\t" then if word then flush_pas_word(word) word = nil end state, i = written(state,c,i) elseif inlongstring then state, i = written(state,c,i) elseif c == '"' or c == "'" then if word then flush_pas_word(word) word = nil end instr = true state = buffers.changestate(states[c],state) state, i = written(state,c,i) state = buffers.finishstate(state) s = c elseif string.find(c,"^[%a]$") then state = buffers.finishstate(state) if word then word = word .. c else word = c end elseif word and (#word > 1) and string.find(c,"^[%d%.%_]$") then if word then word = word .. c else word = c end else flush_pas_word(word) word = nil state = buffers.changestate(states[c],state) tex.write(c) instr = (c == '"') end end end if p then tex.write(p) -- state, i = written(state,p,i) p = nil end flush_pas_word(word) if post then state = buffers.changestate(states['--'], state) tex.write("--") state = buffers.finishstate(state) for c in string.utfcharacters(post) do state, i = written(state,c,i) end end end if comment then incomment = true state = buffers.changestate(states['--'], state) tex.write("NRA") state = buffers.finishstate(state) -- tex.write(comment) -- maybe also split and for c in string.utfcharacters(comment) do state, i = written(state,c,i) end end ]] state = buffers.finishstate(state) end