Luacheck FAR scripts — статический анализатор для Lua/MoonScript

Здесь выкладываются готовые к использованию макросы и скрипты.
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

Luacheck FAR scripts — статический анализатор для Lua/MoonScript

Post by John Doe »

Luacheck это статический анализатор для Lua.
Luacheck может обнаруживать разнообразные проблемы, такие как использование неопределённых глобальных переменных, неиспользованные переменные и значения, доступ к неинициализированным переменным, недостижимый код и многое другое.

А для удобной работы с luacheck в фаре предлагаю данный пакет скриптов, обеспечивающий работу Luacheck в редакторе и в командной строке.
Кроме того, в редакторе для Luacheck обеспечивается прозрачная "трансляция" MoonScript, что позволяет анализировать и *.moon-файлы.

Инструкции по установке, настройке, и работе — во встроенной справке.

Требования:
  • FAR 3 не старше b5106
  • luacheck не ниже v0.19
Attachments
far_standards.lua.cfg_v1.5.7z
Обновлённые определения (far 6114 / lm 772)
(8.5 KiB) Downloaded 87 times
luaсheck_far_v1.4.3.7z
far5505.lm712
(23.38 KiB) Downloaded 335 times
Last edited by John Doe on Sat 09 Nov, 2019 16:08, edited 3 times in total.
User avatar
HaRT
Moderator
Posts: 10806
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 220 times
Been thanked: 357 times

luacheck — статический анализатор для Lua

Post by HaRT »

Latest post of the previous page:

John Doe wrote: CODE: [ВЫДЕЛИТЬ ВСЁ] [EXPAND/COLLAPSE] [DOWNLOAD] (LUACHECK_EDITOR.LUA)
Спасибо, вижу, что по нажатию на [b]CtrlH[/b] список фильтруется в соответствии с [b]options_alt.only[/b]. Несколько соображений:
1. Слово alt у меня не вызывает никаких ассоциаций с происходящим, я бы предпочёл раздедение major/minor, primary/secondary, …. Ну или объясните, пожалуйста, как бы это лучше осознать и запомнить.
2. Обнаружился неприятный эффект: если после фильтрации список оказался пуст, то кратковременно показывается сообщение “No warnings” и список уже не открывается (если вдуматься, это и не удивительно), но вот фильтр после этого снимается только перезагрузкой макросов — неудобно. Предлагаю, чтобы при включенной фильтрации список показывался, даже если он пустой.
3. Чтобы короткий/пустой список не создавал иллюзию чистого кода, предлагаю в качестве признака отфильтрованности добавить, например, звёздочку в название меню. (Например, AltHistory так индицирует тип фильтра: от начала или в любом месте строки.)
4. Хорошо бы добавить [b]CtrlH[/b] в подсказку на нижней рамке и в Справку.
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

HaRT wrote: Слово alt у меня не вызывает никаких ассоциаций с происходящим,
Альтернативный набор опций. Настраивается в начале файла, таблицей options_alt. Если хотите, то можно переименовать (параметр и/или шорткат)
HaRT wrote: после этого снимается только перезагрузкой макросов
Это ошибка, исправил
HaRT wrote: Предлагаю, чтобы при включенной фильтрации список показывался, даже если он пустой.
По сути это не фильтрация, а только лишь использование другого набора опций.

И я тут глянул, чтобы "нормально" показать пустой список потребуется добавить слишком много костылей.

