-- Copyright 2013-17 Paul Kulchenko, ZeroBrane LLC --------------------------------------------------------- local q = EscapeMagic local modpref = ide.MODPREF ide.proto.Document = {__index = { GetFileName = function(self) return self.fileName end, GetFilePath = function(self) return self.filePath end, GetFileExt = function(self) return GetFileExt(self.fileName) end, GetFileModifiedTime = function(self) return self.modTime end, GetEditor = function(self) return self.editor end, GetTabIndex = function(self) local notebook = self.editor:GetParent():DynamicCast("wxAuiNotebook") local index = notebook:GetPageIndex(self.editor) -- index may be -1 when `GetPageIndex` is called when the editor is already -- removed from the notebook; return non-existing index to continue return index >= 0 and index or notebook:GetPageCount(), notebook end, IsModified = function(self) return self.editor:GetModify() end, IsNew = function(self) return self.filePath == nil end, IsActive = function(self) if not self.editor then return false end local index, notebook = self:GetTabIndex() return notebook:GetSelection() == index end, SetFilePath = function(self, path) self.filePath = path end, SetFileName = function(self, name) local newext = not self.fileName or not name or GetFileExt(name) ~= GetFileExt(self.fileName) self.fileName = name -- reset the editor based on the set name local editor = self.editor if editor and newext then editor:SetupKeywords(GetFileExt(name)) editor:Colourise(0, -1) editor:ResetTokenList() -- reset list of tokens if this is a reused editor end end, SetFileModifiedTime = function(self, modtime) self.modTime = modtime end, SetModified = function(self, modified) if modified == false then self.editor:SetSavePoint() end end, SetTabText = function(self, text) local modpref = ide.config.editor.modifiedprefix or modpref local index, notebook = self:GetTabIndex() notebook:SetPageText(index, (self:IsModified() and modpref or '')..(text or self:GetTabText())) if ide.config.editor.showtabtooltip and ide:IsValidProperty(notebook, "SetPageToolTip") then notebook:SetPageToolTip(index, self:GetFilePath() or text or self:GetTabText()) end if ide.config.editor.showtabicon and ide:IsValidProperty(notebook, "GetImageList") and ide:IsValidProperty(notebook, "SetPageImage") then if not notebook:GetImageList() then notebook:SetImageList(ide:GetProjectTree():GetImageList()) end if notebook:GetImageList() then notebook:SetPageImage(index, ide:GetProjectTree():GetFileImage(self:GetFilePath() or text or self:GetTabText())) end end end, GetTabText = function(self) local modpref = ide.config.editor.modifiedprefix or modpref local index, notebook = self:GetTabIndex() if index == nil then return self.fileName end return (notebook:GetPageText(index):gsub("^"..q(modpref), "")) end, SetActive = function(self) if not self.editor then return false end local index, notebook = self:GetTabIndex() if index and notebook:GetSelection() ~= index then notebook:SetSelection(index) end AddToFileHistory(self:GetFilePath()) self.editor:SetFocus() self.editor:SetSTCFocus(true) -- when the active editor is changed while the focus is away from the application -- (as happens on OSX when the editor is selected from the command bar) -- the focus stays on wxAuiToolBar component, so need to explicitly switch it. -- this is needed because SetFocus doesn't reset the focus if it's already on the target. if ide.osname == "Macintosh" and ide.infocus then ide.infocus = self.editor end end, Save = function(self) return SaveFile(self.editor, self.filePath) end, Close = function(self) return ClosePage(self:GetTabIndex()) end, CloseAll = function(self, opts) -- opts.keep=true/false -- keep the current document (false) -- opts.scope="section"/"notebook"/"project"/"all" -- ("all") -- opts.dryrun=true/false -- return the list of documents and not close (false) if not opts then opts = {} end local index, nb = self:GetTabIndex() local tabctrl = opts.scope == "section" and nb:GetTabCtrl(self.editor) or nil -- if the tab control is not available and `section` is requested as the scope, -- change the scope to the `notebook`. This shouldn't normally happen, -- but may if the tab control is checked before the frame is fully set up. if not tabctrl and opts.scope == "section" then opts.scope = "notebook" end local toclose = {} for _, document in ipairs(ide:GetDocumentList()) do local dindex, dnb = document:GetTabIndex() local path = document:GetFilePath() if (not opts.keep or dnb ~= nb or dindex ~= index) and (not opts.scope or opts.scope == "all" -- close all if the scope is not set or (opts.scope == "notebook" and nb:GetPageIndex(document:GetEditor()) >= 0) or (opts.scope == "project" and path and ide:IsProjectSubDirectory(path)) -- if the document is in the same tab control (for split notebooks) or (opts.scope == "section" and tabctrl and tabctrl:GetIdxFromWindow(document:GetEditor()) >= 0) ) then table.insert(toclose, document) end end if opts.dryrun then return toclose end -- close pages in the reverse order (as ids shift when pages are closed) for i = #toclose, 1, -1 do if not toclose[i]:Close() then return false end end return true end, }} ide.proto.Plugin = {__index = { GetName = function(self) return self.name end, GetFileName = function(self) return self.fname end, GetFilePath = function(self) return MergeFullPath(GetPathWithSep(ide.editorFilename), self.fpath) end, GetConfig = function(self) return rawget(ide.config,self.fname) or {} end, GetSettings = function(self) return SettingsRestorePackage(self.fname) end, SetSettings = function(self, settings, opts) SettingsSavePackage(self.fname, settings, opts) end, }} ide.proto.Interpreter = {__index = { GetName = function(self) return self.name end, GetFileName = function(self) return self.fname end, GetExePath = function(self, ...) return self:fexepath(...) end, GetAPI = function(self) return self.api end, GetCommandLineArg = function(self, name) return ide.config.arg and (ide.config.arg.any or ide.config.arg[name or self.fname]) end, UpdateStatus = function(self) local cla = self.takeparameters and self:GetCommandLineArg() ide:SetStatus(self.name..(cla and #cla > 0 and ": "..cla or ""), 4) end, fprojdir = function(self,wfilename) return wfilename:GetPath(wx.wxPATH_GET_VOLUME) end, fworkdir = function(self,wfilename) local proj = ide:GetProject() return proj and proj:gsub("[\\/]$","") or wfilename:GetPath(wx.wxPATH_GET_VOLUME) end, fattachdebug = function(self) ide:GetDebugger():SetOptions() end, }} ide.proto.Debugger = {__index = { IsRunning = function(self) return self.running end, IsConnected = function(self) return self.server end, IsListening = function(self) return self.listening end, GetHostName = function(self) return self.hostname end, GetPortNumber = function(self) return self.portnumber end, GetConsole = function(self) local debugger = self return function(...) return debugger:shell(...) end end, GetDataOptions = function(self, options) local cfg = ide.config.debugger local params = { comment = false, nocode = true, numformat = cfg.numformat, metatostring = cfg.showtostring, maxlevel = cfg.maxdatalevel, maxnum = cfg.maxdatanum, maxlength = cfg.maxdatalength, } for k, v in pairs(options or {}) do params[k] = v end return params end, }} ide.proto.ID = { __index = function(_, id) return _G['ID_'..id] end, __call = function(_, id) return IDgen(id) end, }