-- TIME_STAMP 2021-11-12 10:16:58 v 0.3 -- coding:utf-8 --[[ event: OnBeforeSave SciTEUser.properties: #======================================================================== TIMESTAMP & BACKUP ======= #~ TimeStamp, which file type and line in script: type=#line-number TimeStamp.Type.Line=au3=1|lua=1|py=3 #~ Coding-Cookie (if exists) should use which line (1 or 2) #~ will moved after setting time stamp to its correct line Coding.Cookie=lua=2|py=2 #~ Use version-backup for following file types: EXT|EXT.. Version.BackUp.Files=au3|lua #~ Ignore backup for files from these folders/drives (pipe-delimited list) #~ not case sensitive #~ i.e.: =C:\Program Files|C:\Program Files (x86)|E: Version.Backup.Exclude.Dirs= #~ Ignore backup for files with these names (or string pattern), (pipe-delimited list) #~ not case sensitive #~ i.e. #~ file name starts with 'Test': "^Test" #~ file name ends with 'Test': "Test$" #~ If the exception is to apply only to a specific file type, append suffix. This is checked separately. #~ i.e. #~ Lua - file name starts with 'Test': "^Test.lua" --> checks file name for find("^Test") and compares the file type "lua" Version.Backup.Exclude.Files= #~ optional general prefix for backup folder Version.Prefix=BUVer_ #~ Path for version backup folder [VER_DIR]: #~ URGENT!: Path NOT in quotation! #~ NO following backslash! #~ "Version.Path.*=default" - creates subdirectory in current script folder (likewise if property does not exist or has no value) #~ Folder name: $(Version.Path.ext)\$(Version.Prefix)FILENAME.EXT\ #~ File name: \FILENAME[Version-Number].EXT Version.Path.au3=C:\Code\VersionBackup\au3 Version.Path.lua=C:\Code\VersionBackup\lua #======================================================================== \TIMESTAMP & BACKUP ====== ]] -- v 0.3 fixed: Incorrect use of Lua comments with additional characters ("--~" or others) -- v 0.2 added: CheckExclude() local ct = require "CommonTools" -- min v 0.4 TimeStamp = EventClass:new(Common) TimeStamp.OnBeforeSave = function(self, _file) local tFile = {Dir = props['FileDir'], Name = props['FileName'], Ext = props['FileExt']:lower()} local tSetStamp, tCookie = {}, {} -- File types to set time-stamp/move coding-cookie for ext, line in (props['TimeStamp.Type.Line']):gmatch('([^|=]+)=([^|]+)') do tSetStamp[ext] = line -1 end for ext, line in (props['Coding.Cookie']):gmatch('([^|=]+)=([^|]+)') do tCookie[ext] = line -1 end local tWriteBackup = {} -- File types to write version backup for ext in (props['Version.BackUp.Files']):gmatch('([^|]+)') do tWriteBackup[ext] = true end -- check excludes if self:CheckExclude(tFile) then tWriteBackup[tFile.Ext] = nil end -- check conditions to call the function if tFile.Ext == nil or (tSetStamp[tFile.Ext] == nil and tWriteBackup[tFile.Ext] == nil) then return nil end -- call function self:Insert(tFile, tSetStamp[tFile.Ext], tCookie[tFile.Ext], (tWriteBackup[tFile.Ext] ~= nil)) return nil end TimeStamp.CheckExclude = function(self, _tFile) local propExDirs, tExDirs = props['Version.Backup.Exclude.Dirs'], {} if propExDirs ~= '' then tExDirs = ct:Split(propExDirs, '|', true) end local propExFiles, tExFiles = props['Version.Backup.Exclude.Files'], {} if propExFiles ~= '' then tExFiles = ct:Split(propExFiles, '|', true) end if #tExDirs > 0 then for i=1, #tExDirs do if tExDirs[i]:lower():find('^'.._tFile.Dir:lower()) then return true end end end if #tExFiles > 0 then for i=1, #tExFiles do local ext = tExFiles[i]:lower():match('%.(%w+)$') if ext ~= nil then if ext == _tFile.Ext then local name = tExFiles[i]:lower():match('^(.+)%.'..ext..'$') if _tFile.Name:lower():find(name) then return true end end else if _tFile.Name:lower():find(tExFiles[i]:lower()) then return true end end end end return false end TimeStamp.SaveToVersionFolder = function (self, _tFile, _sVer) local sSaveFolder = props['Version.Path.'.._tFile.Ext]:lower() if sSaveFolder == '' then sSaveFolder = 'default' end local sPrefix = props['Version.Prefix'] local sVerFolder = sPrefix.._tFile.Name..'.'.._tFile.Ext..'\\' local sVerFile = _tFile.Name..'['.._sVer:sub(3, _sVer:len())..']'..'.'.._tFile.Ext if sSaveFolder == 'default' then sSaveFolder = _tFile.Dir..'\\' end local len = sSaveFolder:len() if sSaveFolder:sub(len, len) ~= '\\' then sSaveFolder = sSaveFolder..'\\' end if not ct:FileExists(sSaveFolder..sVerFolder) then ct:FolderCreate(sSaveFolder..sVerFolder) end if ct:FileExists(sSaveFolder..sVerFolder..sVerFile) then return nil end local fh = io.open(sSaveFolder..sVerFolder..sVerFile, "wb") local text = editor:GetText() fh:write(text) fh:close() return end TimeStamp.Insert = function (self, _tFile, _lineStamp, _lineCookie, _bBackup) local firstVisible, lineDiff = editor.FirstVisibleLine, 0 local sCmntChar = ct:EditorGetCommentChar(_tFile.Ext) if sCmntChar:find('^--') then sCmntChar = '' end -- the time stamps starts as default with "--" local pattCmntChar = ct:EscapeMagic(sCmntChar) if _tFile.Ext == 'au3' then sCmntChar = ';' pattCmntChar = ';' end -- avoid multi char comment like ";~" local len_eol, _, eol = ct:EditorGetEOL() local caret = editor.CurrentPos -- Checks (for max. 50 lines) if TimeStamp and/or coding-cookie exists and stores the informations local lineNum, lineText, lineLen, lineHome, lineCookie for l = 0, 49 do lineText, lineLen = editor:GetLine(l) if lineLen == nil then break end lineHome = editor:PositionFromLine(l) local a, y = lineText:find("^"..pattCmntChar.."%-+ TIME_STAMP.*()"..eol) if y ~= nil then lineNum = l break end end if lineNum == nil then -- none time stamp exists lineText = '' lineLen = 0 lineHome = editor:PositionFromLine(_lineStamp) end if _tFile.Ext ~= 'au3' then lineCookie = ct:EditorCodingCookieLine(50) end editor:BeginUndoAction() local mustSave, space, bStampNew, bFirst = 0, ' ', false, false local sVer, sVerMain, sVerSub = '', 0, 0 if lineNum ~= nil then -- if time stamp exists, check for main/sub number sVerMain, sVerSub = lineText:match('%s-v%s(%d+)%.(%d+)') if _bBackup == true then local verMark = lineText:match("([vVn])"..eol) if sVerMain ~= nil then if verMark == 'V' then sVer = 'v '..tostring(tonumber(sVerMain) +1)..'.0' elseif verMark == 'v' then sVer = 'v '..sVerMain..'.'..tostring(tonumber(sVerSub) +1) elseif verMark == 'n' or verMark == nil then sVer = 'v '..sVerMain..'.'..sVerSub end mustSave = 1 else -- time stamp has no version number space = '' end end else -- none time stamp exists bStampNew = true lineNum = _lineStamp if _bBackup == false then space = '' else -- first backup editor:SetSel(0,1) -- is it marked to avoid backup in this case? if editor:GetSelText() == '*' then -- with asterisk at first editor position: no backup will saved, only time stamp are print space = '' editor:ReplaceSel('') bFirst = true else sVer = 'v 0.1' mustSave = 1 end end end local stamp = sCmntChar.."-- TIME_STAMP "..ct:OSDate().." "..ct:OSTime()..space..sVer..eol if bFirst == true then caret = caret - stamp:len() end if bStampNew == true then lineDiff = 1 editor:InsertText(editor:PositionFromLine(lineNum), stamp) else local stampLineEnd = lineHome + lineLen editor:SetSel(lineHome, stampLineEnd) editor:ReplaceSel(stamp) end -- is TimeStamp in line from property --> if not, move it if lineNum ~= _lineStamp then ct:EditorMoveLine(lineNum, _lineStamp-lineNum) -- target.line - current.line = count_to_move (-up/+down) end -- if coding cookie exists, be sure it has the line as set in properties, cookie has priority if lineCookie ~= nil then lineCookie = ct:EditorCodingCookieLine(50) -- might have been moved --> search again if (lineCookie ~= _lineCookie) then ct:EditorMoveLine(lineCookie, _lineCookie-lineCookie) end end editor.FirstVisibleLine = firstVisible + lineDiff if mustSave == 1 then self:SaveToVersionFolder(_tFile, sVer) end if lineDiff == 1 then caret = caret + stamp:len() end editor:SetSel(caret,caret) editor:EndUndoAction() end