P.S.
Возможно вот этого вам хватит, здесь просто скрывается всё что не начинается на "1", но зато список не закрывается.
  1. local _NAME,_VER = "luacheck","1.2H"
  2.  
  3. local _forumtopic = "http://forum.farmanager.com/viewtopic.php?f=15&t=9650"
  4.  
  5. local luacheck_min_version,lmv_err_msg = "0.11.0","luacheck version %s or newer expected"
  6.  
  7. -- list options
  8.  
  9. local O = {
  10.  
  11.   MaxHeight = 10,
  12.  
  13.   InitPos   = "Bottom", --Top,Bottom,Center
  14.  
  15.   AutoPos   = true,
  16.  
  17.   --CycleMode = "ping-pong",
  18.  
  19.   --ConvertToAnsi = true,
  20.  
  21. }
  22.  
  23.  
  24.  
  25. -- luacheck options
  26.  
  27. local options = { --http://luacheck.readthedocs.org/en/0.11.0/config.html
  28.  
  29.   new_read_globals={
  30.  
  31.     "Macro","NoMacro","Event","NoEvent","MenuItem","NoMenuItem","CommandLine","NoCommandLine",
  32.  
  33.   };
  34.  
  35.   new_globals={
  36.  
  37.     "_filename",                    --scripts executed in luamacro via cmdline prefix
  38.  
  39.     "export","IsLuaStateRecreated", --lua plugins
  40.  
  41.   }
  42.  
  43.  
  44.  
  45.   --global=false;
  46.  
  47.   --allow_defined=true;
  48.  
  49.   --allow_defined_top=true;
  50.  
  51.   --unused=false;
  52.  
  53.   --unused_args=false;
  54.  
  55.   --unused_secondaries=false;
  56.  
  57.   --redefined=false;
  58.  
  59.   --http://luacheck.readthedocs.org/en/0.11.0/cli.html#patterns
  60.  
  61.   --ignore={"4../.*"};
  62.  
  63.   --enable={};
  64.  
  65.   --only={};
  66.  
  67. }
  68.  
  69. local only_globals
  70.  
  71.  
  72.  
  73. local function showHelp()
  74.  
  75.   if far.Message([[
  76.  
  77. Основные действия:
  78.  
  79. • Enter           - перейти к позиции предупреждения
  80.  
  81. • Esc             - закрыть список и восстановить исходную позицию
  82.  
  83.  
  84.  
  85. Дополнительные действия (не закрывают список):
  86.  
  87. • Ctrl-PgUp       - перейти к позиции, на которую ссылается предупреждение
  88.  
  89. • Ctrl-Up/Down    - скроллировать текст редактора
  90.  
  91.  
  92.  
  93. Управление расположением списка:
  94.  
  95. • Ctrl-Home, Num7 - вверху
  96.  
  97. • Ctrl-End,  Num1 - внизу
  98.  
  99. • Num4            - по центру
  100.  
  101. • F6, Divide      - перебор режимов
  102.  
  103. • F5, Num5        - максимизация
  104.  
  105.  
  106.  
  107. Действия с закладками
  108.  
  109. • Ctrl-0..9       - перейти к позиции закладки 0..9
  110.  
  111. • Ctrl-Shift-0..9 - установить закладку 0..9 в текущей позиции
  112.  
  113. • Add             - добавить сессионную закладку с текущей позицией]],
  114.  
  115. ("%s v%s"):format(_NAME,_VER),"OK;Go to forum;","l")==2 then win.ShellExecute(nil,"open",_forumtopic) end
  116.  
  117. end
  118.  
  119. --todo
  120.  
  121. --• Ctrl-Shift-Enter,
  122.  
  123. --  Ctrl-Enter      - перейти к позиции предупреждения
  124.  
  125. --• Shift-Up,  Num2 - перейти к предыдущему предупреждению
  126.  
  127. --• Shift-Down,Num8 - перейти к следующему предупреждению
  128.  
  129.  
  130.  
  131. local luacheck = require "luacheck"
  132.  
  133. if luacheck._VERSION<luacheck_min_version then error(lmv_err_msg:format(luacheck_min_version)) end
  134.  
  135.  
  136.  
  137. local function MessagePopup(msg,title,flags,delay)
  138.  
  139.   local s = far.SaveScreen()
  140.  
  141.   far.Message(msg,title or "","",flags)
  142.  
  143.   win.Sleep(delay or 500); far.RestoreScreen(s)
  144.  
  145. end
  146.  
  147.  
  148.  
  149. local Id = "CFD31C22-0D17-4D87-829A-14561B529D34"
  150.  
  151. local function expandBreakKeys(BreakKeysArr)
  152.  
  153.   local newBreakKeysArr = {}
  154.  
  155.   for _,item in ipairs(BreakKeysArr) do
  156.  
  157.     if item then
  158.  
  159.       for key in item.BreakKey:gmatch("%S+") do
  160.  
  161.         local newitem = {}
  162.  
  163.         for k,v in pairs(item) do newitem[k]=v end
  164.  
  165.         newitem.BreakKey = key
  166.  
  167.         table.insert(newBreakKeysArr,newitem)
  168.  
  169.       end
  170.  
  171.     end
  172.  
  173.   end
  174.  
  175.   return newBreakKeysArr
  176.  
  177. end
  178.  
  179.  
  180.  
  181. local function setEditorPos(info) editor.SetPosition(nil,info); editor.Redraw() end
  182.  
  183.  
  184.  
  185. local bak_pos
  186.  
  187. local function restorePos()
  188.  
  189.   if bak_pos then
  190.  
  191.     editor.Select(nil,bak_pos)
  192.  
  193.     setEditorPos(bak_pos)
  194.  
  195.   end
  196.  
  197. end
  198.  
  199.  
  200.  
  201. local function scrollEditor(dir)
  202.  
  203.   local ei = editor.GetInfo()
  204.  
  205.   ei.TopScreenLine = ei.TopScreenLine+dir
  206.  
  207.   if ei.TopScreenLine<1 or ei.TopScreenLine>ei.TotalLines-ei.WindowSizeY+1 then mf.beep(); return end
  208.  
  209.   if ei.CurLine-ei.TopScreenLine-(dir==1 and -1 or ei.WindowSizeY)==0 then
  210.  
  211.     ei.CurLine = ei.CurLine+dir
  212.  
  213.   end
  214.  
  215.   setEditorPos(ei)
  216.  
  217. end
  218.  
  219.  
  220.  
  221. local F = far.Flags
  222.  
  223.  
  224.  
  225. local list = {}
  226.  
  227. function list:calcProps(Items,Props)
  228.  
  229.   self.Pos = self.Pos or O.InitPos
  230.  
  231.   Items = assert(Items or self.Items,"Items not set")
  232.  
  233.   local nItems = #Items
  234.  
  235.   Props = assert(Props or self.Props,"Props not set")
  236.  
  237.   -- calculate required list's dimensions and position
  238.  
  239.   local r = far.AdvControl(F.ACTL_GETFARRECT)
  240.  
  241.   local xSize,ySize = r.Right-r.Left,r.Bottom-r.Top --Far size
  242.  
  243.   local MaxItems = ySize-3 --max items n to fit
  244.  
  245.   local X,Y
  246.  
  247.   X = Items.maxlen<xSize-4 and (xSize-Items.maxlen)/2-2 or -1
  248.  
  249.   local nLines = math.min(nItems,O.MaxHeight,MaxItems) --actual list lines n
  250.  
  251.   local Pos = self.Pos or O.InitPos
  252.  
  253.   local isMaximizable = nItems>nLines and nLines<MaxItems
  254.  
  255.   local isMaximized = self.isMaximized and isMaximizable
  256.  
  257.   if Pos=="Center" or isMaximized then
  258.  
  259.     X,Y = -1,-1
  260.  
  261.   elseif Pos=="Top" then
  262.  
  263.     Y = 0
  264.  
  265.   elseif Pos=="Bottom" then
  266.  
  267.     Y = MaxItems-nLines>0 and MaxItems-nLines+1+1 or -1
  268.  
  269.   end
  270.  
  271.   -- set properties
  272.  
  273.   Props.X,Props.Y,Props.MaxHeight = X,Y,isMaximized and 0 or O.MaxHeight
  274.  
  275.   self.Props,self.Items,self.nItems = Props,Items,nItems
  276.  
  277.   self.nLines,self.isMaximized = nLines,isMaximized
  278.  
  279.   self.EditorShiftTop = Far.GetConfig"Editor.ShowTitleBar" and 0 or 1
  280.  
  281.   self.EditorShiftBottom = Far.KeyBar_Show()-1
  282.  
  283. end
  284.  
  285. function list:maximize(state)
  286.  
  287.   self.isMaximized = state==nil and not self.isMaximized or state
  288.  
  289.   self:calcProps()
  290.  
  291. end
  292.  
  293. function list:setPos(Pos)
  294.  
  295.   if Pos==self.Pos then
  296.  
  297.     return list:maximize()
  298.  
  299.   elseif Pos=="ping-pong" then
  300.  
  301.     if self.Pos=="Center" then
  302.  
  303.       Pos = self.prevPos=="Top" and "Bottom" or "Top"
  304.  
  305.     else
  306.  
  307.       Pos = "Center"
  308.  
  309.     end
  310.  
  311.   elseif not Pos then
  312.  
  313.     local next = {["Top"]="Bottom",["Bottom"]="Center",["Center"]="Top"}
  314.  
  315.     Pos = next[self.Pos]
  316.  
  317.   end
  318.  
  319.   self.prevPos = Pos~="Center" and Pos or self.prevPos
  320.  
  321.   self.Pos = Pos
  322.  
  323.   self.isMaximized = false
  324.  
  325.   self:calcProps()
  326.  
  327. end
  328.  
  329. function list:gotoWarning(pos,to_prev,force_top)
  330.  
  331.   local w = self.Items[pos]
  332.  
  333.   local line = to_prev and w.prev_line or w.line
  334.  
  335.   if not line then return end
  336.  
  337.   local column = to_prev and w.prev_column or w.column
  338.  
  339.   local end_column = not to_prev and w.end_column
  340.  
  341.   --select
  342.  
  343.   local width
  344.  
  345.   if end_column then
  346.  
  347.     width = end_column-column+1
  348.  
  349.   elseif w.name then
  350.  
  351.     width = w.name:len()
  352.  
  353.   else
  354.  
  355.     local str = editor.GetString(nil,line)
  356.  
  357.     if not str then return end
  358.  
  359.     local a,b = str.StringText:find("^%S+",column)
  360.  
  361.     width = a and b-a+1 or str.StringLength-column+1
  362.  
  363.   end
  364.  
  365.   editor.Select(nil,F.BTYPE_STREAM,line,column,width,1)
  366.  
  367.   --goto
  368.  
  369.   local nLines,TopScreenLine = self.nLines
  370.  
  371.   if nLines then --trying to correct TopScreenLine in order not to let cursor be hidden behind list
  372.  
  373.     local ei = editor.GetInfo()
  374.  
  375.     local y = line-ei.TopScreenLine --calculated screen line of warning
  376.  
  377.     local a,b = 0,ei.WindowSizeY    --valid screen lines (a..b)
  378.  
  379.     if self.Pos=="Top" then
  380.  
  381.       a = a+nLines+3+self.EditorShiftTop
  382.  
  383.     elseif self.Pos=="Bottom" then
  384.  
  385.       b = b-nLines-4+1+self.EditorShiftBottom
  386.  
  387.     end
  388.  
  389.     TopScreenLine = (y<a or force_top) and math.max(line-a,1)
  390.  
  391.                  or (y>b)              and line-b
  392.  
  393.     --win.OutputDebugString(("%s…%s = %s = %s"):format(a,b,y,TopScreenLine or '-'))
  394.  
  395.   end
  396.  
  397.   setEditorPos{CurLine=line,CurPos=column,TopScreenLine=TopScreenLine}
  398.  
  399. end
  400.  
  401. function list:Up(pos)   return pos-1>=1 and pos-1 or self.nItems end
  402.  
  403. function list:Down(pos) return pos+1<=self.nItems and pos+1 or 1 end
  404.  
  405. local function go(dir,pos,autopos)
  406.  
  407.   local nextpos = list[dir](list,pos)
  408.  
  409.   if autopos then list:gotoWarning(nextpos) end
  410.  
  411.   return nextpos
  412.  
  413. end
  414.  
  415.  
  416.  
  417. local Check --fw decl
  418.  
  419. local bKeys = expandBreakKeys {
  420.  
  421.   {BreakKey="C+UP   C+NUMPAD8 C+8",action=function() scrollEditor(-1) end},
  422.  
  423.   {BreakKey="C+DOWN C+NUMPAD2 C+2",action=function() scrollEditor(1) end},
  424.  
  425.   {BreakKey="C+RETURN C+NEXT C+NUMPAD3 C+3",action=function(pos) list:gotoWarning(pos) end},
  426.  
  427.   {BreakKey="CS+RETURN",        action=function(pos) list:gotoWarning(pos,nil,true) end},
  428.  
  429.   {BreakKey="RETURN",           action=function(pos)
  430.  
  431.      if list.Props.SelectIndex~=pos then list:gotoWarning(pos) end
  432.  
  433.      return "break"
  434.  
  435.    end},
  436.  
  437.   {BreakKey="ESCAPE",           action=function() restorePos(); return "break" end},
  438.  
  439.   {BreakKey="C+PRIOR C+NUMPAD9 C+9",action=function(pos) list:gotoWarning(pos,true) end},
  440.  
  441.   {BreakKey="C+HOME NUMPAD7 7", action=function() list:setPos("Top") end},
  442.  
  443.   {BreakKey="C+END  NUMPAD1 1", action=function() list:setPos("Bottom") end},
  444.  
  445.   {BreakKey="NUMPAD4 4",        action=function() list:setPos("Center") end},
  446.  
  447.   {BreakKey="F6 DIVIDE",        action=function() list:setPos(O.CycleMode) end},
  448.  
  449.   {BreakKey="F5 CLEAR 5",       action=function() list:maximize() end},
  450.  
  451.   {BreakKey="ADD",              action=function() editor.AddSessionBookmark() end},
  452.  
  453.   {BreakKey="CS+1 CS+2 CS+3 CS+4 CS+5 CS+6 CS+7 CS+8 CS+9 CS+0 C+1 C+2 C+3 C+4 C+5 C+6 C+7 C+8 C+9 C+0",keys=true},
  454.  
  455.   {BreakKey="F1",               action=showHelp},
  456.  
  457.   --http://bugs.farmanager.com/view.php?id=1301#c12736
  458.  
  459.   {BreakKey="UP",               action=function(pos) return go("Up",pos,O.AutoPos) end},
  460.  
  461.   {BreakKey="S+UP NUMPAD8 8",   action=function(pos) return go("Up",pos,not O.AutoPos) end},
  462.  
  463.   {BreakKey="DOWN",             action=function(pos) return go("Down",pos,O.AutoPos) end},
  464.  
  465.   {BreakKey="S+DOWN NUMPAD2 2", action=function(pos) return go("Down",pos,not O.AutoPos) end},
  466.  
  467.   --{BreakKey="F3",               action=function(pos) require"le"(list.Items[pos],"Event") end},
  468.  
  469.   --{BreakKey="F9",               action=function() require"le"(O,"Options");list:calcProps() end},
  470.  
  471.   {BreakKey="C+H",              action=function(_,Items)
  472.  
  473.      only_globals = not only_globals
  474.  
  475.      for i=1,#Items do
  476.  
  477.        local item = Items[i]
  478.  
  479.        item.hidden = only_globals and item.code and item.code:sub(1,1)~="1"
  480.  
  481.      end
  482.  
  483.    end},
  484.  
  485. }
  486.  
  487.  
  488.  
  489. local Props = {
  490.  
  491.   Title=_NAME;
  492.  
  493.   Bottom="Ctrl-Enter, Ctrl-Up/Down, F5, F6, F1";
  494.  
  495.   Id=win.Uuid(Id);
  496.  
  497. }
  498.  
  499.  
  500.  
  501. function Check()
  502.  
  503.   local ei = editor.GetInfo()
  504.  
  505.   local sel = editor.GetSelection()
  506.  
  507.   if sel then --save for further restoring
  508.  
  509.     ei.BlockStartPos = sel.StartPos
  510.  
  511.     ei.BlockWidth = sel.EndPos-sel.StartPos+1
  512.  
  513.     ei.BlockHeight = sel.EndLine-sel.StartLine+1
  514.  
  515.   end
  516.  
  517.   bak_pos = ei
  518.  
  519.   local source = {}
  520.  
  521.   for i=1,ei.TotalLines do source[i] = editor.GetString(nil,i).StringText end
  522.  
  523.   local text = table.concat(source,"\n")
  524.  
  525.   if O.ConvertToAnsi then
  526.  
  527.     text = win.WideCharToMultiByte(win.Utf8ToUtf16(text),win.GetACP())
  528.  
  529.   end
  530.  
  531.   local report = luacheck.check_strings({text}, options)[1]
  532.  
  533.   if not report then
  534.  
  535.     far.Message("Internal error: unable to get report",_NAME,nil,"w")
  536.  
  537.     return
  538.  
  539.   end
  540.  
  541.   if #report==0 then
  542.  
  543.     MessagePopup("No warnings",_NAME)
  544.  
  545.   else -- proceed with warnings list
  546.  
  547.     local Items,pos,maxlen,err = {},nil,0
  548.  
  549.     for i,w in ipairs(report) do
  550.  
  551.       err = w.code:sub(1,1)=="0"
  552.  
  553.       w.text =  ("%4u:%-3u "):format(w.line,w.column)..
  554.  
  555.                 ("│ %s%s │ "):format(err and "E" or "W",w.code)..
  556.  
  557.                 luacheck.get_message(w)
  558.  
  559.       local len = w.text:len()
  560.  
  561.       maxlen = len>maxlen and len or maxlen
  562.  
  563.       w.checked = err and "‼" or w.code:sub(1,1)=="1" and "!" --[[??]] or w.secondary and "²"
  564.  
  565.       if not pos and w.line==ei.CurLine and w.column==ei.CurPos then pos = i end
  566.  
  567.       Items[i] = w
  568.  
  569.       if not w.end_column then mf.beep() end--??
  570.  
  571.     end
  572.  
  573.     Items.maxlen = maxlen
  574.  
  575.     if err then mf.beep(); mf.postmacro(MessagePopup,"Errors found!",_NAME,"w",300) end
  576.  
  577.     list:calcProps(Items,Props)
  578.  
  579.     if O.AutoPos then list:gotoWarning(pos or 1) end
  580.  
  581.     repeat --todo use dialog instead of menu
  582.  
  583.       -- show list
  584.  
  585.       Props.SelectIndex = pos
  586.  
  587.       local item
  588.  
  589.       item,pos = far.Menu(Props,Items,bKeys)
  590.  
  591.       -- process breakkeys
  592.  
  593.       if not item then
  594.  
  595.         break
  596.  
  597.       elseif item.keys then
  598.  
  599.         Keys(item.BreakKey:gsub("^CS%+","CtrlShift"):gsub("^C%+","Ctrl"))
  600.  
  601.       elseif not item.action then
  602.  
  603.         list:gotoWarning(pos)
  604.  
  605.       else
  606.  
  607.         pos = item.action(pos,Items) or pos
  608.  
  609.         if pos=="break" then break end
  610.  
  611.       end
  612.  
  613.     until false
  614.  
  615.     only_globals = false
  616.  
  617.   end
  618.  
  619. end
  620.  
  621.  
  622.  
  623. Event { description="luacheck menu handler";
  624.  
  625.   group="DialogEvent";
  626.  
  627.   action=function(Event,param)
  628.  
  629.     local hDlg,Msg = param.hDlg,param.Msg
  630.  
  631.     if Msg==F.DN_RESIZECONSOLE then
  632.  
  633.       if Event==F.DE_DLGPROCINIT and Menu.Id==Id then
  634.  
  635.         hDlg:send(F.DM_CLOSE,-1,0)
  636.  
  637.         list:calcProps()
  638.  
  639.       end
  640.  
  641.     elseif Msg==F.DN_INITDIALOG and Event==F.DE_DLGPROCINIT then
  642.  
  643.       local info = hDlg:send(F.DM_GETDIALOGINFO)
  644.  
  645.       if info and info.Id==win.Uuid(Id) then
  646.  
  647.         local r = hDlg:send(F.DM_GETITEMPOSITION,1)
  648.  
  649.         hDlg:send(F.DM_SETITEMPOSITION,1,{Left=r.Left-2,Top=r.Top-1,Right=r.Right-2,Bottom=r.Bottom-1})
  650.  
  651.         r = hDlg:send(F.DM_GETDLGRECT)
  652.  
  653.         hDlg:send(F.DM_RESIZEDIALOG,0,{Y=r.Bottom-r.Top-1,X=r.Right-r.Left-3})
  654.  
  655.         hDlg:send(F.DM_MOVEDIALOG,0,{X=2,Y=list.Pos=="Bottom" and 1 or 0})
  656.  
  657.       end
  658.  
  659.     end
  660.  
  661.   end
  662.  
  663. }
  664.  
  665.  
  666.  
  667. Macro { description="luacheck menu helper";
  668.  
  669.   area="Menu";  key="ShiftUp ShiftDown";    flags="NoSendKeysToPlugins";
  670.  
  671.   uid="60596FEB-E7C5-47A5-A3C9-B782C8F8EF93";
  672.  
  673.   condition=function()return O.AutoPos and Menu.Id==Id end;
  674.  
  675.   action=function()
  676.  
  677.     Keys(mf.akey(1,1):match"Up" and "Num8" or "Num2")
  678.  
  679.   end;
  680.  
  681. }
  682.  
  683.  
  684.  
  685. Macro { description="luacheck: process current editor";
  686.  
  687.   area="Editor";    key="CtrlShiftF7";  filemask="*.lua";
  688.  
  689.   uid="CE634ECE-1039-43F3-80CC-8BB17B1FDB05";
  690.  
  691.   action=Check;
  692.  
  693. }
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

Ни один из предложенных мной варианта в шапку пока не пойдёт, т.к. не соответствуют моему видению процесса отладки кода.
Ведь (в идеале) требуется избавиться от всех предупреждений.

Замечу, что изменение кода это не единственный путь "избавления".
Luacheck всего лишь предупреждает, и если какой-то приём в коде использован сознательно, то можно просто подавить предупреждение, например с помощью inline-опций (есть и другие варианты, но не суть).

Впрочем, не исключаю, что действительно может есть смысл рассматривать различные группы предупреждений по отдельности.
Т.е. например:
- можно сортировать список не в порядке следования, а по кодам
- или как вы и предлагали фильтровать список, но тогда не только по "1", а и по прочим группам.
User avatar
HaRT
Moderator
Posts: 10806
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 220 times
Been thanked: 357 times

luacheck — статический анализатор для Lua

Post by HaRT »

John Doe wrote: здесь просто скрывается всё что не начинается на "1", но зато список не закрывается
Спасибо, погоняю.
John Doe wrote: рассматривать различные группы предупреждений по отдельности
Мне вот тоже уже приходило в голову, что, возможно, имело бы смысл сопоставить каждому предупреждению тэги (хоть по тем же опциям luacheck), и фильтровать, включая/выключая те или иные тэги. Но я больших программ на Луа не пишу, поэтому не могу утверждать, как будет удобно при серьёзной разработке.
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

