DRlVER124

MiddayCommander 1.8

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