/extman/extman.lua
Lua | 896 lines | 743 code | 84 blank | 69 comment | 119 complexity | 2893d58b2886ad899cbb40ef16a67ab6 MD5 | raw file
Possible License(s): ISC
1-- Extman is a Lua script manager for SciTE. It enables multiple scripts to capture standard events 2-- without interfering with each other. For instance, scite_OnDoubleClick() will register handlers 3-- for scripts that need to know when a double-click event has happened. (To know whether it 4-- was in the output or editor pane, just test editor.Focus). It provides a useful function scite_Command 5-- which allows you to define new commands without messing around with property files (see the 6-- examples in the scite_lua directory.) 7-- extman defines three new convenience handlers as well: 8--scite_OnWord (called when user has entered a word) 9--scite_OnEditorLine (called when a line is entered into the editor) 10--scite_OnOutputLine (called when a line is entered into the output pane) 11 12-- this is an opportunity for you to make regular Lua packages available to SciTE 13--~ package.path = package.path..';C:\\lang\\lua\\lua\\?.lua' 14--~ package.cpath = package.cpath..';c:\\lang\\lua\\?.dll' 15 16package.cpath = package.cpath..';c:\\lua\\clibs\\?.dll' 17 18 19 20-- useful function for getting a property, or a default if not present. 21function scite_GetProp(key,default) 22 local val = props[key] 23 if val and val ~= '' then return val 24 else return default end 25end 26 27function scite_GetPropBool(key,default) 28 local res = scite_GetProp(key,default) 29 if not res or res == '0' or res == 'false' then return false 30 else return true 31 end 32end 33 34local GTK = scite_GetProp('PLAT_GTK') 35 36local _MarginClick,_DoubleClick,_SavePointLeft = {},{},{} 37local _SavePointReached,_Open,_SwitchFile = {},{},{} 38local _BeforeSave,_Save,_Char = {},{},{} 39local _Word,_LineEd,_LineOut = {},{},{} 40local _OpenSwitch = {} 41local _UpdateUI = {} 42local _UserListSelection 43-- new with 1.74! 44local _Key = {} 45local _DwellStart = {} 46local _Close = {} 47-- new 48local _remove = {} 49local append = table.insert 50local find = string.find 51local size = table.getn 52local sub = string.sub 53local gsub = string.gsub 54 55 56-- file must be quoted if it contains spaces! 57function quote_if_needed(target) 58 local quote = '"' 59 if find(target,'%s') and sub(target,1,1) ~= quote then 60 target = quote..target..quote 61 end 62 return target 63end 64 65function OnUserListSelection(tp,str) 66 if _UserListSelection then 67 local callback = _UserListSelection 68 _UserListSelection = nil 69 return callback(str) 70 else return false end 71end 72 73local function DispatchOne(handlers,arg) 74 for i,handler in pairs(handlers) do 75 local fn = handler 76 if _remove[fn] then 77 handlers[i] = nil 78 _remove[fn] = nil 79 end 80 local ret = fn(arg) 81 if ret then return ret end 82 end 83 return false 84end 85 86local function Dispatch4(handlers,arg1,arg2,arg3,arg4) 87 for i,handler in pairs(handlers) do 88 local fn = handler 89 if _remove[fn] then 90 handlers[i] = nil 91 _remove[fn] = nil 92 end 93 local ret = fn(arg1,arg2,arg3,arg4) 94 if ret then return ret end 95 end 96 return false 97end 98 99DoDispatchOne = DispatchOne -- export this! 100 101-- these are the standard SciTE Lua callbacks - we use them to call installed extman handlers! 102function OnMarginClick() 103 return DispatchOne(_MarginClick) 104end 105 106function OnDoubleClick() 107 return DispatchOne(_DoubleClick) 108end 109 110function OnSavePointLeft() 111 return DispatchOne(_SavePointLeft) 112end 113 114function OnSavePointReached() 115 return DispatchOne(_SavePointReached) 116end 117 118function OnChar(ch) 119 return DispatchOne(_Char,ch) 120end 121 122function OnSave(file) 123 return DispatchOne(_Save,file) 124end 125 126function OnBeforeSave(file) 127 return DispatchOne(_BeforeSave,file) 128end 129 130function OnSwitchFile(file) 131 return DispatchOne(_SwitchFile,file) 132end 133 134function OnOpen(file) 135 return DispatchOne(_Open,file) 136end 137 138function OnUpdateUI() 139 if editor.Focus then 140 return DispatchOne(_UpdateUI) 141 else 142 return false 143 end 144end 145 146-- new with 1.74 147function OnKey(key,shift,ctrl,alt) 148 return Dispatch4(_Key,key,shift,ctrl,alt) 149end 150 151function OnDwellStart(pos,s) 152 return Dispatch4(_DwellStart,pos,s) 153end 154 155function OnClose() 156 return DispatchOne(_Close) 157end 158 159-- may optionally ask that this handler be immediately 160-- removed after it's called 161local function append_unique(tbl,fn,rem) 162 local once_only 163 if type(fn) == 'string' then 164 once_only = fn == 'once' 165 fn = rem 166 rem = nil 167 if once_only then 168 _remove[fn] = fn 169 end 170 else 171 _remove[fn] = nil 172 end 173 local idx 174 for i,handler in pairs(tbl) do 175 if handler == fn then idx = i; break end 176 end 177 if idx then 178 if rem then 179 table.remove(tbl,idx) 180 end 181 else 182 if not rem then 183 append(tbl,fn) 184 end 185 end 186end 187ex_append_unique = append_unique 188 189-- this is how you register your own handlers with extman 190function scite_OnMarginClick(fn,rem) 191 append_unique(_MarginClick,fn,rem) 192end 193 194function scite_OnDoubleClick(fn,rem) 195 append_unique(_DoubleClick,fn,rem) 196end 197 198function scite_OnSavePointLeft(fn,rem) 199 append_unique(_SavePointLeft,fn,rem) 200end 201 202function scite_OnSavePointReached(fn,rem) 203 append_unique(_SavePointReached,fn,rem) 204end 205 206function scite_OnOpen(fn,rem) 207 append_unique(_Open,fn,rem) 208end 209 210function scite_OnSwitchFile(fn,rem) 211 append_unique(_SwitchFile,fn,rem) 212end 213 214function scite_OnBeforeSave(fn,rem) 215 append_unique(_BeforeSave,fn,rem) 216end 217 218function scite_OnSave(fn,rem) 219 append_unique(_Save,fn,rem) 220end 221 222function scite_OnUpdateUI(fn,rem) 223 append_unique(_UpdateUI,fn,rem) 224end 225 226function scite_OnChar(fn,rem) 227 append_unique(_Char,fn,rem) 228end 229 230function scite_OnOpenSwitch(fn,rem) 231 append_unique(_OpenSwitch,fn,rem) 232end 233 234--new 1.74 235function scite_OnKey(fn,rem) 236 append_unique(_Key,fn,rem) 237end 238 239function scite_OnDwellStart(fn,rem) 240 append_unique(_DwellStart,fn,rem) 241end 242 243function scite_OnClose(fn,rem) 244 append_unique(_Close,fn,rem) 245end 246 247local function buffer_switch(f) 248--- OnOpen() is also called if we move to a new folder 249 if not find(f,'[\\/]$') then 250 DispatchOne(_OpenSwitch,f) 251 end 252end 253 254scite_OnOpen(buffer_switch) 255scite_OnSwitchFile(buffer_switch) 256 257local next_user_id = 13 -- arbitrary 258 259-- the handler is always reset! 260function scite_UserListShow(list,start,fn) 261 local separators = {' ', ';', '@', '?', '~', ':'} 262 local separator 263 local s = table.concat(list) 264 for i, sep in ipairs(separators) do 265 if not string.find(s, sep, 1, true) then 266 s = table.concat(list, sep, start) 267 separator = sep 268 break 269 end 270 end 271 -- we could not find a good separator, set it arbitrarily 272 if not separator then 273 separator = '@' 274 s = table.concat(list, separator, start) 275 end 276 _UserListSelection = fn 277 local pane = editor 278 if not pane.Focus then pane = output end 279 pane.AutoCSeparator = string.byte(separator) 280 pane:UserListShow(next_user_id,s) 281 pane.AutoCSeparator = string.byte(' ') 282 return true 283end 284 285 local word_start,in_word,current_word 286-- (Nicolas) this is in Ascii as SciTE always passes chars in this "encoding" to OnChar 287local wordchars = '[A-Za-z�-��-�]' -- wuz %w 288 289 local function on_word_char(s) 290 if not in_word then 291 if find(s,wordchars) then 292 -- we have hit a word! 293 word_start = editor.CurrentPos 294 in_word = true 295 current_word = s 296 end 297 else -- we're in a word 298 -- and it's another word character, so collect 299 if find(s,wordchars) then 300 current_word = current_word..s 301 else 302 -- leaving a word; call the handler 303 local word_end = editor.CurrentPos 304 DispatchOne(_Word, {word=current_word, 305 startp=word_start,endp=editor.CurrentPos, 306 ch = s 307 }) 308 in_word = false 309 end 310 end 311 -- don't interfere with usual processing! 312 return false 313 end 314 315function scite_OnWord(fn,rem) 316 append_unique(_Word,fn,rem) 317 if not rem then 318 scite_OnChar(on_word_char) 319 else 320 scite_OnChar(on_word_char,'remove') 321 end 322end 323 324local last_pos = 0 325 326function get_line(pane,lineno) 327 if not pane then pane = editor end 328 if not lineno then 329 local line_pos = pane.CurrentPos 330 lineno = pane:LineFromPosition(line_pos)-1 331 end 332 -- strip linefeeds (Windows is a special case as usual!) 333 local endl = 2 334 if pane.EOLMode == 0 then endl = 3 end 335 local line = pane:GetLine(lineno) 336 if not line then return nil end 337 return string.sub(line,1,-endl) 338end 339 340-- export this useful function... 341scite_Line = get_line 342 343local function on_line_char(ch,was_output) 344 if ch == '\n' then 345 local in_editor = editor.Focus 346 if in_editor and not was_output then 347 DispatchOne(_LineEd,get_line(editor)) 348 return false -- DO NOT interfere with any editor processing! 349 elseif not in_editor and was_output then 350 DispatchOne(_LineOut,get_line(output)) 351 return true -- prevent SciTE from trying to evaluate the line 352 end 353 end 354 return false 355end 356 357local function on_line_editor_char(ch) 358 return on_line_char(ch,false) 359end 360 361local function on_line_output_char(ch) 362 return on_line_char(ch,true) 363end 364 365local function set_line_handler(fn,rem,handler,on_char) 366 append_unique(handler,fn,rem) 367 if not rem then 368 scite_OnChar(on_char) 369 else 370 scite_OnChar(on_char,'remove') 371 end 372end 373 374function scite_OnEditorLine(fn,rem) 375 set_line_handler(fn,rem,_LineEd,on_line_editor_char) 376end 377 378-- with this scheme, there is a primary handler, and secondary prompt handlers 379-- can temporarily take charge of input. There is only one prompt in charge 380-- at any particular time, however. 381local primary_handler 382 383function scite_OnOutputLine(fn,rem) 384 if not rem then 385 if not primary_handler then primary_handler = fn end 386 end 387 _LineOut = {} 388 set_line_handler(fn,rem,_LineOut,on_line_output_char) 389 if rem and fn ~= primary_handler then 390 set_line_handler(primary_handler,false,_LineOut,on_line_output_char) 391 end 392end 393 394local path_pattern 395local tempfile 396local dirsep 397 398if GTK then 399 tempfile = '/tmp/.scite-temp-files' 400 path_pattern = '(.*)/[^%./]+%.%w+$' 401 dirsep = '/' 402else 403 tempfile = os.getenv 'TMP' .. '\\scite_temp1' 404 path_pattern = '(.*)[\\/][^%.\\/]+%.%w+$' 405 dirsep = '\\' 406end 407 408function path_of(s) 409 local _,_,res = find(s,path_pattern) 410 if _ then return res else return s end 411end 412 413local extman_path = path_of(props['ext.lua.startup.script']) 414local lua_path = scite_GetProp('ext.lua.directory',extman_path..dirsep..'scite_lua') 415props['ext.lua.directory'] = lua_path:gsub('[\\/]$', '') 416 417fn,err = package.loadlib(extman_path.."/gui.dll","luaopen_gui") 418if fn then fn() else 419 --DISABLED:print(err) 420end 421 422 423function extman_Path() 424 return extman_path 425end 426 427-- this version of scite-gdb uses the new spawner extension library. 428local fn,err,spawner_path 429if package then loadlib = package.loadlib end 430-- by default, the spawner lib sits next to extman.lua 431spawner_path = scite_GetProp('spawner.extension.path',extman_path) 432if GTK then 433 fn,err = loadlib(spawner_path..'/unix-spawner-ex.so','luaopen_spawner') 434else 435 fn,err = loadlib(spawner_path..'\\spawner-ex.dll','luaopen_spawner') 436end 437if fn then 438 fn() -- register spawner 439else 440 --DISABLED: print('cannot load spawner '..err) 441end 442 443-- a general popen function that uses the spawner library if found; otherwise falls back 444-- on os.execute 445function scite_Popen(cmd) 446 if spawner then 447 return spawner.popen(cmd) 448 else 449 cmd = cmd..' > '..tempfile 450 if GTK then -- io.popen is dodgy; don't use it! 451 os.execute(cmd) 452 else 453 if Execute then -- scite_other was found! 454 Execute(cmd) 455 else 456 os.execute(cmd) 457 end 458 end 459 return io.open(tempfile) 460 end 461end 462 463function dirmask(mask,isdir) 464 local attrib = '' 465 if isdir then 466 if not GTK then 467 attrib = ' /A:D ' 468 else 469 attrib = ' -F ' 470 end 471 end 472 if not GTK then 473 mask = gsub(mask,'/','\\') 474 return 'dir /b '..attrib..quote_if_needed(mask) 475 else 476 return 'ls -1 '..attrib..quote_if_needed(mask) 477 end 478end 479 480-- p = globtopattern(g) 481-- 482-- Converts glob string (g) into Lua pattern string (p). 483-- Always succeeds. 484-- 485-- Warning: could be better tested. 486-- 487-- (c) 2008 D.Manura, Licensed under the same terms as Lua (MIT License). 488local function globtopattern(g) 489 -- Some useful references: 490 -- - apr_fnmatch in Apache APR. For example, 491 -- http://apr.apache.org/docs/apr/1.3/group__apr__fnmatch.html 492 -- which cites POSIX 1003.2-1992, section B.6. 493 494 local p = "^" -- pattern being built 495 local i = 0 -- index in g 496 local c -- char at index i in g. 497 498 -- unescape glob char 499 local function unescape() 500 if c == '\\' then 501 i = i + 1; c = g:sub(i,i) 502 if c == '' then 503 p = '[^]' 504 return false 505 end 506 end 507 return true 508 end 509 510 -- escape pattern char 511 local function escape(c) 512 return c:match("^%w$") and c or '%' .. c 513 end 514 515 -- Convert tokens at end of charset. 516 local function charset_end() 517 while 1 do 518 if c == '' then 519 p = '[^]' 520 break 521 elseif c == ']' then 522 p = p .. ']' 523 break 524 else 525 if not unescape() then break end 526 local c1 = c 527 i = i + 1; c = g:sub(i,i) 528 if c == '' then 529 p = '[^]' 530 break 531 elseif c == '-' then 532 i = i + 1; c = g:sub(i,i) 533 if c == '' then 534 p = '[^]' 535 break 536 elseif c == ']' then 537 p = p .. escape(c1) .. '%-]' 538 break 539 else 540 if not unescape() then break end 541 p = p .. escape(c1) .. '-' .. escape(c) 542 end 543 elseif c == ']' then 544 p = p .. escape(c1) .. ']' 545 break 546 else 547 p = p .. escape(c1) 548 i = i - 1 -- put back 549 end 550 end 551 i = i + 1; c = g:sub(i,i) 552 end 553 end 554 555 -- Convert tokens in charset. 556 local function charset() 557 p = p .. '[' 558 i = i + 1; c = g:sub(i,i) 559 if c == '' or c == ']' then 560 p = p .. '[^]' 561 elseif c == '^' or c == '!' then 562 p = p .. '^' 563 i = i + 1; c = g:sub(i,i) 564 if c == ']' then 565 -- ignored 566 else 567 charset_end() 568 end 569 else 570 charset_end() 571 end 572 end 573 574 -- Convert tokens. 575 while 1 do 576 i = i + 1; c = g:sub(i,i) 577 if c == '' then 578 p = p .. '$' 579 break 580 elseif c == '?' then 581 p = p .. '.' 582 elseif c == '*' then 583 p = p .. '.*' 584 elseif c == '[' then 585 charset() 586 elseif c == '\\' then 587 i = i + 1; c = g:sub(i,i) 588 if c == '' then 589 p = p .. '\\$' 590 break 591 end 592 p = p .. escape(c) 593 else 594 p = p .. escape(c) 595 end 596 end 597 return p 598end 599 600-- grab all files matching @mask, which is assumed to be a path with a wildcard. 601-- 2008-06-27 Now uses David Manura's globtopattern(), which is not fooled by cases 602-- like test.lua and test.lua~ ! 603function scite_Files(mask) 604 local f,path,pat,cmd,_ 605 if not GTK then 606 cmd = dirmask(mask) 607 path = mask:match('(.*\\)') or '.\\' 608 local file = mask:match('([^\\]*)$') 609 pat = globtopattern(file) 610 else 611 cmd = 'ls -1 '..mask 612 path = '' 613 end 614 f = scite_Popen(cmd) 615 local files = {} 616 if not f then return files end 617 618 for line in f:lines() do 619 if not pat or line:match(pat) then 620 append(files,path..line) 621 end 622 end 623 f:close() 624 return files 625end 626 627-- grab all directories in @path, excluding anything that matches @exclude_path 628-- As a special exception, will also any directory called 'examples' ;) 629function scite_Directories(path,exclude_pat) 630 local cmd 631 --print(path) 632 if not GTK then 633 cmd = dirmask(path..'\\*.',true) 634 else 635 cmd = dirmask(path,true) 636 end 637 path = path..dirsep 638 local f = scite_Popen(cmd) 639 local files = {} 640 if not f then return files end 641 for line in f:lines() do 642-- print(line) 643 if GTK then 644 if line:sub(-1,-1) == dirsep then 645 line = line:sub(1,-2) 646 else 647 line = nil 648 end 649 end 650 if line and not line:find(exclude_pat) and line ~= 'examples' then 651 append(files,path..line) 652 end 653 end 654 f:close() 655 return files 656end 657 658function scite_FileExists(f) 659 local f = io.open(f) 660 if not f then return false 661 else 662 f:close() 663 return true 664 end 665end 666 667function scite_CurrentFile() 668 return props['FilePath'] 669end 670 671-- (Nicolas) 672if GTK then 673 function scite_DirectoryExists(path) 674 local result = os.execute('test -d "'..path..'"') 675 if result == -1 then return true end -- FIX: why this return -1 on SciTE 2.2.5/Ubuntu? 676 return result == 0 677 end 678else 679 -- what is the Win32 equivalent?? 680 function scite_DirectoryExists(path) 681 return true 682 end 683end 684 685function split(s,delim) 686 res = {} 687 while true do 688 p = find(s,delim) 689 if not p then 690 append(res,s) 691 return res 692 end 693 append(res,sub(s,1,p-1)) 694 s = sub(s,p+1) 695 end 696end 697 698function splitv(s,delim) 699 return unpack(split(s,delim)) 700end 701 702local idx = 10 703local shortcuts_used = {} 704local alt_letter_map = {} 705local alt_letter_map_init = false 706local name_id_map = {} 707 708local function set_command(name,cmd,mode) 709 local _,_,pattern,md = find(mode,'(.+){(.+)}') 710 if not _ then 711 pattern = mode 712 md = 'savebefore:no' 713 end 714 local which = '.'..idx..pattern 715 props['command.name'..which] = name 716 props['command'..which] = cmd 717 props['command.subsystem'..which] = '3' 718 props['command.mode'..which] = md 719 name_id_map[name] = 1100+idx 720 return which 721end 722 723local function check_gtk_alt_shortcut(shortcut,name) 724 -- Alt+<letter> shortcuts don't work for GTK, so handle them directly... 725 local _,_,letter = shortcut:find('Alt%+([A-Z])$') 726 if _ then 727 alt_letter_map[letter:lower()] = name 728 if not alt_letter_map_init then 729 alt_letter_map_init = true 730 scite_OnKey(function(key,shift,ctrl,alt) 731 if alt and key < 255 then 732 local ch = string.char(key) 733 if alt_letter_map[ch] then 734 scite_MenuCommand(alt_letter_map[ch]) 735 end 736 end 737 end) 738 end 739 end 740end 741 742local function set_shortcut(shortcut,name,which) 743 if shortcut == 'Context' then 744 local usr = 'user.context.menu' 745 if props[usr] == '' then -- force a separator 746 props[usr] = '|' 747 end 748 props[usr] = props[usr]..'|'..name..'|'..(1100+idx)..'|' 749 else 750 local cmd = shortcuts_used[shortcut] 751 if cmd then 752 print('Error: shortcut already used in "'..cmd..'"') 753 else 754 shortcuts_used[shortcut] = name 755 if GTK then check_gtk_alt_shortcut(shortcut,name) end 756 props['command.shortcut'..which] = shortcut 757 end 758 end 759end 760 761-- allows you to bind given Lua functions to shortcut keys 762-- without messing around in the properties files! 763-- Either a string or a table of strings; the string format is either 764-- menu text|Lua command|shortcut 765-- or 766-- menu text|Lua command|mode|shortcut 767-- where 'mode' is the file extension which this command applies to, 768-- e.g. 'lua' or 'c', optionally followed by {mode specifier}, where 'mode specifier' 769-- is the same as documented under 'command.mode' 770-- 'shortcut' can be a usual SciTE key specifier, like 'Alt+R' or 'Ctrl+Shift+F1', 771-- _or_ it can be 'Context', meaning that the menu item should also be added 772-- to the right-hand click context menu. 773function scite_Command(tbl) 774 if type(tbl) == 'string' then 775 tbl = {tbl} 776 end 777 for i,v in pairs(tbl) do 778 local name,cmd,mode,shortcut = splitv(v,'|') 779 if not shortcut then 780 shortcut = mode 781 mode = '.*' 782 else 783 mode = '.'..mode 784 end 785 -- has this command been defined before? 786 local old_idx = 0 787 for ii = 10,idx do 788 if props['command.name.'..ii..mode] == name then old_idx = ii end 789 end 790 if old_idx == 0 then 791 local which = set_command(name,cmd,mode) 792 if shortcut then 793 set_shortcut(shortcut,name,which) 794 end 795 idx = idx + 1 796 end 797 end 798end 799 800 801-- use this to launch Lua Tool menu commands directly by name 802-- (commands are not guaranteed to work properly if you just call the Lua function) 803function scite_MenuCommand(cmd) 804 if type(cmd) == 'string' then 805 cmd = name_id_map[cmd] 806 if not cmd then return end 807 end 808 scite.MenuCommand(cmd) 809end 810 811local loaded = {} 812local current_filepath 813 814-- this will quietly fail.... 815local function silent_dofile(f) 816 if scite_FileExists(f) then 817 if not loaded[f] then 818 dofile(f) 819 loaded[f] = true 820 end 821 return true 822 end 823 return false 824end 825 826function scite_dofile(f) 827 f = extman_path..'/'..f 828 silent_dofile(f) 829end 830 831function scite_require(f) 832 local path = lua_path..dirsep..f 833 if not silent_dofile(path) then 834 silent_dofile(current_filepath..dirsep..f) 835 end 836end 837 838if not GTK then 839 scite_dofile 'scite_other.lua' 840end 841 842if not scite_DirectoryExists(lua_path) then 843 print('Error: directory '..lua_path..' not found') 844 return 845end 846 847function load_script_list(script_list,path) 848 if not script_list then 849 print('Error: no files found in '..path) 850 else 851 current_filepath = path 852 for i,file in pairs(script_list) do 853 silent_dofile(file) 854 end 855 end 856end 857 858-- Load all scripts in the lua_path (usually 'scite_lua'), including within any subdirectories 859-- that aren't 'examples' or begin with a '_' 860local script_list = scite_Files(lua_path..dirsep..'*.lua') 861load_script_list(script_list,lua_path) 862local dirs = scite_Directories(lua_path,'^_') 863for i,dir in ipairs(dirs) do 864 load_script_list(scite_Files(dir..dirsep..'*.lua'),dir) 865end 866 867function scite_WordAtPos(pos) 868 if not pos then pos = editor.CurrentPos end 869 local p2 = editor:WordEndPosition(pos,true) 870 local p1 = editor:WordStartPosition(pos,true) 871 if p2 > p1 then 872 return editor:textrange(p1,p2) 873 end 874end 875 876function scite_GetSelOrWord() 877 local s = editor:GetSelText() 878 if s == '' then 879 return scite_WordAtPos() 880 else 881 return s 882 end 883end 884 885--~ scite_Command 'Reload Script|reload_script|Shift+Ctrl+R' 886 887--~ function reload_script() 888--~ current_file = scite_CurrentFile() 889--~ print('Reloading... '..current_file) 890--~ loaded[current_file] = false 891--~ silent_dofile(current_file) 892--~ end 893 894--~ require"remdebug.engine" 895--~ remdebug.engine.start() 896