Заметил, что моя рабочая версия отличается от выложенной в шапке.
Изменения больше внутренние, но для порядка обновил.
IgorZ
Posts: 790
Joined: Wed 13 Jul, 2011 03:32
Has thanked: 15 times
Been thanked: 93 times

luacheck — статический анализатор для Lua

Post by IgorZ »

Случайно заметил ошибку:

В обоих макросах uid="60596FEB-E7C5-47A5-A3C9-B782C8F8EF93"
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

Я тоже нашёл её случайно, в процессе перехода на id )
Во втором будет id="CE634ECE-1039-43F3-80CC-8BB17B1FDB05";
Shmuel
Posts: 6815
Joined: Thu 23 Mar, 2006 21:36
Location: Israel
Has thanked: 41 times
Been thanked: 526 times

luacheck — статический анализатор для Lua

Post by Shmuel »

Возможно LuaMacro должен это ловить и выдавать сообщения?
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

Возможно, но позиция изложенная тут мне кажется обоснованной.
Если когда-нибудь в фаре появится окошко с логом, то там таким ошибком самое место.

А сейчас как вариант можно при обнаружении такой ошибки создавать в таблице макроса поле error = "duplicated id", а макробраузеры сделают остальное.

P.S.
В rebind есть возможность отлавливать такие ошибки, но если будет официальное поле error, то пожалуй тоже уберу.
User avatar
HaRT
Moderator
Posts: 10806
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 220 times
Been thanked: 357 times

luacheck — статический анализатор для Lua

Post by HaRT »

John Doe wrote: можно при обнаружении такой ошибки создавать в таблице макроса поле error = "duplicated id", а макробраузеры сделают остальное.
Если уж что-то такое и делать, то я бы предложил что-то более структурное, чем одна строка. Как минимум нужен массив строк, т.к. ошибок в одном макросе может быть несколько. Далее, с каждой ошибкой может ассоциироваться позиция в коде, а то и две или три. Ещё, поскольку с макросами работают разные плагины/макросы, неплохо бы иметь возможность задать в отдельном поле „источник“ ошибки. Ну и так далее — одним словом, есть, что обдумать/обсудить.
Last edited by HaRT on Thu 01 Jan, 1970 01:00, edited 0 times in total.
Reason: Подчёркнуто главное
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

HaRT
Пока что формально это внутренняя приватная структура плагина, недокументированная и подверженная внезапным изменениям.
Можно долго обдумывать, а потом ничего этого так и не пригодится.

А можно долго не думать, а изменить значение на таблицу тогда, когда возникнет реальная необходимость.

Вместо error можно завести поле duplicated_id
User avatar
HaRT
Moderator
Posts: 10806
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 220 times
Been thanked: 357 times

luacheck — статический анализатор для Lua

