Advertisement
slipers

Minecraft. Opencomputers. Midday Commander.

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