_G
(со всеми вложенностями).Стоя в редакторе на строке, например, APanel.Cu нажимаем
CtrlShiftSpace
и получаем меню из двух вариантов - CurrPos и Current; Enter
вставляет в строку выбранный вариант, начиная с третьего символа . А для особо ленивых на пустой строке набираете AP - CtrlShiftSpace
- меню из одного варианта APanel - Enter
набираем точку, Cu - CtrlShiftSpace - получаем то, что выше.В настоящее время для получения списка ключевых слов используется скрипт LuaCheck, модуль luacheck.builtin_standards (подраздел возвращаемой таблицы max).
- ----[[*D*]]local TabToStr=require("Bax.TabUtils").TableToString
- --local BaxUtils=require"Bax.BaxUtils"
- --[[
- LuaComplete - завершение слов языка. Версия 2 от 19.05.2018
- Подстановка ключевых слов и известных идентификаторов из _G.
- Список ключевых слов пока получаю из модуля luacheck.builtin_standards
- Макрос повешен на CtrlShiftSpace.
- Как это использовать:
- Встаёте на слове или на пустом месте. Во втором случае будет выведен
- список всех ключевых слов и идентификаторов из _G первого уровня вложенности.
- Если курсор установлен на слове (или в конце) - список фильтруется по введённой
- части слова.
- Если слово над курсором является именем поля (или свойства) таблицы, то поиск ограничен
- этой таблицей.
- Примеры (положение курсора отмечено символом ).
- e -- будет выведено 3 ключевыз слова (else, elseif и end) и 5 таблиц (editor,...,export)
- far. -- Список полей и функций таблицы far
- far.Message -- список из Menu и Message, первоначальное позиционирование на Message.
- При этом если Вы выберете Menu и нажмёте [Enter], то слово Message будет заменено на Menu;
- для выбора можно сразу нажать "(" - в текст сразу будет занесено "Menu("
- Особо отмечу удобство поиска флагов (far.Flags.DI_)
- Если выбор варианта сделать CtrlEnter-ом, то слово будет не заменено, а вставлено. Что странно...
- В меню выбора работают буквенно-цифровые кнопкм и BackSpace - наложение фильтра.
- Версия 3.
- 1. Сделана настройка.
- 2. Добавлена возможность поиска без учёта регистра. Инициируется, если "точный" поиск не дал результата
- 3. Добавлен поиск слова (в таблицах). Поиск регистронезависимый. Инициируется при неудаче остальных либо
- по отдельной "горячей" кнопке (по умолчанию - AltShiftSpace)
- --]]
- local function Settings()
- return
- {
- Key='CtrlShiftSpace'; -- Вызов макроса
- KeyAdd='CtrlEnter'; -- Выбор со вставкой
- KeyLastWord = 'AltShiftSpace'; -- Поиск последего слова ВЕЗДЕ.
- CaseSens=true; -- Искать точное совпадение
- CaseIgnore=true; -- Искать ли регистронезависимо, если точное ненайдено или не искалось
- AnywhereSearch=true -- Искать ли по последнему слову, если при предыдущих поисках не найдено.
- }
- end
- -- Процедура "слепливания" настройки по умолчанию с заданной
- local function MergeSettings(Old, New)
- if type(New) == 'function' then
- local _
- _, New = pcall(New)
- end
- if type(New) == 'table' then
- for i,v in pairs(New) do
- Old[i]=v
- end
- end
- return Old
- end
- -- Настройка - там же, но с расширением cfg
- local S=MergeSettings( Settings(), loadfile((...):match("(.*)%.lua")..'.cfg') )
- local _,builtin_standards=pcall(require, "luacheck.builtin_standards")
- local macroCheck = {
- [Area or 1]=1, [APanel or 1]=1, [PPanel or 1]=1, [CmdLine or 1]=1,
- [Dlg or 1]=1, [Drv or 1]=1, [Editor or 1]=1, [Far or 1]=1, [Help or 1]=1,
- [Menu or 1]=1, [Mouse or 1]=1, [Object or 1]=1, [Viewer or 1]=1,
- }
- local asCurr={}
- local xWas={}
- local function AddPath(t, pref, nn, vv, subfield)
- local function _aiFind(tbl, sample)
- for _,w in ipairs(tbl) do
- if (type(w) == type(sample)) and
- (w == sample) then
- return true
- end
- end
- end
- local s
- if type(nn) == 'string' and nn ~= '' then
- s=(pref=='' and '' or pref..'.') .. nn
- t[#t+1] = {text=s; TEXT=s:upper()}
- else
- s = ''
- end
- if type(vv) == 'table' and not _aiFind(xWas, vv) then
- xWas[#xWas+1] = vv
- if subfield and vv[subfield] then
- for n,v in pairs(vv[subfield]) do
- AddPath(t, s, n, v, subfield)
- end
- if macroCheck[vv[subfield]] and vv[subfield].properties then
- for n,v in pairs(vv[subfield].properties) do
- AddPath(t, s, n, v)
- end
- end
- else
- for n,v in pairs(vv) do
- AddPath(t, s, n, v)
- end
- if macroCheck[vv] and vv.properties then
- for n, v in pairs(vv.properties) do
- AddPath(t, s, n, v)
- end
- end
- end
- end
- end -- AddPath
- local MenuId="93A8469D-6047-492F-BFFD-9D62801BB18C"
- local function DoSearch(items, Str0, Str99)
- local sWas, macros, c='', {}
- for i=1,255 do
- c = mf.chr(i):upper()
- if (not sWas:find(c,1,true)) and c:match"[%w_]" then
- sWas = sWas.. c
- macros[#macros+1] = {pcall(far.MacroAdd, 'MACROAREA_MENU', 0,
- c,
- [[
- local FilterStr = Menu.FilterStr(0) or ''
- Menu.FilterStr( 1, FilterStr.. akey(1,1) )
- Menu.Filter(1,1)
- ]]
- ,'FilterStr ++ '..c,
- function() return Menu.Id == MenuId end
- )}
- end
- end
- macros[#macros+1] = {pcall(far.MacroAdd,'MACROAREA_MENU', 0,
- 'BS',
- [[
- local FilterStr = Menu.FilterStr(0) or ''
- if FilterStr:len() > 1 then
- Menu.Filter(1,0)
- Menu.FilterStr(1, FilterStr:sub(1,FilterStr:len()-1))
- Menu.Filter(1,1)
- else
- Menu.Filter(0,0)
- end
- ]], 'FilterStr <- (BS)',
- function() return Menu.Id == MenuId end
- )}
- local Res,Ch=far.Menu({Id=win.Uuid(MenuId); Title="Выберите элемент для вставки";
- Bottom="Буква - фильтр; "..S.KeyAdd.."-Вставить; Enter,символ-заменить"
- },
- items,
- S.KeyAdd..[[ Space ! " # $ % & ' ( ) * + , - . / : ; < = > ? @]])
- for i=#macros,1,-1 do if macros[i][1] then far.MacroDelete(macros[i][2]) end end
- local sNew
- if Ch then
- if Res.BreakKey then
- if Res.BreakKey == S.KeyAdd then
- print(items[Ch].result or items[Ch].text)
- else
- sNew = (items[Ch].FullPath or items[Ch].result or items[Ch].text)..Res.BreakKey
- end
- else -- [Enter]
- sNew = items[Ch].FullPath or items[Ch].result or items[Ch].text
- end
- if sNew then
- Editor.SetStr(Str0..sNew.. Str99)
- end
- end
- end -- DoSearch
- local function GetFromEdit()
- local Str, xPos=Editor.GetStr(), Editor.RealPos
- local Str1=Str:sub(1,xPos-1) or ''
- local Str0, ForSearch
- if Str1:sub(-1) == '.' then -- Кончается на точку
- Str0, ForSearch = Str1:match('(.-)([%w_%.]+)%.$')
- Str0 = Str0 or ''
- ForSearch = (ForSearch or '') ..'.'
- else
- Str0, ForSearch = Str1:match('(.-)([%w_%.]+)$')
- Str0 = Str0 or ''
- ForSearch = ForSearch or ''
- end
- local LastWord, Str99=Str:sub(xPos):match('([%w_]*)(.*)')
- if ForSearch:match"%." then -- Содержит точку. Конец пристыковываю к началу LastWord-а
- LastWord = ForSearch:match('([^%.]*)$') .. LastWord
- else
- LastWord = ForSearch..LastWord
- end
- return Str0, Str99, ForSearch, LastWord
- end -- GetFromEdit
- Macro{
- -- id="";
- area="Editor";
- key=S.Key; --"CtrlShiftSpace";
- description="(Old) Подстановка известных слов";
- filemask="*.lua,*.moon,*.fmlua";
- flags="";
- -- priority=50;
- sortpriority=50;
- -- condition=function(key) return true end;
- action=function()
- xWas, asCurr = {}, {}
- AddPath(asCurr, '', '', _G, nil)
- if type(builtin_standards) == 'table' then
- AddPath(asCurr, '', '', builtin_standards.max.read_globals, 'fields')
- end
- table.sort(asCurr, function(a1,a2) return a1.text < a2.text end)
- for i=#asCurr,2,-1 do
- if asCurr[i].text == asCurr[i-1].text then
- table.remove(asCurr, i)
- end
- end
- -- Вычленение текста
- local Str0, Str99, ForSearch, LastWord = GetFromEdit()
- -- Тут: ForSearch - Строка для поиска; LastWord - слово для позиционирования
- -- Поиск по сортированному массиву
- local items={}
- local function FillMenu(aForSearch, Title, LastWord, IgnoreCase, IncludePath)
- local i0, i1, i=1,#asCurr
- local ForSearch=IgnoreCase and aForSearch:upper() or aForSearch
- local Fld=IgnoreCase and 'TEXT' or 'text'
- i = math.floor((i1+i0)/2)
- while i1 > i0 + 1 do
- if asCurr[i][Fld] < ForSearch then
- i0 = i
- elseif asCurr[i][Fld] > ForSearch then
- i1 = i
- else
- break
- end
- i = math.floor((i1+i0)/2)
- end
- if i > 1 and asCurr[i][Fld]:sub(1,ForSearch:len()) < ForSearch then i = i + 1 end
- local bWas=false
- local Tail
- local Last=''
- for j=i,#asCurr do
- if asCurr[j][Fld]:sub(1,ForSearch:len()) == ForSearch then -- Начинается с искомого
- if not bWas or asCurr[j][Fld]:sub(1,Last:len()) ~= Last then
- -- Сверяю с предыдущим, чтоб не было повтора
- Tail = asCurr[j][Fld]:sub(ForSearch:len())
- if Tail:sub(1,1) == '.' then Tail = Tail:sub(2) end
- if Tail:gsub('[^.]',''):len() <= 1 then -- Не более одной точки после найденной
- if not bWas and Title then
- items[#items+1] = {text=Title; separator=true}
- bWas = true
- end
- items[#items+1] = {text=asCurr[j].text:match('[^.]-$'); result=asCurr[j].text:sub(aForSearch:len()+1)}
- if IncludePath then items[#items].FullPath=asCurr[j].text end
- if (LastWord ~= '') and (items[#items].text == LastWord) then
- items[#items].selected = true
- end
- Last = asCurr[j][Fld] .. '.'
- end
- end
- elseif asCurr[j][Fld]:sub(1,ForSearch:len()) > ForSearch then
- break
- end
- end -- for j=i,#asCurr
- return bWas
- end -- FillMenu
- if not ForSearch:match('%.') then
- -- Если в искомой строке нет точки - добавлю ключевые слова
- FillMenu('package.loaded.moonscript.data.lua_keywords.'..ForSearch, 'Ключевые слова LUA', LastWord, false, false)
- end
- if ForSearch:sub(1,3) == '_G.' then
- ForSearch = ForSearch:sub(4)
- end
- if ForSearch == '.' then
- far.Message("Поддерживаются только конструкции,\nсостоящие из строковых литералов,\nразделённых точками", 'LuaComplete', nil, 'w')
- return
- end
- local bSucc = S.CaseSens and FillMenu(ForSearch,'Таблицы, функции:', LastWord, nil, true)
- if not bSucc and
- S.CaseIgnore and
- far.Message('Элемент не найден.\nПовторить без учёта регистра?','LuaComplete',';YesNo','w') then
- table.sort(asCurr, function(a1,a2) return a1.TEXT < a2.TEXT end)
- if not FillMenu(ForSearch,'Таблицы, функции:', LastWord, true, true) and
- ForSearch:sub(-1) ~= '.' and
- S.AnywhereSearch and
- far.Message('Так тоже ничего не найдено.\nИскать во всех таблицах по имени элемента?','LuaComplete',';YesNo','w') then
- for iDeb,v in ipairs(asCurr) do
- if ('_G.'..v.TEXT):sub(-(LastWord:len()+1)) == '.'..LastWord:upper() then
- items[#items+1] = {text=v.text}
- end
- end
- end
- end
- if #items > 0 then
- DoSearch(items, Str0, Str99)
- end -- if #items > 0
- end;
- }
- Macro{
- -- id="";
- area="Editor";
- key=S.KeyLastWord;
- -- description="";
- filemask="*.lua,*.moon,*.fmlua";
- flags="";
- -- priority=50;
- -- sortpriority=50;
- -- condition=function(key) return true end;
- action=function()
- xWas, asCurr = {}, {}
- AddPath(asCurr, '', '', _G, nil)
- if type(builtin_standards) == 'table' then
- AddPath(asCurr, '', '', builtin_standards.max.read_globals, 'fields')
- end
- local Str0, Str99, _, LastWord = GetFromEdit()
- table.sort(asCurr, function(a1,a2) return a1.text < a2.text end) -- В принципе, тут сортировка не нужна
- local items={}
- for _,v in ipairs(asCurr) do
- if ('_G.'..v.TEXT):sub(-(LastWord:len()+1)) == '.'..LastWord:upper() then
- items[#items+1] = {text=v.text}
- end
- end
- DoSearch(items, Str0, Str99)
- end;
- }
GeSHi © Codebox Plus Extension
- Версия 2
- Реализована фильтрация в меню выбора слова
- "Тупая" вставка выбранного слова заменена на замену текущего слова выбранным. Возможность вставки оставлена и "повешена" на сочетание
CtrlEnter
- Реализован выбор варианта вводом не-словного символа; при этом в текст помещается выбранное слово и введённый знак.
- Версия 3
- Добавлена настройка. В настроечном файле можно указать только изменённые параметры. Имя настроечного файла совпадает с именем файла со скриптом, в том же каталоге, расширение - .cfg
- Добавлена возможность поиска без учёта регистра. Инициируется, если "точный" поиск не дал результата
- Добавлен поиск слова (в таблицах). Поиск регистронезависимый. Инициируется при неудаче остальных либо по отдельной "горячей" кнопке (по умолчанию - AltShiftSpace). Например, Вы забыли, где определена функция GetStr - в editor или в Editor. Просто наберите getstr, нажмите
AltShiftSpace
- и получите Editor.GetStr - Исправлены баги, приводившие к вылетам (спасибо John Doe и HaRT)
- LuaComplete.v3.7z
- Версия 3 от 24.05.18
- (4.35 KiB) Downloaded 73 times