Advertisement
CrimsonTheLynx

Helen Commander

Jun 21st, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.68 KB | None | 0 0
  1. --[[ Helen Commander Ver. 1.9 ]]--
  2. --[[ Русификатор от CrimsonTheLynx ]]--
  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 = 0x0000AA,
  20. green = 0x00AA00,
  21. orange= 0xFFFF55,
  22. red = 0xFF5555
  23. }
  24. local keys = keyboard.keys
  25. local Left,Rght,Active,Find
  26. local wScr, hScr = gpu.maxResolution()
  27. if wScr>80 then wScr,hScr=80,25 end
  28. local cmd, scr, Menu
  29. local NormalCl, PanelCl, DirCl, SelectCl, WindowCl, AlarmWinCl
  30. local xMenu,cmdstr,curpos,work=-1,'',0,true
  31. local Shift,Ctrl,Alt=256,512,1024
  32.  
  33. local function SetColor(cl)
  34. gpu.setForeground(cl[1])
  35. gpu.setBackground(cl[2])
  36. end
  37.  
  38. local function saveScreen()
  39. scr={cl={}}
  40. scr.W,scr.H = gpu.getResolution()
  41. scr.cl[1]=gpu.getForeground()
  42. scr.cl[2]=gpu.getBackground()
  43. scr.posX, scr.posY = term.getCursor()
  44. for i=1,scr.H do
  45. scr[i]={}
  46. local FC,BC
  47. for j=1,scr.W do
  48. local c,fc,bc=gpu.get(j,i)
  49. if fc==FC then fc=nil end
  50. if bc==BC then bc=nil end
  51. if fc or bc then
  52. table.insert(scr[i],{fc=fc,bc=bc,c=""})
  53. FC,BC=fc or FC, bc or BC
  54. end
  55. scr[i][#scr[i]].c=scr[i][#scr[i]].c .. c
  56. end
  57. end
  58. gpu.setResolution(wScr,hScr)
  59. end
  60.  
  61. local function loadScreen()
  62. gpu.setResolution(scr.W,scr.H)
  63. term.setCursorBlink(false)
  64. for i=1,scr.H do
  65. local curX=1
  66. for j=1,#scr[i] do
  67. if scr[i][j].fc then gpu.setForeground(scr[i][j].fc) end
  68. if scr[i][j].bc then gpu.setBackground(scr[i][j].bc) end
  69. gpu.set(curX,i,scr[i][j].c) curX=curX+len(scr[i][j].c)
  70. end
  71. end
  72. SetColor(scr.cl)
  73. term.setCursor(scr.posX,scr.posY)
  74. term.setCursorBlink(true)
  75. end
  76.  
  77. local function ShowCmd()
  78. SetColor(NormalCl)
  79. term.setCursor(1, hScr-1)
  80. term.clearLine()
  81. term.write(shell.getWorkingDirectory()..'> '..cmdstr)
  82. term.setCursor(term.getCursor()-curpos, hScr-1)
  83. end
  84.  
  85. local panel ={wPan=math.ceil(wScr / 2)}
  86. function panel:ShowFirst()
  87. local p=self.Path..'/'
  88. if len(p)> self.wPan-6 then p='..'..sub(p,-self.wPan+7) end
  89. p=' '..p..' '
  90. gpu.set(self.X, 1,'-'..string.rep('-',self.wPan-2)..'¬')
  91. term.setCursor(self.X+(self.wPan-len(p))/2,1)
  92. if self==Active then
  93. SetColor(SelectCl)
  94. term.write(p)
  95. SetColor(PanelCl)
  96. else
  97. term.write(p)
  98. end
  99. end
  100.  
  101. function panel:ShowLine(Line)
  102. term.setCursor(self.X, Line-self.Shift+2)
  103. term.write('¦')
  104. if self.tFiles[Line]~=nil then
  105. local Name=self.tFiles[Line]
  106. if self.tSize[Line]=='DIR' then Name='/'..Name SetColor(DirCl) end
  107. if len(Name)>self.wPan-4 then Name=sub(Name,1,self.wPan-6)..'..' end
  108. Name=' '..Name..string.rep(' ',self.wPan-len(Name)-4)..' '
  109. if self==Active and Line==self.CurLine then SetColor(SelectCl) end
  110. term.write(Name)
  111. else
  112. term.write(string.rep(' ',self.wPan-2))
  113. end
  114. SetColor(PanelCl)
  115. term.write('¦')
  116. end
  117.  
  118. function panel:ShowLines()
  119. for i=self.Shift, self.Shift+hScr-5 do self:ShowLine(i) end
  120. end
  121.  
  122. function panel:ShowLast()
  123. gpu.set(self.X, hScr-2,'L'..string.rep('-',self.wPan-2)..'-')
  124. gpu.set(self.X+2, hScr-2, self.tSize[self.CurLine])
  125. end
  126.  
  127. function panel:Show()
  128. if self.CurLine>#self.tFiles then self.CurLine=#self.tFiles end
  129. SetColor(PanelCl)
  130. self:ShowFirst()
  131. self:ShowLines()
  132. self:ShowLast()
  133. end
  134.  
  135. function panel:GetFiles()
  136. local Files={}
  137. for name in fs.list(self.Path) do
  138. table.insert(Files, name)
  139. end
  140. if self.Path=='' then
  141. self.tFiles={}
  142. self.tSize={}
  143. else
  144. self.tFiles={'..'}
  145. self.tSize={'DIR'}
  146. end
  147. for n,Item in pairs(Files) do
  148. if Item:sub(-1) == '/' then
  149. table.insert(self.tFiles,Item)
  150. table.insert(self.tSize,'DIR')
  151. end
  152. end
  153. for n,Item in pairs(Files) do
  154. if Item:sub(-1) ~= '/' then
  155. local sPath=fs.concat(self.Path,Item)
  156. table.insert(self.tFiles,Item)
  157. table.insert(self.tSize,fs.size(sPath).." b")
  158. end
  159. end
  160. self:Show()
  161. end
  162.  
  163. function panel:SetPos(FileName)
  164. if fs.isDirectory(FileName) then FileName=FileName..'/' end
  165. self.Path,FileName=FileName:match('(.-)/?([^/]+/?)$')
  166. shell.setWorkingDirectory(self.Path)
  167. self.CurLine=1
  168. self.Shift=1
  169. self:GetFiles()
  170. for i=1,#self.tFiles do
  171. if self.tFiles[i]==FileName then
  172. self.CurLine=i
  173. break
  174. end
  175. end
  176. if Active.CurLine>hScr-4 then
  177. Active.Shift=Active.CurLine-hScr+6
  178. end
  179. end
  180.  
  181. function panel:new(x,path)
  182. local obj={X = x, Path =path, tFiles={}, tSize={}, CurLine=1, Shift=1}
  183. return setmetatable(obj,{__index=panel})
  184. end
  185.  
  186. local Fpanel ={wPan=wScr}
  187. setmetatable(Fpanel,{__index=panel})
  188.  
  189. function Fpanel:new(x,path)
  190. local obj=panel:new(x,path)
  191. return setmetatable(obj,{__index=Fpanel})
  192. end
  193.  
  194. local function FindFile(FileName,Path)
  195. local Result={}
  196. local SubDir={}
  197. for name in fs.list(Path) do
  198. if string.sub(name, -1) == '/' then
  199. table.insert(SubDir, Path..name)
  200. name=name..".."
  201. end
  202. if string.match(name, FileName) then
  203. table.insert(Result, Path..name)
  204. end
  205. end
  206. for i=1,#SubDir do
  207. local Files = FindFile(FileName,SubDir[i])
  208. for j=1,#Files do table.insert(Result,Files[j]) end
  209. end
  210. return Result
  211. end
  212.  
  213. function Fpanel:GetFiles()
  214. local code={{'%.','%%.'},{'*','.-'},{'?','.'}}
  215. local Templ=self.Path
  216. for i=1,#code do Templ=Templ:gsub(code[i][1],code[i][2]) end
  217. self.tFiles=FindFile('^'..Templ..'$','')
  218. table.insert(self.tFiles,1,'..')
  219. self.tSize={'DIR'}
  220. for i=2,#self.tFiles do
  221. if fs.isDirectory(self.tFiles[i]) then
  222. self.tSize[i]='DIR'
  223. else
  224. self.tSize[i]=tostring(fs.size(self.tFiles[i]))
  225. end
  226. end
  227. self:Show()
  228. end
  229.  
  230. function Fpanel:ShowFirst()
  231. local p='Find:'..self.Path
  232. if len(p)> self.wPan-6 then p='..'..sub(p,-self.wPan+7) end
  233. p=' '..p..' '
  234. gpu.set(self.X, 1,'-'..string.rep('-',self.wPan-2)..'¬')
  235. SetColor(SelectCl)
  236. gpu.set(self.X+(self.wPan-len(p))/2,1,p)
  237. SetColor(PanelCl)
  238. end
  239.  
  240. local function ShowPanels()
  241. SetColor(NormalCl)
  242. term.clear()
  243. if Active==Find then
  244. Find:Show()
  245. else
  246. Left:GetFiles()
  247. Rght:GetFiles()
  248. end
  249. term.setCursor(xMenu, hScr)
  250. for i=1,#Menu do
  251. if #Menu[i]>0 then
  252. SetColor(NormalCl)
  253. term.write(' F'..i)
  254. SetColor(SelectCl)
  255. term.write(Menu[i])
  256. end
  257. end
  258. term.setCursorBlink(true)
  259. end
  260.  
  261. local function Dialog(cl,Lines,Str,But)
  262. SetColor(cl)
  263. local H=#Lines+3
  264. local CurBut=1
  265. if Str then H=H+1 CurBut=0 end
  266. if not But then But={'Ok'} end
  267. local function Buttons()
  268. local Butt=''
  269. for i=1,#But do
  270. if i==CurBut then
  271. Butt=Butt..'['..But[i]..']'
  272. else
  273. Butt=Butt..' '..But[i]..' '
  274. end
  275. end
  276. return Butt
  277. end
  278. local W=len(Buttons())
  279. for i=1,#Lines do
  280. if len(Lines[i])>W then W=len(Lines[i]) end
  281. end
  282. if Str and (len(Str)>W) then W=len(Str) end
  283. W=W+4
  284. local x= math.ceil((wScr-W)/2)
  285. local y= math.ceil((hScr-H)/2)+1
  286. gpu.set(x-1, y, ' г'..string.rep('=',W-2)..'¬ ')
  287. for i=1,#Lines+2 do
  288. gpu.set(x-1, y+i, ' ¦'..string.rep(' ',W-2)..'¦ ')
  289. end
  290. gpu.set(x-1, y+H-1,' L'..string.rep('=',W-2)..'- ')
  291. for i=1,#Lines do
  292. if Lines.left then gpu.set(x+2, y+i, Lines[i])
  293. else gpu.set(x+(W-len(Lines[i]))/2, y+i, Lines[i]) end
  294. end
  295.  
  296. while true do
  297. term.setCursorBlink(CurBut==0)
  298. term.setCursor(x+(W-len(Buttons()))/2, y+H-2)
  299. term.write(Buttons())
  300. if CurBut==0 then
  301. local S=Str
  302. if len(S)>W-4 then S='..'..sub(S,-W+6) end
  303. term.setCursor(x+2, y+H-3) term.write(S)
  304. end
  305.  
  306. local eventname, _, ch, code = event.pull('key_down')
  307. if eventname == 'key_down' then
  308. if code == keys.enter then
  309. if CurBut==0 then CurBut=1 end
  310. return But[CurBut],Str
  311. elseif code == keys.left and CurBut~=0 then
  312. if CurBut>1 then CurBut=CurBut-1 end
  313. elseif code == keys.right and CurBut~=0 then
  314. if CurBut<#But then CurBut=CurBut+1 end
  315. elseif code == keys.tab then
  316. if CurBut<#But then CurBut=CurBut+1
  317. else CurBut=Str and 0 or 1
  318. end
  319. elseif code == keys.back and CurBut==0 then
  320. if #Str>0 then gpu.set(x+1, y+H-3, string.rep(' ',W-2)) Str=sub(Str,1,-2) end
  321. elseif ch > 0 and CurBut == 0 then
  322. Str = Str..unicode.char(ch)
  323. end
  324. end
  325. end
  326. end
  327.  
  328. local function call(func,...)
  329. local r,e=func(...)
  330. if not r then Dialog(AlarmWinCl,{e}) end
  331. return r
  332. end
  333.  
  334. local function CpMv(func,from,to)
  335. if fs.isDirectory(from) then
  336. if not fs.exists(to) then call(fs.makeDirectory,to) end
  337. for name in fs.list(from) do
  338. CpMv(func,fs.concat(from,name),fs.concat(to,name))
  339. end
  340. if func==fs.rename then call(fs.remove,from) end
  341. else
  342. if fs.exists(to) then
  343. if Dialog(AlarmWinCl,{'File already exists!',to,'Overwrite it?'},nil,{'Yes','No'})=='Yes' then
  344. if not call(fs.remove,to) then return end
  345. end
  346. end
  347. call(func,from,to)
  348. end
  349. end
  350.  
  351. local function CopyMove(action,func)
  352. if Active==Find then return end
  353. Name = ((Active==Rght) and Left or Rght).Path..'/'..cmd
  354. cmd=Active.Path..'/'..cmd
  355. local Ok,Name=Dialog(WindowCl,{action,cmd,'to:'},Name,{'<Ok>','Cancel'})
  356. if Ok=='<Ok>' then
  357. if Name:find("^"..cmd) then
  358. Dialog(AlarmWinCl,{'Cannot copy/move file to itself!'})
  359. else
  360. CpMv(func, cmd, Name)
  361. end
  362. end
  363. ShowPanels()
  364. end
  365.  
  366. local eventKey={}
  367. eventKey[keys.up]=function()
  368. if Active.CurLine>1 then
  369. local Line=Active.CurLine
  370. Active.CurLine=Line-1
  371. if Active.CurLine<Active.Shift then
  372. Active.Shift=Active.CurLine
  373. Active:ShowLines()
  374. else
  375. Active:ShowLine(Active.CurLine)
  376. Active:ShowLine(Line)
  377. end
  378. Active:ShowLast()
  379. end
  380. end
  381.  
  382. eventKey[keys.down]=function()
  383. if Active.CurLine<#Active.tFiles then
  384. local Line=Active.CurLine
  385. Active.CurLine=Active.CurLine+1
  386. if Active.CurLine>Active.Shift+hScr-5 then
  387. Active.Shift=Active.CurLine-hScr+5
  388. Active:ShowLines()
  389. else
  390. Active:ShowLine(Active.CurLine)
  391. Active:ShowLine(Line)
  392. end
  393. Active:ShowLast()
  394. end
  395. end
  396.  
  397. eventKey[keys.left]=function()
  398. if curpos<len(cmdstr) then curpos=curpos+1 end
  399. end
  400.  
  401. eventKey[keys.right]=function()
  402. if curpos>0 then curpos=curpos-1 end
  403. end
  404.  
  405. eventKey[keys.tab]=function()
  406. if Active==Find then return end
  407. Active = (Active==Rght) and Left or Rght
  408. shell.setWorkingDirectory(Active.Path)
  409. ShowPanels()
  410. end
  411.  
  412. eventKey[keys.enter]=function()
  413. local function exec(cmd)
  414. loadScreen() scr=nil
  415. shell.execute(cmd)
  416. saveScreen()
  417. ShowPanels()
  418. end
  419. curpos=0
  420. if cmdstr~='' then
  421. exec(cmdstr)
  422. cmdstr=''
  423. return
  424. end
  425. if Active==Find then
  426. Active=Find.Last
  427. if cmd~='..' then Active:SetPos("/"..cmd) end
  428. ShowPanels()
  429. return
  430. end
  431. if Active.tSize[Active.CurLine]=='DIR' then
  432. if cmd=='..' then Active:SetPos(Active.Path)
  433. else Active:SetPos(shell.resolve(cmd)..'/..') end
  434. Active:Show()
  435. else
  436. exec(cmd)
  437. end
  438. end
  439.  
  440. eventKey[Ctrl+keys.enter]=function()
  441. cmdstr=cmdstr..cmd..' '
  442. end
  443.  
  444. eventKey[Alt+keys.enter]=function()
  445. loadScreen()
  446. event.pull("key_down")
  447. gpu.setResolution(wScr,hScr)
  448. ShowPanels()
  449. end
  450.  
  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- Навигация",
  481. 'Enter - Изменить программу dir/запустить',
  482. 'Ctrl+Enter - Вставить в командную строку',
  483. 'Alt+Enter - Скрыть панели',
  484. 'F1 - Помощь',
  485. 'F4 - Редактирование файла',
  486. 'Shift+F4 - Создать новый файл',
  487. 'F5 - Copy файл/dir',
  488. 'F6 - Move файл/dir',
  489. 'F7 - Create directory',
  490. 'Alt+F7 - Find файл/директорию ',
  491. 'F8 - Delete файл/директорию ',
  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={'Помощь','','','Edit','Copy','Move','Dir','Del','','Exit'}
  581. else
  582. Menu={' Помощь','','',' 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 Helen Commander!!!')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement