-- SciTEStartup.lua -- SciTE extention functions
-- Some functions and code fragments were taken from other people,
-- including Tugarinov Sergey, mozers™ et al. Thanks!
-- Georgiy Pruss (C) 2007-05-24 21:23:31 Thu version 1294 * $@{YmdHMSv4a}
-- http://moon.aka.sun.googlepages.com/SciTE.htm
--[[ INDEX:
--||
--|| back_up
--|| calculate_total
--|| capitalize
--|| collect_marked
--|| current_word
--|| double_backslashes
--|| exec_lua
--|| exec_python_and_replace
--|| fill_rectangle
--|| find_next_function & find_prev_function
--|| mark_text_0/1/2/3
--|| move_word_left & move_word_right
--|| OnDoubleClick (timer)
--|| pop_mark
--|| push_mark
--|| replace_version
--|| sort_text
--|| tabs_to_spaces
--|| toggle_bool
--|| open_favorites
--|| utility
--]]
--print( os.date()..' Re-loading file "SciTEStartup.lua". Buffer "'..props.FileNameExt..'"' )
--[[ UTILITIES ]]
function get_sel_or_line()
if editor:GetSelText()=='' then
editor:Home()
editor:LineEndExtend()
end
return editor:GetSelText()
end
menu_table = {} -- a table id-->fn
function choose_from_menu( lst, sep, id, fn )
-- show menu, after the choice call fn with selected item
-- lst - string of items e.g. "First;Second;Third"
-- sep - separator in lst e.g. ";"
-- id - unique id of this menu, arbitrary number
-- fn - function to call e.g. function(s) print( s.." is chosen" ) end
menu_table[id] = fn
editor.AutoCSeparator = string.byte(sep)
editor:UserListShow(id,lst)
editor.AutoCSeparator = string.byte(' ')
end
function OnUserListSelection(id,s)
local fn = menu_table[id]
if fn then fn(s) end
end
--[[ fill_rectangle ]]
function _replace_block( l1, c1, l2, c2, fill, incr, nlen )
-- Replace/Insert/Fill in rectangle block
local l, line_pos, line_len, start_pos, end_pos, nblanks, blanks, txt, inslen
if l1>l2 then l2,l1=l1,l2 end
if c1>c2 then c2,c1=c1,c2 end
if nlen>0 then inslen=nlen else inslen=string.len(fill) end
editor:BeginUndoAction()
editor:DeleteBack() -- we don't need old text in the selection
for l = l1, l2 do
line_pos = editor:PositionFromLine(l)
line_len = editor.LineEndPosition[l] - line_pos
if c1 > line_len then
nblanks = c1 - line_len
blanks = string.rep(" ",nblanks)
editor:InsertText(line_pos+line_len, blanks)
end
start_pos = line_pos + c1
if nlen==0 then
editor:InsertText(start_pos, fill)
else
txt = string.format("%0"..nlen.."d", fill)
editor:InsertText(start_pos, txt)
fill = fill + incr
end
end
editor.CurrentPos = editor:PositionFromLine(l1) + c1 + inslen
editor:EndUndoAction()
end
function fill_rectangle(args)
-- fill_rectangle text:$(1) incr:$(2)
-- with one argument - fill with it
-- with two arguments (numeric) - fill with sequence
if editor.SelectionMode ~= SC_SEL_RECTANGLE then
_ALERT("Please provide rectangular selection")
return
end
local ARG1 = "text:"
local ARG1LEN = string.len( ARG1 )
local ARG2 = " incr:"
local ARG2LEN = string.len( ARG2 )
local fill=''
local incr=''
local nlen=0
local pos = string.find(args,ARG1,1,true)
if not pos then
return
end
args = string.sub(args,pos+ARG1LEN)
local pos = string.find(args,ARG2,1,true)
if pos then
fill = string.sub(args,1,pos-1)
incr = string.sub(args,pos+ARG2LEN)
else
fill = args
incr = ''
end
if incr ~= '' then
nlen = string.len( fill )
fill = tonumber( fill )
incr = tonumber( incr )
end
local p1 = editor.CurrentPos
local p2 = editor.Anchor
if p1 > p2 then
p1, p2 = p2, p1
end
_replace_block( editor:LineFromPosition(p1), editor.Column[p1],
editor:LineFromPosition(p2), editor.Column[p2],
fill, incr, nlen )
end
--[[ calculate_total ]]
function calculate_total()
local txt = editor:GetSelText()
local num = 0
local sum = 0.0
local function add(x) num = num + 1; sum = sum + tonumber(x); return '' end
local function add_hex(x) num = num + 1; sum = sum + tonumber(x,16); return '' end
txt = string.gsub( txt, "[+-]?%d+%.%d+[eE][+-]?%d+", add )
txt = string.gsub( txt, "[+-]?%d+[eE][+-]?%d+", add )
txt = string.gsub( txt, "[+-]?%d+%.%d+", add )
txt = string.gsub( txt, "[+-]?0x%x+", add_hex )
txt = string.gsub( string.gsub( txt, ",", "" ), "[+-]?%d+", add )
if num>0 then
print( "Count: "..num.." Sum: "..sum.." Avg: "..(sum/num) )
else
print( "No numbers found in the selection" )
end
end
--[[ tabs_to_spaces ]]
function tabs_to_spaces()
-- get override or editor's current tab size
local tabsz = tonumber(props["ext.lua.tabtospace.tabsize"])
if not tabsz then tabsz = editor.TabWidth end
local sub = string.sub
editor:BeginUndoAction()
for ln = 0, editor.LineCount - 1 do
local lbeg = editor:PositionFromLine(ln)
local lend = editor.LineEndPosition[ln]
local text = editor:textrange(lbeg, lend)
local changed = false
local x, y = string.find(text, "\t", 1, 1)
while x do
y = x - 1 + tabsz
y = y - math.mod(y, tabsz) + 1 -- tab stop position
text = sub(text, 1, x - 1) .. string.rep(" ", y - x) .. sub(text, x + 1)
changed = true
x, y = string.find(text, "\t", 1, 1)
end--while
if changed then
editor.TargetStart = lbeg
editor.TargetEnd = lend
editor:ReplaceTarget(text)
end
end--for
editor:EndUndoAction()
end
--[[ sort_text ]]
function _sort_text( opts )
local desc = string.find( opts, 'desc', 1, true ) ~= nil
local igncase = string.find( opts, 'ignore', 1, true ) ~= nil
editor:BeginUndoAction()
-- Tugarinov Sergey & mozers™ & me :)
local sel_text = editor:GetSelText()
local sel_start = editor.SelectionStart
local sel_end = editor.SelectionEnd
local lines = {}
if sel_text ~= '' then
local a_line = ''
for a_line in string.gfind(sel_text, "[^\n]+") do
table.insert(lines, a_line)
end
if table.getn(lines) > 1 then
upr = string.upper
if desc then
if igncase then
table.sort(lines, function(a, b) return upr(a) > upr(b) end)
else
table.sort(lines, function(a, b) return a > b end)
end
else -- asc
if igncase then
table.sort(lines, function(a, b) return upr(a) < upr(b) end)
else
table.sort(lines)
end
end
local out_text = table.concat(lines, "\n").."\n"
editor:ReplaceSel(out_text)
end
end
editor:SetSel(sel_start, sel_end)
editor:EndUndoAction()
-- ToDo: option for ignoring leading '_'s
--
-- To[Re]Do: arguments from the parameters dialog
-- flags in the first arg:
-- d - desceding (default - asc)
-- i - ignore case (default - case-sensitive)
-- n - numeric (50<100, default - lexical, 50>100) [NIY]
-- u - keep unique strings (default - keep duplicates too) [NIY]
-- e - external program (MS sort) [NIY]
-- g - external program (GNU sort) [NIY]
-- to do: parameters 2-4 can define positions for sorting
-- e.g. 10 = start from 10, 20-30 = chars 20-30, -40 = up to 40, etc
-- parse them for internal sort or rather pass to external programs
--
-- args is a string of opts followed by (hint)
--~ local x, y = string.find( args, '(', 1, true )
--~ local opts = string.sub( args, 1, x )
--~ local desc = string.find( opts, 'd', 1, true ) ~= nil
--~ local igncase = string.find( opts, 'i', 1, true ) ~= nil
end
function sort_text()
choose_from_menu( 'asc;desc;asc,ignore case;desc,ignore case', ';',
125, _sort_text )
end
--[[ back_up ]]
-- Back up 1) on open, 2) before save, 3) when Ctrl+2 pressed
-- copy file on *disk* (not from buffer!) to C:\TEMP\BackUp\
-- and append suffix .####.bak where #### is a radix-36 counter
-- of 5-second intervals with period 97.2 days (0000 to ZZZZ)
-- if new Untitled file, then saved from *buffer* with name Untitled.####.bak
function _radix_str( n, r, l )
-- formats string from int number n, radix r (2..36), min length l (>=0)
if r>36 then r=36 end
if r<2 then r=10 end
if l<0 then l=0 end
local a = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'
local d = 0
local s = ''
local z = ''
if n<0 then z = '-'; l = l - 1; n = -n end
n = math.floor(n)
while l>0 or n>0 do
n,d = math.floor(n/r),math.mod(n,r)
l = l - 1
s = string.sub(a,d+1,d+1)..s
end
return z..s
end
function _back_up_file( fp, fn, verbose ) -- may be used in SciTEExtension.lua
-- if fp and fn are '', save current buffer to 'Untitled'
if fp=='' then
fn = "Untitled"
else
local xx = string.find( fp, ' ', 1, true )
if xx then fp = '"'..fp..'"' end
fn = string.gsub( fn, ' ', '_' )
end
local nn = math.mod( math.floor(os.time()/5), 1679616 ) -- 36^4 by 5 s == 97.2 days
fn = string.format( "%s.%s.bak", fn, _radix_str( nn, 36, 4 ) )
if verbose then print( fp..' --> C:\\TEMP\\BackUp\\'..fn ) end
local fo = "C:\\TEMP\\BackUp\\"..fn
local txt
if fp=='' or string.find( fp, "C:\\TEMP\\Temporary Internet Files\\Content.IE5\\", 1, true ) then
txt = editor:GetText()
else
local f = io.open(fp, 'rb')
if f then txt = f:read('*all') f:close() else txt = fp.." not found" end
end
local f = io.open(fo, 'wb') f:write(txt) f:close()
end
function back_up()
local fp, fn = props.FilePath, props.FileNameExt
if fn == '' then
fp = ''
end
_back_up_file( fp, fn, true )
end
function OnOpen( fp )
if props["ext.lua.backup.on.open"] == '1' then
_back_up_file( fp, props.FileNameExt )
end
end
function OnBeforeSave( fp )
assert( fp == props.FilePath )
-- back up
if props["ext.lua.backup.before.save"] == '1' then
_back_up_file( props.FilePath, props.FileNameExt )
end
-- change version
local vers = props["ext.lua.count.version.before.save"]
if vers then
for pat in string.gfind( vers, "[^|]+" ) do -- ToDo: *.ext patterns
pat = string.gsub( pat, "%.", "%%." )
local pos,num = string.find( fp, "^.*" .. pat .. "$" )
if pos then
print( os.date()..' Versioning file "'..fp..'"' )
replace_version() -- it's in active buffer, isn't it? so we don't pass fp
end
end
end
end
--[[ replace_version ]]
-- look for version commands: $@{...}
-- a command is a char out of set: YymdHIMSwaAbBv+-
-- a number parameter may preceed a command
-- for the first command the default parameter is 1
-- for each next command w/o parameter it's value is incremented
-- the default parameter for + and - is always 1
-- after + or - the default goes back to 1 too
-- YymdHIMSwjUW -- change parameter'th number in the line to the current value
-- of corresponding component of date/time. See os.date/strftime for details.
-- aAbBp -- change parameter'th word (actually, id: %a%w*) in the line to
-- the current weekday/month name. See os.date/strftime for details.
-- v -- increment the parameter'th number
-- numbers/words are counted from the beginnig of the line with the commands
-- commands + and - change the line affected
-- See examples at the beginnig of this file and in SciTEGlobal.properties
function _process_ctrl_sequence( cmd, nr, st, en, txt )
local dirty = false
local digits = false
local num, num_specified = 0
local pat, p,e,x,y,z
for i = 1, string.len( cmd ) do
local c = string.sub( cmd, i, i )
if '0'<=c and c<='9' then
if digits then
num = num .. c
else
num = c
digits = true
end
else -- commnad
if digits then
num = tonumber(num)
num_specified = true
else
num_specified = false
end
digits = false
-- process c,num,num_specified
if not num_specified then num = num + 1 end -- increment parameter
local is_date_cmd = string.find( "YymdHIMSwjUW", c, 1, true )
local is_word_cmd = string.find( "aAbBp", c, 1, true )
if c == 'v' or is_date_cmd then -- change a number
pat = "^(%D*" .. string.rep( "%d+%D+", num-1 ) .. ")(%d+)(.*)$"
p,e,x,y,z = string.find( txt, pat )
elseif is_word_cmd then -- change a word (id, to be precise)
pat = "^(%A*" .. string.rep( "%a%w*%A+", num-1 ) .. ")(%a%w*)(.*)$"
p,e,x,y,z = string.find( txt, pat )
elseif c == '-' or c == '+' then -- previous/next line(s)
if dirty then
editor.TargetStart, editor.TargetEnd = st, en
editor:ReplaceTarget(txt)
end
if not num_specified then num = 1 end
if c == '+' then nr = nr + num else nr = nr - num end
st = editor:PositionFromLine(nr)
en = editor.LineEndPosition[nr]
txt = editor:textrange(st,en)
num = 0
dirty = false
end
if p then
if c == 'v' then
txt = x..tostring(tonumber(y)+1)..z
elseif is_date_cmd then
txt = x..os.date("%"..c)..z
elseif is_word_cmd then
txt = x..os.date("%"..c)..z
end
dirty = true
end
end
end
if dirty then
editor.TargetStart, editor.TargetEnd = st, en
editor:ReplaceTarget(txt)
end
end
function _process_ctrl_line( nr )
local st = editor:PositionFromLine(nr)
local en = editor.LineEndPosition[nr]
local txt = editor:textrange(st,en)
local pos,endpos = string.find( txt, "$@".."{[^}]*}" )
if pos then
_process_ctrl_sequence( string.sub( txt, pos+3, endpos-1 ), nr, st, en, txt )
end
end
function _find_ctrl_line( n )
-- starting from line n, looks for a line >= 0 containing control sequence
local st = editor:PositionFromLine( n )
local pos = editor:findtext( "$@{", SCFIND_MATCHCASE, st )
if pos then
return editor:LineFromPosition( pos )
end
return nil
end
function replace_version()
editor:BeginUndoAction()
local nr = _find_ctrl_line( 0 )
while nr do
_process_ctrl_line( nr )
nr = _find_ctrl_line( nr+1 )
end
editor:EndUndoAction()
end
--[[ current_word ]]
function _get_current_word_pos()
return editor:WordStartPosition(editor.CurrentPos,true),
editor:WordEndPosition(editor.CurrentPos,true)
end
function current_word()
-- double click on the word does the same
local s,e = _get_current_word_pos()
editor:SetSel(s,e)
end
--[[ toggle_bool ]]
function toggle_bool()
local p = editor.CurrentPos
local s = editor:WordStartPosition(p,true)
local e = editor:WordEndPosition(p,true)
editor.TargetStart, editor.TargetEnd = s, e
local word = editor:textrange(s,e)
if word == "False" then editor:ReplaceTarget("True")
elseif word == "True" then editor:ReplaceTarget("False")
elseif word == "false" then editor:ReplaceTarget("true")
elseif word == "true" then editor:ReplaceTarget("false")
elseif word == "FALSE" then editor:ReplaceTarget("TRUE")
elseif word == "TRUE" then editor:ReplaceTarget("FALSE")
end
editor:GotoPos( p )
end
--[[ exec_lua ]]
function exec_lua()
-- executes current line or selection as Lua code
-- if text starts with '=' execute as expression and print the result
local txt = string.gsub( get_sel_or_line(),"^%s*","",1 )
if string.sub(txt,1,1)=='=' then
dostring( "print("..string.sub(txt,2)..")" )
else
dostring( txt )
end
end
--[[ find_prev_function & find_next_function ]]
function _what_is_fn_re()
-- returns an RE that recognizes a function start in some languages
local fn = nil
local ext = string.lower(props.FileExt)
if ext=='lua' or ext=='js' or ext=='htm' or ext=='html' then
fn = '\\<function [A-Za-z_][A-Za-z0-9_:.]*('
elseif ext=='py' or ext=='pyw' or ext=='rb' then
fn = '\\<def [A-Za-z_][A-Za-z0-9_]*('
end
return fn
end
function find_prev_function()
local fn = _what_is_fn_re()
if fn then
editor:SearchAnchor()
local x = editor:SearchPrev(SCFIND_REGEXP,fn)
if x>=0 then editor:CharLeft() end
end
end
function find_next_function()
local fn = _what_is_fn_re()
if fn then
editor:SearchAnchor()
local x = editor:SearchNext(SCFIND_REGEXP,fn)
if x>=0 then editor:CharRight() end
end
end
--[[ capitalize ]]
function capitalize()
editor:BeginUndoAction()
local text = string.gsub( editor:GetSelText(), '([%a_])([%w_]*)',
function(a,b) return string.upper(a)..string.lower(b) end )
editor:ReplaceSel(text)
editor:EndUndoAction()
end
--[[ push_mark & pop_mark ]]
the_pos_stack = {}
function push_mark()
local f = props.FilePath
local m = the_pos_stack[f]
if not m then
the_pos_stack[f] = {n=0}
m = the_pos_stack[f]
end
local n = m.n
m[n] = editor.CurrentPos
m.n = n+1
-- todo: should be markers, because 'pos' becomes invalid after editing
-- and another idea - on some key, print FileNameExt:Ln: [comment]
-- to the output pane. then it's quite easy to move back with a click there.
end
function pop_mark()
local m = the_pos_stack[props.FilePath]
if m then
local n = m.n-1
if n>=0 then
m.n = n
editor:GotoPos( m[n] )
end
end
end
--[[ exec_python_and_replace ]]
FILE_IN = os.getenv('TEMP')..'\\scite_input.py'
FILE_OUT = os.getenv('TEMP')..'\\scite_output.txt'
REDIRECT = ' > '
PYTHON_CMD = 'C:\\Python\\python.exe -W ignore::FutureWarning '
function exec_python_and_replace()
-- executes line or selection as Python code
-- replace the selection with the result or append if "#a" is found inside
editor:BeginUndoAction()
local txt = get_sel_or_line()
local f = io.open(FILE_IN, 'wb') f:write(txt) f:close() -- write the file
os.execute(PYTHON_CMD..FILE_IN..REDIRECT..FILE_OUT) -- execute it
f = io.open(FILE_OUT) local out = f:read('*all') f:close() -- read output
if string.find(txt,"#a",1,true) then out = txt .. "\n" .. out end
editor:ReplaceSel(out)
editor:EndUndoAction()
end
--[[ double_backslashes ]]
function double_backslashes()
editor:ReplaceSel( string.gsub( get_sel_or_line(), '\\', '\\\\' ) )
end
--[[ mark_text_0 and mark_text_1/2/3 ]]
function _reset_mark_indic()
-- there's no editor pane during loading, so this can't be called at start
-- so let's assign it to mark_text_0 w/o selection -- quite approprite
editor.IndicStyle[0] = INDIC_ROUNDBOX
editor.IndicStyle[1] = INDIC_ROUNDBOX
editor.IndicStyle[2] = INDIC_ROUNDBOX
-- could be ext.lua.indic.fore.1/2/3 but this file is as good as SciTEGlb.prps
editor.IndicFore[0] = 255*257 -- YELLOW
editor.IndicFore[1] = 255*65536 -- BLUE
editor.IndicFore[2] = 255 -- RED
end
mark_names = "plain,squiggle,strike,box,roundbox,diagonal,tt,hidden" -- in menu order
mark_style = { plain = INDIC_PLAIN, squiggle = INDIC_SQUIGGLE,
tt = INDIC_TT, diagonal = INDIC_DIAGONAL,
strike = INDIC_STRIKE, hidden = INDIC_HIDDEN,
roundbox = INDIC_ROUNDBOX, box = INDIC_BOX }
function _set_mark_1(x) editor.IndicStyle[0] = mark_style[x] end
function _set_mark_2(x) editor.IndicStyle[1] = mark_style[x] end
function _set_mark_3(x) editor.IndicStyle[2] = mark_style[x] end
function _selection_pos_len()
local s,e = editor.SelectionStart,editor.SelectionEnd
return s,e-s
end
function mark_text_0()
-- clear marks (indicators) in the selection, or reset mark styles and colors
local pos,len = _selection_pos_len()
if len==0 then _reset_mark_indic()
else editor:StartStyling(pos,INDICS_MASK) editor:SetStyling(len,0) end
end
function _mark_text_N(fn,mask)
-- mark the selection (see three fns below) or choose style if no selection
local pos,len = _selection_pos_len()
if len==0 then choose_from_menu( mark_names, ",", 113, fn )
else editor:StartStyling(pos,INDICS_MASK) editor:SetStyling(len,mask) end
end
function mark_text_1() _mark_text_N( _set_mark_1, INDIC0_MASK ) end
function mark_text_2() _mark_text_N( _set_mark_2, INDIC1_MASK ) end
function mark_text_3() _mark_text_N( _set_mark_3, INDIC2_MASK ) end
--[[ move_word_left move_word_right ]]
function _exchange_ranges(ls,le,rs,re)
-- exchange ls:le and rs:re, ls<le<rs<re
-- here I do it with selections, probably should be done with regions/ranges
editor:SetSel(ls,le)
local lw = editor:GetSelText()
editor:SetSel(rs,re)
local rw = editor:GetSelText()
editor:ReplaceSel(lw)
editor:SetSel(ls,le)
editor:ReplaceSel(rw)
end
function _is_alnum( n )
-- 'A'..'Z' or 'a'..'z' or '0'..'9' or '_'
return 65<=n and n<=90 or 97<=n and n<=122 or 48<=n and n<=57 or n==95
end
function _move_l_r( init_pos, left )
-- move left or right to the next word
local savecp = editor.CurrentPos
editor.CurrentPos = init_pos
local ch,ps
repeat
ps = editor.CurrentPos
if left then editor:WordLeft() else editor:WordRight() end
if editor.CurrentPos == ps then editor.CurrentPos = savecp; return false end
ch = editor.CharAt[editor.CurrentPos]
until _is_alnum(ch)
return true
end
function move_word_left()
local rs,re = _get_current_word_pos()
if rs==re or rs<1 then return end
if _move_l_r( rs, true ) then
editor:BeginUndoAction()
local ls,le = _get_current_word_pos()
_exchange_ranges(ls,le,rs,re)
editor.CurrentPos = ls; editor:SetSel(ls,ls)
editor:EndUndoAction()
end
end
function move_word_right()
local ls,le = _get_current_word_pos()
if ls==le then return end
if _move_l_r( le, false ) then
editor:BeginUndoAction()
local rs,re = _get_current_word_pos()
_exchange_ranges(ls,le,rs,re)
editor.CurrentPos = re; editor:SetSel(re,re)
editor:EndUndoAction()
end
end
--[[ collect_marked ]]
function collect_marked( to_cut )
-- collect all marked lines -- by Jos van der Zande (JdeB)
editor:BeginUndoAction()
local text = ""
local ml = editor:MarkerNext(0, 2) -- find first bookmarked line
while ml >= 0 do
text = text .. editor:GetLine(ml) -- collect text
ml = editor:MarkerNext(ml+1, 2) -- find next bookmarked line
end
editor:AddText(text) -- paste
if to_cut == "cut" then
ml = editor:MarkerPrevious(editor.LineCount, 2)
while ml >= 0 do
editor:MarkerDelete(ml,-1) -- remove all markers
editor.TargetStart = editor:PositionFromLine(ml)
editor.TargetEnd = editor:PositionFromLine(ml+1)
editor:ReplaceTarget("")
ml = editor:MarkerPrevious(ml-1, 2) -- find prev bookmarked line
end
end
editor:EndUndoAction()
end
--[[ open_favorites ]]
function _open_favorites(f)
if string.len(f)>0 then scite.Open(f) end
end
function open_favorites() -- open favorites
local favs = props["favorites.global"] -- list of files by '|'
if string.len(favs)>0 then
choose_from_menu( favs, '|', 120, _open_favorites )
end
end
--[[ utility ]]
function utility() -- temporary fn for doing some work
-- replace utf-8 symbol encoding \xHH with value bytes
-- 1. selection based
-- 1.1. process text
--~ editor:BeginUndoAction()
--~ local txt = get_sel_or_line()
--~ --
--~ txt = string.gsub( txt, "\\x(%x%x)",
--~ function(x) return string.char(tonumber(x,16)) end )
--~ --
--~ editor:ReplaceSel(txt)
--~ editor:EndUndoAction()
-- 1.2. process lines
--~ local nr=0
--~ local st = editor:PositionFromLine(nr)
--~ local en = editor.LineEndPosition[nr]
--~ local txt
--~ while st <= en do
--~ txt = editor:textrange(st,en)
--~ --print( nr, txt )
--~ nr = nr + 1
--~ st = editor:PositionFromLine(nr)
--~ en = editor.LineEndPosition[nr]
--~ end
end
--[[ hello ]]
function hello(x) -- test fn; '' if called w/o args
if not x or x=='' then x = "world" end
print('Hello, '..x..'!')
end
--[[ OnDoubleClick -- timer ]]
function s2hmst( tm )
-- convert seconds (duration) to "MM:SS.TTT" or "H:MM:SS.TTT"
local hr,mn,sc,ms
sc,ms = math.floor(tm),math.floor(1000*math.mod(tm,1)+0.1)
mn,sc = math.floor(sc/60),math.mod(sc,60)
hr,mn = math.floor(mn/60),math.mod(mn,60)
hr = (hr>0) and string.format("%d:",hr) or ""
return hr..string.format("%02d:%02d.%03d",mn,sc,ms)
end
-- One can build applications with this. Make some dedicated "buttons" and
-- attach some actions to them.
function OnDoubleClick()
local cmd = editor:GetSelText()
if not (cmd=='START' or cmd=='STOP' or cmd=='SHOW') then return false end
-- this example is the simpliest timer
--
-------------------> START STOP SHOW <------------------- dblclick on a word
--
-- Global vars live only while this buffer is active, so we use props
local function _show(msg)
local elapsed = os.clock() - tonumber(props.timer_start)
print(os.date(msg.." %H:%M:%S").." elapsed "..s2hmst(elapsed))
end
if cmd=='START' then
if props.timer_is_counting == "true" then
print("already counting, press SHOW or STOP") return end
props.timer_is_counting = "true"
props.timer_start = tostring(os.clock())
print(string.rep("-",50))
print(os.date("stared %H:%M:%S"))
elseif cmd=='STOP' then
if props.timer_is_counting ~= "true" then
print("first you should start the timer") return end
props.timer_is_counting = "false"
_show("stop'd")
elseif cmd=='SHOW' then
if props.timer_is_counting ~= "true" then
print("first you should start the timer") return end
_show("now is")
end
return false
end
--[[ END ]]
--~ some more or less useful fragments...
function input_box(prompt,default,title)
local txt = 'WScript.Echo InputBox("'..prompt..'","'..title..'","'..default..'")'
local tmp = os.getenv('TEMP').."\\"
local tmp1, tmp2 = tmp.."SCRPT.VBS", tmp.."RESLT.TMP"
print(tmp1,tmp2)
local f = io.open(tmp1, 'wb') f:write(txt) f:close() -- write the file
os.execute("cscript //Nologo "..tmp1.." > "..tmp2) -- execute the file
f = io.open(tmp2) local out = f:read('*all') f:close() -- read output
return out
end
--- print(input_box("How's your name?","","Name!"))
--- CREATE_NO_WINDOW = 134217728 -- 0x08000000 not in 5.0.2
--- os.execute('cmd.exe /c dir >c:\\tmp\\dt','d:\\temp',134217728)
--- os.execute('execdll user32.dll MessageBoxA(0,"Hello","***",64)')
--- rundll32 user32.dll,MessageBeep -- only zero or one parameter
--~ print("SciTE is up "..s2hmst(os.clock()))
--~ function OnOpen( fp ) -- props['FilePath']
--~ if props['ext.lua.backup.on.open'] == 1 then
--~ _back_up_file( fp, props['FileNameExt'] )
--~ end
--- return false
--~ end
--- function OnChar( c ) -- works here too!
--- print('char',c)
--- return false
--~ -- OnChar = function(c) if c=='x' then OnChar=nil else print(c) end return false end
--- end
--- get last part from path fp
--~ local fn
--~ if string.find( fp, "[\\/]" ) then
--~ _,_,fn = string.find( fp, '.*[\\/]([^\\/]+)$' )
--~ else
--~ fn = fp
--~ end
-- require 'C:\\Apps\\SciTE\\file_browser.lua' -- full path must be provided
--~ local formula
--~ local Init =loadlib('C:\\Program Files\\Scintilla Text Editor\\luawin.dll', 'Init')
--~ Init()
--~
--~ function setFormula()
--~ local flag, msg = win.InputBox('Formula: <> as the place holder. e.g. <>*10')
--~ if flag and string.find(msg,'<>',1,true) then
--~ formula = msg
--~ end
--~
--~ if formula then msg = formula else msg = "NONE" end
--~ print("FORMULA: "..msg)
--~
--~ executeFormula()
--~ end
--~ function SciteListAllOccurances()
--~ if props.CurrentSelection ~= "" then
--~ for m in editor:match( "^.*" .. props.CurrentSelection .. ".*$", SCFIND_REGEXP, 0) do
--~ print(props.FileNameExt .. ":" .. (editor:LineFromPosition(m.pos)+1) .. ":" .. m.text);
--~ end
--~ else
--~ alert("The InternalGrep script only searchs for selected text");
--~ end
--~ end
--~ Also available:
--~ props.CurrentSelection
--~ props.CurrentWord
--~ props.SelectionStartLine
--~ props.SelectionStartColumn
--~ props.SelectionEndLine
--~ props.SelectionEndColumn
--~ -- goto file being 'require'd
--~ function goto_required()
--~ local line = editor:GetLine(
--~ editor:LineFromPosition(editor.CurrentPos) )
--~ local _, _, _, filename = string.find(line,
--~ '^.*require%s*([\'"])(.-)%1.*$')
--~ for path in string.gfind(LUA_PATH..';', '(.-);') do
--~ path = string.gsub(path, '?', filename)
--~ local f = io.open(path)
--~ if f then f:close() scite.Open(path) break end
--~ end
--~ end
--- editor.MouseDwellTime = 1000
--[[ EOF ]]