ZNZNCOOP

MC 1.3

Oct 9th, 2014
345
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. --[[ Midday Commander Color Ver. 1.3
  2.      Created by Dimus & Neo
  3.      No rights reserved ]]
  4. local function SetColor(cl)
  5.   term.setTextColor(cl[1])
  6.   term.setBackgroundColor(cl[2])
  7. end
  8. local NormalCl, PanelCl, SelectCl, WindowCl, AlarmWinCl
  9. NormalCl={colors.white,colors.black}
  10. if term.isColor() then
  11.   PanelCl={colors.white,colors.blue}
  12.   SelectCl={colors.black,colors.cyan}
  13.   WindowCl={colors.white,colors.green}
  14.   AlarmWinCl={colors.white,colors.red}
  15. else
  16.   PanelCl=NormalCl
  17.   SelectCl={colors.black,colors.white}
  18.   WindowCl=NormalCl
  19.   AlarmWinCl=NormalCl
  20. end
  21. local wScr, hScr = term.getSize()
  22. local wPanA = math.ceil(wScr / 2)
  23. if wPanA<16 then wPanA=16 end
  24. local wPanP=wScr-wPanA+1
  25.  
  26. local Menu
  27. if wScr<27 then
  28.   Menu={'','','','Ed','Cp','Mv','Dr','Dl','','Ex'}
  29. elseif wScr<51 then
  30.   Menu={'Hlp','','','Edt','Cpy','Mov','Dir','Del','','Ext'}
  31. else
  32.   Menu={'Help','','','Edit','Copy','Move','Dir','Del','','Exit'}
  33. end
  34. local help={"Up,Down - Navigation", "Tab - Change panel",
  35. 'Enter - Change dir/run program','Ctrl+Enter - Insert into command line',
  36. 'F1 - This help','F4 - Edit file','Shift+F4 - Create new file',
  37. 'F5 - Copy file/dir','F6 - Move file/dir','F7 - Create directory',
  38. 'Alt+F7 - Find file/dir','F8 - Delete file/dir','F10 - Exit from MC'}
  39. local xMenu=-1
  40. for i=1,#Menu do
  41.   if #Menu[i]>0 then xMenu=xMenu+#tostring(i)+#Menu[i]+2 end
  42. end
  43. xMenu=math.ceil((wScr-xMenu) / 2)
  44.  
  45. local panel ={}
  46. local Active
  47.  
  48. local cmdstr=''
  49. local curpos=0
  50. local function ShowCmd()
  51.   SetColor(NormalCl)
  52.   term.setCursorPos(1, hScr-1)
  53.   term.clearLine()
  54.   term.write(shell.dir()..'> '..cmdstr)
  55.   term.setCursorPos(term.getCursorPos()-curpos, hScr-1)
  56. end
  57.  
  58. function panel:ShowFirst()
  59.   local p=self.Path..'/'
  60.   if #p> self.wPan-6 then p='..'..p:sub(#p-self.wPan+7) end
  61.   p=' '..p..' '
  62.   term.setCursorPos(self.X, 1)
  63.   term.write('+'..string.rep('-',self.wPan-2)..'+')
  64.   term.setCursorPos(self.X+(self.wPan-#p)/2,1)
  65.   if self==Active then
  66.     SetColor(SelectCl)
  67.     term.write(p)
  68.     SetColor(PanelCl)
  69.   else
  70.     term.write(p)
  71.   end
  72. end
  73.  
  74. function panel:ShowLine(Line)
  75.   term.setCursorPos(self.X, Line-self.Shift+2)
  76.   if self.tFiles[Line]~=nil then
  77.     local Name=self.tFiles[Line]
  78.     if self.tSize[Line]=='DIR' then Name='/'..Name end
  79.     if #Name>self.wPan-4 then Name=Name:sub(1,self.wPan-6)..'..' end
  80.     Name=' '..Name..string.rep(' ',self.wPan-#Name-4)..' '
  81.     term.write('|')
  82.     if self==Active and Line==self.CurLine then
  83.       SetColor(SelectCl)
  84.       term.write(Name)
  85.       SetColor(PanelCl)
  86.     else
  87.       term.write(Name)
  88.     end
  89.     term.write('|')
  90.   else
  91.     term.write('|'..string.rep(' ',self.wPan-2)..'|')
  92.   end
  93. end
  94.  
  95. function panel:ShowLines()
  96.   for i=self.Shift, self.Shift+hScr-5 do
  97.     self:ShowLine(i)
  98.   end
  99. end
  100.  
  101. function panel:ShowLast()
  102.   term.setCursorPos(self.X, hScr-2)
  103.   term.write('+'..string.rep('-',self.wPan-2)..'+')
  104.   term.setCursorPos(self.X+2, hScr-2)
  105.   write(self.tSize[self.CurLine])
  106.   if self.tSize[self.CurLine]~='DIR' then write(' b') end
  107. end
  108.  
  109. function panel:Show()
  110.   if self.CurLine>#self.tFiles then self.CurLine=#self.tFiles end  
  111.   SetColor(PanelCl)
  112.   self:ShowFirst()
  113.   self:ShowLines()
  114.   self:ShowLast()
  115. end
  116.  
  117. function panel:GetFiles()
  118.   local Files=fs.list(self.Path)
  119.   table.sort(Files)
  120.   if self.Path=='' then
  121.     self.tFiles={}
  122.     self.tSize={}
  123.   else
  124.     self.tFiles={'..'}
  125.     self.tSize={'DIR'}
  126.   end
  127.   for n,Item in pairs(Files) do
  128.     local sPath=fs.combine(self.Path,Item)
  129.     if fs.isDir(sPath) then
  130.       table.insert(self.tFiles,Item)
  131.       table.insert(self.tSize,'DIR')
  132.     end
  133.   end
  134.   for n,Item in pairs(Files) do
  135.     local sPath=fs.combine(self.Path,Item)
  136.     if not fs.isDir(sPath) then
  137.       table.insert(self.tFiles,Item)
  138.       table.insert(self.tSize,fs.getSize(sPath))
  139.     end
  140.   end
  141.   self:Show()
  142. end
  143.  
  144. function panel:SetPos(FileName)
  145.   self.Path,FileName=FileName:match('(.-)/?([^/]+)$')
  146.   shell.setDir(self.Path)
  147.   self.CurLine=1
  148.   self.Shift=1
  149.   self:GetFiles()
  150.   for i=1,#self.tFiles do
  151.     if self.tFiles[i]==FileName then
  152.       self.CurLine=i
  153.       break
  154.     end
  155.   end
  156.   if Active.CurLine>hScr-4 then
  157.     Active.Shift=Active.CurLine-hScr+6
  158.   end
  159. end
  160.  
  161. function panel:new(x,path,wP)
  162.   local obj={X = x, Path =path, tFiles={}, tSize={}, CurLine=1, Shift=1, wPan=wP}
  163.   setmetatable(obj,self)
  164.   self.__index=self
  165.   return obj
  166. end
  167.  
  168. local Left =panel:new(1,'',wPanP)
  169. local Rght =panel:new(Left.wPan,shell.dir(),wPanA)
  170.  
  171. Active =Rght
  172.  
  173. local Fpanel ={}
  174. setmetatable(Fpanel,panel)
  175.  
  176. function Fpanel:new(x,path,wP)
  177.   local obj=panel:new(x,path,wP)
  178.   setmetatable(obj,self)
  179.   self.__index=self
  180.   return obj
  181. end
  182.  
  183. local function FindFile(FileName,Path)
  184.   local Result={}
  185.   local Files=fs.list(Path)
  186.   for i=1,#Files do
  187.     if string.match(Files[i],FileName) then
  188.       table.insert(Result,fs.combine(Path,Files[i]))
  189.     end
  190.   end
  191.   for i=1,#Files do
  192.     local sPath=fs.combine(Path,Files[i])
  193.     if fs.isDir(sPath) then
  194.       local Files1=FindFile(FileName,sPath)
  195.       for j=1,#Files1 do table.insert(Result,Files1[j]) end
  196.     end
  197.   end
  198.   return Result
  199. end
  200.  
  201. function Fpanel:GetFiles()
  202.   local code={{'%.','%%.'},{'*','.-'},{'?','.'}}
  203.   local Templ=self.Path
  204.   for i=1,#code do Templ=Templ:gsub(code[i][1],code[i][2]) end
  205.   self.tFiles=FindFile('^'..Templ..'$','')
  206.   table.insert(self.tFiles,1,'..')
  207.   self.tSize={'DIR'}
  208.   for i=2,#self.tFiles do
  209.     if fs.isDir(self.tFiles[i]) then
  210.       self.tSize[i]='DIR'
  211.     else
  212.       self.tSize[i]=fs.getSize(self.tFiles[i])
  213.     end
  214.   end
  215.   self:Show()
  216. end
  217.  
  218. function Fpanel:ShowFirst()
  219.   local p='Find:'..self.Path
  220.   if #p> self.wPan-6 then p='..'..p:sub(#p-self.wPan+7) end
  221.   p=' '..p..' '
  222.   term.setCursorPos(self.X, 1)
  223.   term.write('+'..string.rep('-',self.wPan-2)..'+')
  224.   term.setCursorPos(self.X+(self.wPan-#p)/2,1)
  225.   SetColor(SelectCl)
  226.   term.write(p)
  227.   SetColor(PanelCl)
  228. end
  229.  
  230. local Find =Fpanel:new(1,'',wScr)
  231.  
  232. local function ShowPanels()
  233.   SetColor(NormalCl)
  234.   term.clear()
  235.   if Active==Find then
  236.     Find:GetFiles()
  237.   else
  238.     Left:GetFiles()
  239.     Rght:GetFiles()
  240.   end
  241.   term.setCursorPos(xMenu, hScr)
  242.   for i=1,#Menu do
  243.     if #Menu[i]>0 then
  244.     SetColor(NormalCl)
  245.     term.write(' F'..i)
  246.     SetColor(SelectCl)
  247.     term.write(Menu[i])
  248.     end
  249.   end
  250.   term.setCursorBlink(true)
  251. end
  252.  
  253. local function Dialog(cl,Lines,Str,But)
  254.   SetColor(cl)
  255.   local H=#Lines+3
  256.   local CurBut=1
  257.   if Str then H=H+1 CurBut=0 end
  258.   if not But then But={'Ok'} end
  259.   local function Buttons()
  260.     local Butt=''
  261.     for i=1,#But do
  262.       if i==CurBut then
  263.         Butt=Butt..'['..But[i]..']'
  264.       else
  265.         Butt=Butt..' '..But[i]..' '
  266.       end
  267.     end
  268.     return Butt
  269.   end
  270.   local W=#Buttons()
  271.   for i=1,#Lines do
  272.     if #Lines[i]>W then W=#Lines[i] end
  273.   end
  274.   if Str and (#Str>W) then W=#Str end
  275.   W=W+4
  276.   local x= math.ceil((wScr-W)/2)
  277.   local y= math.ceil((hScr-H)/2)
  278.   term.setCursorPos(x, y)
  279.   term.write(string.rep('=',W))
  280.   for i=1,#Lines+2 do
  281.     term.setCursorPos(x, y+i)
  282.     term.write('H'..string.rep(' ',W-2)..'H')
  283.   end
  284.   term.setCursorPos(x, y+H-1)
  285.   term.write(string.rep('=',W))
  286.   for i=1,#Lines do
  287.     term.setCursorPos(x+(W-#Lines[i])/2, y+i)
  288.     term.write(Lines[i])
  289.   end
  290.  
  291.   while true do
  292.     term.setCursorBlink(CurBut==0)
  293.     term.setCursorPos(x+(W-#Buttons())/2, y+H-2)
  294.     term.write(Buttons())
  295.     if CurBut==0 then
  296.       term.setCursorPos(x+2, y+H-3)
  297.       local S=Str
  298.       if #S>W-4 then S='..'..S:sub(#S-W+7) end
  299.       term.write(S)
  300.     end
  301.     local event,p1=os.pullEvent()
  302.     if event=='key' then
  303.       if p1==keys.enter then
  304.         if CurBut==0 then CurBut=1 end
  305.         return But[CurBut],Str
  306.       elseif p1==keys.left and CurBut~=0 then
  307.         if CurBut>1 then CurBut=CurBut-1 end
  308.       elseif p1==keys.right and CurBut~=0 then
  309.         if CurBut<#But then CurBut=CurBut+1 end
  310.       elseif p1==keys.tab then
  311.         if CurBut<#But then CurBut=CurBut+1
  312.         else CurBut=Str and 0 or 1
  313.         end
  314.       elseif p1==keys.backspace and CurBut==0 and #Str>0 then
  315.         term.setCursorPos(x, y+H-3)
  316.         term.write('H'..string.rep(' ',W-2)..'H')
  317.         Str=Str:sub(1,#Str-1)
  318.       end
  319.     elseif event=='char' and CurBut==0 then
  320.       Str=Str..p1
  321.     end
  322.   end
  323. end
  324.  
  325. local cmd, Alt, Ok, Name
  326.  
  327. local function call(...)
  328.   local r,e=pcall(...)
  329.   if not r then Dialog(AlarmWinCl,{e}) end
  330.   return r
  331. end
  332.  
  333. local function CopyMove(action,func)
  334.   if Active==Find then return end
  335.   Name = ((Active==Rght) and Left or Rght).Path..'/'..cmd
  336.   cmd=Active.Path..'/'..cmd
  337.   Ok,Name=Dialog(WindowCl,{action,cmd,'to:'},Name,{'<Ok>','Cansel'})
  338.   if Ok=='<Ok>' then
  339.     if cmd==Name then
  340.       Dialog(AlarmWinCl,{'Cannot copy/move file to itself!'})
  341.     else
  342.       if fs.exists(Name) then
  343.         if Dialog(AlarmWinCl,{'File already exists!',Name,'Overwrite it?'},nil,{'Yes','No'})=='Yes' then
  344.           if call(fs.delete,Name) then call(func,cmd, Name) end
  345.         end
  346.       else
  347.         call(func,cmd, Name)
  348.       end
  349.     end
  350.   end
  351.   ShowPanels()
  352. end
  353.  
  354. local work=true
  355. local eventKey={}
  356. eventKey[keys.up]=function()
  357.   if Active.CurLine>1 then
  358.     local Line
  359.     Line,Active.CurLine=Active.CurLine,Active.CurLine-1
  360.     if Active.CurLine<Active.Shift then
  361.       Active.Shift=Active.CurLine
  362.       Active:ShowLines()
  363.     else
  364.       Active:ShowLine(Active.CurLine)
  365.       Active:ShowLine(Line)
  366.     end
  367.     Active:ShowLast()
  368.   end
  369. end
  370.  
  371. eventKey[keys.down]=function()
  372.   if Active.CurLine<#Active.tFiles then
  373.     local Line
  374.     Line,Active.CurLine=Active.CurLine,Active.CurLine+1
  375.     if Active.CurLine>Active.Shift+hScr-5 then
  376.       Active.Shift=Active.CurLine-hScr+5
  377.       Active:ShowLines()
  378.     else
  379.       Active:ShowLine(Active.CurLine)
  380.       Active:ShowLine(Line)
  381.     end
  382.     Active:ShowLast()
  383.   end
  384. end
  385.  
  386. eventKey[keys.left]=function()
  387.   if curpos<#cmdstr then curpos=curpos+1 end
  388. end
  389.  
  390. eventKey[keys.right]=function()
  391.   if curpos>0 then curpos=curpos-1 end
  392. end
  393.  
  394. eventKey[keys.tab]=function()
  395.   if Active==Find then return end
  396.   if Active==Left then
  397.     Active=Rght
  398.     Rght.wPan=wPanA
  399.     Left.wPan=wPanP
  400.   else
  401.     Active=Left
  402.     Rght.wPan=wPanP
  403.     Left.wPan=wPanA
  404.   end
  405.   Rght.X=Left.wPan
  406.   shell.setDir(Active.Path)
  407.   ShowPanels()
  408. end
  409.  
  410. eventKey[keys.enter]=function()
  411.   local function exec(cmd)
  412.     SetColor(NormalCl)
  413.     term.clear()
  414.     term.setCursorPos(1,1)
  415.     shell.run(cmd)
  416.     sleep(3)
  417.     ShowPanels()
  418.   end
  419.   curpos=0
  420.   if Alt=='C' then
  421.     cmdstr=cmdstr..cmd..' '
  422.   else
  423.     if cmdstr~='' then
  424.       exec(cmdstr)
  425.       cmdstr=''
  426.       return
  427.     end
  428.     if Active==Find then
  429.       Active=Find.Last
  430.       if cmd~='..' then Active:SetPos(cmd) end
  431.       ShowPanels()
  432.       return
  433.     end
  434.     if Active.tSize[Active.CurLine]=='DIR' then
  435.       if cmd=='..' then  Active:SetPos(Active.Path)
  436.       else  Active:SetPos(shell.resolve(cmd)..'/..')  end
  437.       Active:Show()
  438.     else
  439.       exec(cmd)
  440.     end
  441.   end
  442. end
  443.  
  444. eventKey[keys.backspace]=function()
  445.   if cmdstr~='' then
  446.     if curpos==0 then cmdstr=cmdstr:sub(1,-2)
  447.     else cmdstr=cmdstr:sub(1,-2-curpos)..cmdstr:sub(-curpos)
  448.     end
  449.   end
  450. end
  451.  
  452. eventKey[keys.delete]=function()
  453.   if cmdstr~='' then
  454.     if curpos>0 then
  455.       curpos=curpos-1
  456.       if curpos==0 then
  457.         cmdstr=cmdstr:sub(1,-2)
  458.       else
  459.         cmdstr=cmdstr:sub(1,-2-curpos)..cmdstr:sub(-curpos)
  460.       end
  461.     end
  462.   end
  463. end
  464.  
  465. eventKey[keys['end']]=function() curpos=0 end
  466.  
  467. eventKey[keys.home]=function() curpos=#cmdstr end
  468.  
  469. eventKey[keys.leftShift]=function()
  470.   Alt='S'
  471.   os.startTimer(0.5)
  472. end
  473. eventKey[keys.rightShift]=eventKey[keys.leftShift]
  474.  
  475. eventKey[keys.leftCtrl]=function()
  476.   Alt='C'
  477.   os.startTimer(0.5)
  478. end
  479. eventKey[keys.rightCtrl]=eventKey[keys.leftCtrl]
  480.  
  481. eventKey[keys.leftAlt]=function()
  482.   Alt='A'
  483.   os.startTimer(0.5)
  484. end
  485. eventKey[keys.rightAlt]=eventKey[keys.leftAlt]
  486.  
  487. eventKey[keys.f1]=function()
  488.   if Active==Find then return end
  489.   Dialog(SelectCl,help)
  490.   ShowPanels()
  491. end
  492.  
  493. eventKey[keys.f4]=function()
  494.   if Alt=='S' then
  495.     Alt=''
  496.     Ok,Name=Dialog(WindowCl,{'File name:'},'',{'<Ok>','Cansel'})
  497.     if Ok=='<Ok>' then
  498.       shell.run('/rom/programs/edit '..Name)
  499.     end
  500.   else
  501.     if Active.tSize[Active.CurLine]=='DIR' then
  502.       Dialog(AlarmWinCl,{'Error!', cmd, 'is not a file'})
  503.     else
  504.       shell.run('/rom/programs/edit '..cmd)
  505.     end
  506.   end
  507.   ShowPanels()
  508. end
  509.  
  510. eventKey[keys.f5]=function()
  511.   CopyMove('Copy file:',fs.copy)
  512. end
  513.  
  514. eventKey[keys.f6]=function()
  515.   CopyMove('Move file:',fs.move)
  516. end
  517.  
  518. eventKey[keys.f7]=function()
  519.   if Alt=='A' then
  520.     Alt=''
  521.     Ok,Name=Dialog(WindowCl,{'Find file/dir:','Use ? and * for any char(s)'},'',{'<Ok>','Cansel'})
  522.     if Ok=='<Ok>' then
  523.       Find.Path=Name
  524.       Find.CurLine=1
  525.       Find.Shift=1
  526.       if Active~=Find then
  527.         Find.Last=Active
  528.         Active=Find
  529.       end
  530.     end
  531.   else
  532.     if Active==Find then return end
  533.     Ok,Name=Dialog(WindowCl,{'Directory name:'},'',{'<Ok>','Cansel'})
  534.     if Ok=='<Ok>' then
  535.       if Name=='..' or fs.exists(shell.resolve(Name)) then
  536.         ShowPanels()
  537.         Dialog(AlarmWinCl,{' File exists '})
  538.       else
  539.         fs.makeDir(shell.resolve(Name))
  540.       end
  541.     end
  542.   end
  543.   ShowPanels()
  544. end
  545.  
  546. eventKey[keys.f8]=function()
  547.   if Active==Find then return end
  548.   if Dialog(AlarmWinCl,{'Do you want to delete', cmd..'?'}, nil, {'Yes','No'})=='Yes' then
  549.     if call(fs.delete,shell.resolve(cmd)) then
  550. --      if Active.CurLine==#Active.tFiles then Active.CurLine=Active.CurLine-1 end
  551.     end
  552.   end
  553.   ShowPanels()
  554. end
  555.  
  556. eventKey[keys.f10]=function()
  557.   work=false
  558. end
  559.  
  560. ShowPanels()
  561. ShowCmd()
  562. while work do
  563.   local event,p1=os.pullEvent()
  564.   cmd=Active.tFiles[Active.CurLine]
  565.   if event=='char' then
  566.     if curpos==0 then cmdstr=cmdstr..p1
  567.     else cmdstr=cmdstr:sub(1,-1-curpos)..p1..cmdstr:sub(-curpos)
  568.     end
  569.     ShowCmd()
  570.   elseif event=='key' then
  571.     if eventKey[p1]~=nil then
  572.       SetColor(PanelCl)
  573.       eventKey[p1]()
  574.       ShowCmd()
  575.     end
  576.   elseif event=='timer' then
  577.     Alt=''
  578.   end
  579. end
  580. SetColor(NormalCl)
  581. term.setCursorPos(1, hScr)
  582. term.clearLine()
  583. print('Thank you for using Midday Commander!')
RAW Paste Data