Post by HaRT »

John Doe wrote: формально это внутренняя приватная структура плагина, недокументированная и подверженная внезапным изменениям
Это вступает в противоречие с высказанным ранее:
John Doe wrote: макробраузеры сделают остальное
John Doe wrote: Вместо error можно завести поле duplicated_id
Ещё хуже, ибо это отдельное поле, заточенное под конкретную ошибку.
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

HaRT wrote: Это вступает в противоречие с высказанным ранее:
Не знаю насчёт противоречий, но дела обстоят именно так: структура лишь косвенно документирована, и отдельные её элементы могут меняться (и меняются) без предупреждения.

А макробраузеры приспосабливаются.
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

1.3.0-beta: Поддержка moonscript
1.3.1-beta: С этим мунскриптом непросто всё
1.3.2-beta: Обработка синтаксических ошибок.

Update
Прогнал на исходном коде moonscript, по результатам кое-что исправил/усовершенствовал.
1.3.3 в шапке.
lysenkov
Posts: 2
Joined: Wed 15 Mar, 2017 18:50
Has thanked: 1 time

luacheck — статический анализатор для Lua

Post by lysenkov »

Скажите, куда положить .luacheckrc, чтобы он загрузился?
User avatar
John Doe
Бюрократ
Posts: 13801
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 72 times
Been thanked: 425 times
Contact:

luacheck — статический анализатор для Lua

Post by John Doe »

По замыслу он предполагается в текущей папке, или выше (вплоть до корня). В контексте фара это не очень надёжно, и я даже не проверял работает ли.
На практике конфигурацию можно задать прямо в luacheck_editor.lua, а если не хочется трогать исходник, то использовать возможности cfgscript.
Post Reply

Return to “Полезные макросы и скрипты”