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

Здесь выкладываются готовые к использованию макросы и скрипты.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 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 92 times
luaсheck_far_v1.4.3.7z
far5505.lm712
(23.38 KiB) Downloaded 340 times
Last edited by John Doe on Sat 09 Nov, 2019 16:08, edited 3 times in total.
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

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

Post by John Doe »

Latest post of the previous page:

HaRT wrote: скрывать/показывать все „второстепенные“ предупреждения
Не берусь судить о второстепенности, а пометка восклицательным знаком это больше моя самодеятельность: для себя пометил предупреждения коды которых начинаются с 1 (все они связаны с использованием глобальных переменных).

Не уверен что правильно рубить с плеча и скрывать остальные.
Но какое-то более гибкое решение можно рассмотреть. Обратите внимание на опции, возможно стоит реализовать интерактивную конфигурацию.
В частности, вашему предложению соответствует значении опции only={"1.."}
User avatar
HaRT
Moderator
Posts: 10823
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 221 times
Been thanked: 358 times

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

Post by HaRT »

John Doe wrote: возможно стоит реализовать интерактивную конфигурацию
Не уверен, что нужна интерактивная. Лично мне было бы достаточно где-нибудь в скрипте прописать набор паттернов, которые бы скрывались/показывались по нажатию [b]CtrlH[/b] в списке предупреждений. А по умолчанию — {"1.."}.
Фар есть инструмент, а не нянька. © 2009 DrKnS
User avatar
John Doe
Бюрократ
Posts: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

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

Post by John Doe »

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

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

Post by HaRT »

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: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 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: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

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

Post by John Doe »

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

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

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

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

Post by HaRT »

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

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

Post by John Doe »

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

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

Post by Shmuel »

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

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

Post by John Doe »

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

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

P.S.
В rebind есть возможность отлавливать такие ошибки, но если будет официальное поле error, то пожалуй тоже уберу.
User avatar
HaRT
Moderator
Posts: 10823
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 221 times
Been thanked: 358 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: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

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

Post by John Doe »

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

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

Вместо error можно завести поле duplicated_id
User avatar
HaRT
Moderator
Posts: 10823
Joined: Tue 30 Aug, 2005 17:21
Has thanked: 221 times
Been thanked: 358 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: 13807
Joined: Wed 27 Apr, 2005 20:42
Has thanked: 73 times
Been thanked: 426 times
Contact:

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

Post by John Doe »

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

А макробраузеры приспосабливаются.
Post Reply

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