Advertisement
Guest User

Custom ZBS markup

a guest
Oct 29th, 2014
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.84 KB | None | 0 0
  1. --[[-------------------------------------------------------
  2. Custom markup for the documentation
  3. --]]-------------------------------------------------------
  4. local CUSTOM_MARK_ITAL = '^^_' -- italic
  5. local CUSTOM_MARK_BOLD = '^^*' -- bold
  6. local CUSTOM_MARK_LINK = '^^$' -- link description start
  7. local CUSTOM_MARK_LINZ = '$^^' -- link description end
  8. local CUSTOM_MARK_LINA = '^^&' -- link URL start
  9. local CUSTOM_MARK_LINT = '&^^' -- link URL end
  10. local CUSTOM_MARK_HEAD = '^^#' -- header
  11. local CUSTOM_MARK_CODE = '^^`' -- code
  12. local CUSTOM_MARK_BOXD = '^^|' -- highlight
  13. local CUSTOM_MARK_MARK = ' ' -- separator
  14. local markup = {
  15.   [CUSTOM_MARK_BOXD] = {fg={127,0,127}, b=true},
  16.   [CUSTOM_MARK_CODE] = {fg={127,127,127}, fs=10},
  17.   [CUSTOM_MARK_HEAD] = {fn="Lucida Console", b=true},
  18.   [CUSTOM_MARK_LINK] = {u=true, hs={32,32,127}},
  19.   [CUSTOM_MARK_BOLD] = {b=true, fg={0,0,0}},
  20.   [CUSTOM_MARK_ITAL] = {i=true},
  21. }
  22. local q = EscapeMagic
  23. local CUSTOM_MARK_PTRN = ''  -- combination of all markup marks that can start styling
  24. for key in pairs(markup) do
  25.   if key ~= CUSTOM_MARK_MARK then CUSTOM_MARK_PTRN = CUSTOM_MARK_PTRN .. q(key) end
  26. end
  27.  
  28. local function ismarkup (tx)
  29.   local start = 1
  30.   local marksep = "[%s!%?%.,;:%(%)]"
  31.   while true do
  32.     -- find a separator first
  33.     local st,_,sep,more = string.find(tx, "(["..CUSTOM_MARK_PTRN.."])(.)", start)
  34.     if not st then return end
  35.  
  36.     -- check if this is a first character of a multi-character separator
  37.     if not markup[sep] then sep = sep .. (more or '') end
  38.  
  39.     local s,e,cap
  40.     local qsep = q(sep)
  41.     local nonsep = ("[^%s]"):format(qsep)
  42.     local nonspace = ("[^%s]"):format(qsep.."%s")
  43.     if sep == CUSTOM_MARK_HEAD then
  44.       -- always search from the start of the line
  45.       -- [%w%p] set is needed to avoid continuing this markup to the next line
  46.       s,e,cap = string.find(tx,"^("..q(CUSTOM_MARK_HEAD)..".+[%w%p])")
  47.     elseif sep == CUSTOM_MARK_LINK then
  48.       -- allow everything based on balanced link separators
  49.       s,e,cap = string.find(tx,
  50.         "^(%b"..CUSTOM_MARK_LINK..CUSTOM_MARK_LINZ
  51.         .."%b"..CUSTOM_MARK_LINA..CUSTOM_MARK_LINT..")", st)
  52.     elseif markup[sep] then
  53.       -- try 2+ characters between separators first
  54.       -- if not found, try a single character
  55.       s,e,cap = string.find(tx,"^("..qsep..nonspace..nonsep.."-"..nonspace..qsep..")", st)
  56.       if not s then s,e,cap = string.find(tx,"^("..qsep..nonspace..qsep..")", st) end
  57.     end
  58.     if s and -- selected markup is surrounded by spaces or punctuation marks
  59.       (s == 1   or tx:sub(s-1, s-1):match(marksep)) and
  60.       (e == #tx or tx:sub(e+1, e+1):match(marksep))
  61.       then return s,e,cap,sep end
  62.     start = st+1
  63.   end
  64. end
  65.  
  66. local custom_style = function (editor, lines, linee)
  67.   local lines = lines or 0
  68.   if (lines < 0) then return end
  69.  
  70.   -- if the current spec doesn't have any comments, nothing to style
  71.   if not next(editor.spec.iscomment) then return end
  72.  
  73.   -- always style to the end as there may be comments that need re-styling
  74.   -- technically, this should be GetLineCount()-1, but we want to style
  75.   -- beyond the last line to make sure it is styled correctly
  76.   local linec = editor:GetLineCount()
  77.   local linee = linee or linec
  78.  
  79.   local linecomment = editor.spec.linecomment
  80.   local iscomment = {}
  81.   for i,v in pairs(editor.spec.iscomment) do
  82.     iscomment[i] = v
  83.   end
  84.  
  85.   local es = editor:GetEndStyled()
  86.   local needfix = false
  87.  
  88.   for line=lines,linee do
  89.     local tx = editor:GetLine(line)
  90.     local ls = editor:PositionFromLine(line)
  91.  
  92.     local from = 1
  93.     local off = -1
  94.  
  95.     -- doing WrapCount(line) when line == linec (which may be beyond
  96.     -- the last line) occasionally crashes the application on OSX.
  97.     local wrapped = line < linec and editor:WrapCount(line) or 0
  98.  
  99.     while from do
  100.       tx = string.sub(tx,from)
  101.       local f,t,w,mark = ismarkup(tx)
  102.  
  103.       if (f) then
  104.         local p = ls+f+off
  105.         local s = bit.band(editor:GetStyleAt(p), 31)
  106.         -- only style comments and only those that are not at the beginning
  107.         -- of the file to avoid styling shebang (#!) lines
  108.         -- also ignore matches for line comments (as defined in the spec)
  109.         if iscomment[s] and p > 0 and mark ~= linecomment then
  110.           local smark = #mark
  111.           local emark = #mark -- assumes end mark is the same length as start mark
  112.           if mark == CUSTOM_MARK_HEAD then
  113.             -- grab multiple CUSTOM_MARK_HEAD if present
  114.             local _,_,full = string.find(w,"^("..q(CUSTOM_MARK_HEAD).."+)")
  115.             smark,emark = #full,0
  116.           elseif mark == CUSTOM_MARK_LINK then
  117.             local lsep = w:find(q(CUSTOM_MARK_LINZ)..q(CUSTOM_MARK_LINA))
  118.             if lsep then emark = #w-lsep+#CUSTOM_MARK_LINT end
  119.           end
  120.           editor:StartStyling(p, 31)
  121.           editor:SetStyling(smark, markup[CUSTOM_MARK_MARK].st)
  122.           editor:SetStyling(t-f+1-smark-emark, markup[mark].st or markup[CUSTOM_MARK_MARK].st)
  123.           editor:SetStyling(emark, markup[CUSTOM_MARK_MARK].st)
  124.         end
  125.  
  126.         off = off + t
  127.       end
  128.       from = t and (t+1)
  129.     end
  130.  
  131.     -- has this line changed its wrapping because of invisible styling?
  132.     if wrapped > 1 and editor:WrapCount(line) < wrapped then needfix = true end
  133.   end
  134.   editor:StartStyling(es, 31)
  135.  
  136.   -- if any wrapped lines have changed, then reset WrapMode to fix the drawing
  137.   if needfix then
  138.     -- this fixes an issue with duplicate lines in Scintilla when
  139.     -- invisible styles hide some of the content that would be wrapped.
  140.     local wrapmode = editor:GetWrapMode()
  141.     if wrapmode ~= wxstc.wxSTC_WRAP_NONE then editor:SetWrapMode(wrapmode) end
  142.     -- if some of the lines have folded, this can make not styled lines visible
  143.     custom_style(editor, linee+1) -- style to the end in this case
  144.   end
  145. end
  146.  
  147. --[[----------------------------------------------------------
  148. plugin locals
  149. ]]------------------------------------------------------------
  150. local G = ...
  151. local id = G.ID("ts_docpanel.referenceview")
  152. local refpanel = "ts_docpanel"
  153. local refeditor
  154. -- Add the documentaion panel
  155. local addDocumentationPanel = function()
  156.   local e = wxstc.wxStyledTextCtrl(ide:GetMainFrame(), wx.wxID_ANY,
  157.     wx.wxDefaultPosition, wx.wxSize(20, 20), wx.wxBORDER_NONE)
  158.   refeditor = e
  159.  
  160.   -- Add the panel
  161.   local w, h = 250, 250
  162.   ide:AddPanel(e, refpanel, TR("Documentation"), function(pane)
  163.       pane:Dock():Right():TopDockable(false):BottomDockable(false)
  164.         :MinSize(w,-1):BestSize(w,-1):FloatingSize(w,h)
  165.     end)
  166.  
  167.   -- Append our own styles to those of the IDE
  168.   local numExistingStyles = #(ide.config.styles)
  169.   local currentCustomStyle = 1
  170.   for key,value in pairs(markup) do
  171.     local style = {}
  172.     -- copy all style features by value
  173.     for feature in pairs(value) do
  174.       style[feature] = value[feature]
  175.     end
  176.     style.fg = style.fg or {0, 0, 0}
  177.     style.bg = style.bg or {255, 255, 255}
  178.     style.st = numExistingStyles + currentCustomStyle
  179.     currentCustomStyle = currentCustomStyle + 1
  180.     ide.config.styles[key] = style
  181.   end
  182.  
  183.   -- Make sure the default IDE styles are in our markup, too, or they won't be applied by
  184.   -- the custom_style function
  185.   for key,value in pairs(ide.config.styles) do
  186.     if value["st"] ~= nil and value.st > 24 and value.st < 32 then
  187.       markup[key] = value
  188.     end
  189.   end
  190.  
  191.   -- Register keywords and set the styles to use
  192.   SetupKeywords(e, "lua", nil, ide.config.styles, ide.font.oNormal ,ide.font.oItalic)
  193.   StylesApplyToEditor(ide.config.styles, e, ide.font.oNormal, ide.font.oItalic)
  194.  
  195.   -- Provide fake iscomment
  196.   e.spec = {}
  197.   e.spec.iscomment = {}
  198.   for i = 0, 100 do
  199.     e.spec.iscomment[i] = true
  200.   end
  201.  
  202.   local font = ide:GetOutput():GetFont()
  203.   e:SetFont(font)
  204.   e:StyleSetFont(wxstc.wxSTC_STYLE_DEFAULT, font)
  205.   e:SetReadOnly(true)
  206.   e:SetWrapMode(wxstc.wxSTC_WRAP_WORD)
  207.  
  208.   -- remove all margins
  209.   for m = 0, 4 do e:SetMarginWidth(m, 0) end
  210.  
  211.   -- disable dragging to the panel
  212.   e:Connect(wxstc.wxEVT_STC_DO_DROP, function(event) event:SetDragResult(wx.wxDragNone) end)
  213.  
  214.   -- Connect to UI update to be able to style the document
  215.   e:Connect(wxstc.wxEVT_STC_UPDATEUI, function(event)
  216.       custom_style(e,0,e:GetLineCount()) -- style the entire document
  217.   end)
  218.  
  219.  
  220.   local menu = ide:GetMenuBar():GetMenu(ide:GetMenuBar():FindMenu(TR("&View")))
  221.   menu:InsertCheckItem(4, id, TR("Documentation Panel")..KSC(id))
  222.   menu:Connect(id, wx.wxEVT_COMMAND_MENU_SELECTED, function (event)
  223.       local uimgr = ide:GetUIManager()
  224.       uimgr:GetPane(refpanel):Show(not uimgr:GetPane(refpanel):IsShown())
  225.       uimgr:Update()
  226.     end)
  227.   ide:GetMainFrame():Connect(id, wx.wxEVT_UPDATE_UI, function (event)
  228.       local pane = ide:GetUIManager():GetPane(refpanel)
  229.       menu:Enable(event:GetId(), pane:IsOk()) -- disable if doesn't exist
  230.       menu:Check(event:GetId(), pane:IsOk() and pane:IsShown())
  231.     end)
  232. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement