Advertisement
Guest User

vim

a guest
May 4th, 2014
204
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.81 KB | None | 0 0
  1. --Porting vim.lua from a CC script I found on pastebin
  2.  
  3.  
  4. --Todo:
  5. --port rest of the functions to OC
  6. --add rest of the binds
  7.  
  8. --add line numbering (use bind to toggle it)
  9.  
  10.  
  11. --Adding imports first
  12.  
  13. local allthecomps = require("component")
  14. local event = require("event")
  15. local fs = require("filesystem")
  16. local gpu = allthecomps.gpu --will I need it? I do not know
  17. local keyboard = require("keyboard")
  18. local term = require("term")
  19.  
  20. local state = 0
  21.  
  22. local tArgs = { ... }
  23.  
  24. local x,y = 1,1
  25. local w,h = gpu.getResolution() --rather than term.getsize. apparently I do need the gpu.
  26. local tLines = {} --the central table the entire file is stored in.
  27. --maybe this will be the site of optimization
  28. local scrollX, scrollY = 0,0
  29.  
  30. local clipboard = {}
  31.  
  32. local sStatus,sSearch = "",""
  33.  
  34. local bSearchBack = false
  35.  
  36. if #tArgs == 0 then
  37. error("Usage: vim <path>")
  38. end
  39.  
  40. local sPath = fs.canonical(tArgs[1])
  41. local sFileName = string.match(sPath, "[^/]+$")
  42. local bReadOnly = false --fs.isReadOnly(sPath) --I don't think isReadOnly exists in OC
  43. local bReadOnlyW = false
  44.  
  45. if fs.exists(sPath) and fs.isDirectory(sPath) then
  46. error("Cannot edit a directory") --should add support for viewing dirs, or maybe not to save memory
  47. end
  48.  
  49. local bNewFile = false
  50.  
  51. local bChanged = false
  52.  
  53. local redrawS
  54.  
  55. print(1)
  56.  
  57. -- Helper functions
  58.  
  59. local function getFilesize()
  60. local filesize = 0
  61. for k,v in pairs(tLines) do
  62. filesize = filesize + string.len(v)+1
  63. end
  64. return filesize
  65. end
  66.  
  67. local function redrawStatus(bsec)
  68. local _x,_y = term.getCursor()
  69. term.setCursor(1, h)
  70. if not bsec then
  71. term.clearLine()
  72. redrawCursor(true) --WHY, HOW IS THIS UNDEFINED? how
  73. end
  74. term.write(sStatus) --ooh, this structure is good
  75.  
  76. term.setCursor(_x,_y)
  77. end
  78.  
  79. local function redrawCursor(bsec)
  80. local size = string.len(tostring(x)) + string.len(tostring(y)) + 4 --this is an offset
  81. local _x,_y = term.getCursor() --test term.setCursor
  82.  
  83. term.setCursor(w - size, h) --this puts it at the end of the bottom line. nice
  84.  
  85. if not bsec then
  86. term.clearLine()
  87. redrawStatus(true)
  88. end
  89.  
  90. local percent
  91. if y == 1 then
  92. percent = "Top"
  93. elseif y == #tLines then
  94. percent = "Bot"
  95. else
  96. percent = math.floor(y / #tLines * 100) .. "%"
  97. end
  98.  
  99. term.write(y .. "," .. x .. " " .. percent)
  100.  
  101. term.setCursor(_x,_y)
  102. end
  103.  
  104. print(2)
  105. local function setStatus(_s)
  106. sStatus = _s
  107. redrawStatus()
  108. end
  109.  
  110. local function load() --should be renamed to init maybe
  111. local lines = 0
  112.  
  113. if fs.exists(sPath) then
  114. local file = fs.open(sPath, "r")
  115. local sLine = file:read() --here, tLines is populated by the file's lines
  116. while sLine do
  117. table.insert(tLines, sLine)
  118. sLine = file:read()
  119. lines = lines + 1
  120. end
  121. file:close() --this is very similar to OC it seems, maybe because of lua
  122. else
  123. table.insert(tLines,"")
  124. bNewFile = true
  125. end
  126.  
  127. local _sStatus = "\"" .. sFileName .. "\""
  128. if bNewFile then
  129. _sStatus = _sStatus .. " [New File]"
  130. end
  131. if bReadOnly then --where is this defined? search later
  132. _sStatus = _sStatus .. " [Read Only]"
  133. end
  134.  
  135. if not bNewFile then
  136. _sStatus = _sStatus .. " " .. lines .. "L, " .. getFilesize() .. "C" --maybe count words too. getWordcount()
  137. end
  138.  
  139. setStatus(_sStatus)
  140. end
  141.  
  142. local function save()
  143. local file = io.open(sPath, "w")
  144. if file then
  145. for k,v in pairs(tLines) do --maybe this algorithm could be optimized.
  146. file:write(v .. "\n")
  147. end
  148. file:close()
  149. return true
  150. end
  151. return false
  152. end
  153. print(3)
  154. -- local function reload() --I would like this later
  155. --loads the file again and sets the cursor to its previous place
  156.  
  157. local function redrawText()
  158. for _y=1, h-1 do --I don't understand how this for works.
  159. term.setCursor(1 - scrollX, _y)
  160. term.clearLine()
  161.  
  162. local sLine = tLines[_y + scrollY]
  163. if sLine ~= nil then
  164. term.write(sLine)
  165. end
  166. end
  167.  
  168. term.setCursor(x - scrollX, y - scrollY)
  169. end
  170.  
  171. local function setCursor(x, y)
  172. local screenX = x - scrollX
  173. local screenY = y - scrollY
  174.  
  175. local bRedraw = false
  176.  
  177. if screenX < 1 then
  178. scrollX = x - 1
  179. screenX = 1
  180. bRedraw = true
  181. elseif screenX > w then
  182. scrollX = x - w
  183. screenX = w
  184. bRedraw = true
  185. end
  186.  
  187. if screenY < 1 then
  188. scrollY = y - 1
  189. screenY = 1
  190. bRedraw = true
  191. elseif screenY > h-1 then
  192. scrollY = y - (h - 1)
  193. screenY = h - 1
  194. bRedraw = true
  195. end
  196.  
  197. term.setCursor(screenX, screenY)
  198.  
  199. if bRedraw then redrawText() end
  200. redrawCursor()
  201. end
  202.  
  203. local function redrawLine()
  204. local _x,_y = term.getCursor()
  205. term.setCursor(1 - scrollX, _y)
  206. term.clearLine()
  207. term.write(tLines[y])
  208. term.setCursor(_x, _y)
  209. end
  210.  
  211. local function cursor(param)
  212. if param == 203 then
  213. -- Left
  214. if keyboard.isControlDown() then --implementing this
  215. x = x
  216. --Move until you encounter the beginning of a new word
  217. --space, \n, ., ,...all the word seperator chars
  218. --maybe I should make a list of those. (or are they tables here?)
  219. --wait a minute, this seems to be the wrong func. should be in 0 or 2?
  220. --or no, this func is for the keys
  221. elseif x > 1 then
  222. x = x - 1
  223. setCursor(x,y)
  224. end
  225. return true
  226. elseif param == 205 then
  227. -- Right
  228. if x < string.len(tLines[y])+1 then
  229. x = x + 1
  230. setCursor(x,y)
  231. end
  232. return true
  233. elseif param == 200 then
  234. -- Up
  235. if y > 1 then
  236. y = y - 1
  237. local len = string.len(tLines[y])+1
  238. if x > len then
  239. x = len
  240. end
  241. setCursor(x,y)
  242. end
  243. return true
  244. elseif param == 208 then
  245. -- Down
  246. if y < #tLines then
  247. y = y + 1
  248. local len = string.len(tLines[y])+1
  249. if x > len then
  250. x = len
  251. end
  252. setCursor(x,y)
  253. end
  254. return true
  255. elseif param == 199 then
  256. -- Home
  257. x = 1
  258. setCursor(x,y)
  259. return true
  260. elseif param == 207 then
  261. -- End
  262. x = string.len(tLines[y]) + 1
  263. setCursor(x,y)
  264. return true
  265. elseif param == 201 then
  266. -- PageUp
  267. y = y - h + 1
  268. if y < 1 then y = 1 end
  269.  
  270. local len = tLines[y]:len()
  271. if x > len+1 then
  272. x = len+1
  273. end
  274.  
  275. setCursor(x,y)
  276. elseif param == 209 then
  277. -- PageDown
  278. y = y + h - 2
  279. if y > #tLines then
  280. y = #tLines
  281. end
  282.  
  283. local len = tLines[y]:len()
  284. if x > len+1 then
  285. x = len+1
  286. end --why doesn't this return true?
  287.  
  288. setCursor(x,y)
  289. end
  290.  
  291. return false
  292. end
  293.  
  294. local function searchF(s)
  295. sSearch = s
  296. for i = x+1, tLines[y]:len() do
  297. if tLines[y]:sub(i,i+s:len()-1) == s then
  298. return i,y
  299. end
  300. end
  301. for i = y+1, #tLines do
  302. if i > #tLines then break end
  303. for j = 1, tLines[i]:len() do
  304. if tLines[i]:sub(j,j+s:len()-1):lower() == s:lower() then
  305. return j,i
  306. end
  307. end
  308. end
  309. setStatus("search hit BOTTON, continuing at TOP")
  310. for i = 1, y do
  311. for j = 1, tLines[i]:len() do
  312. if tLines[i]:sub(j,j+s:len()-1):lower() == s:lower() then
  313. return j,i
  314. end
  315. end
  316. end
  317.  
  318. setStatus("E486: Pattern not found: " .. s)
  319. return x,y
  320. end
  321.  
  322. local function searchB(s)
  323. sSearch = s
  324. bSearchBack = true
  325. for i = x-1, 1, -1 do
  326. if x < 1 then break end
  327. if tLines[y]:sub(i,i+s:len()-1) == s then
  328. return i,y
  329. end
  330. end
  331. for i = y-1, 1, -1 do
  332. if i < 1 then break end
  333. for j = tLines[i]:len(), 1, -1 do
  334. if tLines[i]:sub(j,j+s:len()-1):lower() == s:lower() then
  335. return j,i
  336. end
  337. end
  338. end
  339. setStatus("search hit TOP, continuing at BOTTOM")
  340. for i = #tLines, y, -1 do
  341. for j = tLines[i]:len(), 1, -1 do
  342. if tLines[i]:sub(j,j+s:len()-1):lower() == s:lower() then
  343. return j,i
  344. end
  345. end
  346. end
  347. setStatus("E486: Pattern not found: " .. s)
  348. return x,y
  349. end
  350.  
  351. local function executecmd(rangemin, rangemax, command, amount, force)
  352. if force == nil then force = false end
  353. if amount == nil or amount == "" then amount = 1 end
  354.  
  355. if rangemin > rangemax then
  356. rangemax = rangemin
  357. end
  358.  
  359. if rangemin == 0 and rangemax == 0 then
  360. rangemin,rangemax = 0,0
  361. end
  362.  
  363. local function _quit()
  364. if bChanged and not force then
  365. setStatus("E37: No write since last change (add ! to override)")
  366. state = 0
  367. else
  368. setStatus("")
  369. state = -1
  370. end
  371. end
  372.  
  373. local function _save()
  374. if bReadOnly and not force then
  375. setStatus("E45: 'readonly' option is set (add ! to override)")
  376. state = 0
  377. else
  378. if not save() then
  379. setStatus("E212: Can't open file for writing")
  380. state = 0
  381. else
  382. local _sStatus = "\"" .. sFileName .. "\""
  383. if bNewFile then
  384. _sStatus = _sStatus .. " [New] "
  385. bNewFile = false
  386. end
  387.  
  388. _sStatus = _sStatus .. " " .. #tLines .. "L, " .. getFilesize() .. "C written"
  389.  
  390. setStatus(_sStatus)
  391. bChanged = false
  392. state = 0
  393. end
  394. end
  395. end
  396.  
  397. if command == "q" then
  398. _quit()
  399. elseif command == "w" then
  400. _save()
  401. elseif command == "wq" then
  402. _save()
  403. _quit()
  404. elseif command == "d" then --I have no idea
  405. local _y = y
  406. y = rangemin
  407. if rangemin ~= rangemax then
  408. amount = rangemax - rangemin + 1
  409. end
  410. clipboard = {}
  411.  
  412. for i = 1, amount do
  413. if tLines[y] ~= nil then
  414. table.insert(clipboard,tLines[y])
  415. table.remove(tLines, y)
  416.  
  417. if #tLines == 0 then table.insert(tLines, "") end
  418.  
  419. redrawText()
  420. bChanged = true
  421.  
  422. if tLines[y] == nil then
  423. y = y - 1
  424. break
  425. end
  426.  
  427. local len = string.len(tLines[y]) + 1
  428. if x > len then
  429. x = len
  430. setCursor(x,y)
  431. end
  432. end
  433. end
  434. y = _y
  435.  
  436. state = 0
  437. elseif command:sub(1,1) == "/" then
  438. x,y = searchF(command:sub(2))
  439. setCursor(x,y)
  440.  
  441. state = 0
  442.  
  443. elseif command:sub(1,1) == "?" then
  444. x,y = searchB(command:sub(2))
  445. setCursor(x,y)
  446.  
  447. state = 0
  448.  
  449. elseif command:sub(1,1) == "s" then --what was this?
  450.  
  451.  
  452. elseif command == "=" then
  453. setStatus(#tLines)
  454. state = 0
  455. else
  456. setStatus("E492: Not an editor command: " .. command)
  457. state = 0
  458. end
  459. end
  460.  
  461. -- _i, _j = string.find(s, _currentpattern)
  462. -- if _i==1 and _j==#s then
  463. -- do some true things! yay
  464.  
  465. local function defaultmode()
  466. local kb = "" --kb is short for keybuffer; I didn't like how long keybuffer was
  467. local function resetkb() kb = "" end
  468. while state == 0 do
  469. local sEvent,param = os.pullEvent() --sEvent seems to be the kind of event. how many events are there?
  470. if sEvent == "key" then --up, down, pageup, pagedown, home, end, backspace, del, maybe more
  471. if param == 28 then param = 208 end --down
  472. if param == 14 then param = 203 end --left, don't know what 28 and 14 are
  473. if cursor(param) then bGPressed = false end --so bGPressed isn't actually used anywhere...
  474. elseif sEvent == "char" then --I need to learn the events
  475. kb = kb .. param
  476. -- local _i, _j
  477. local function attv(patt) --checks if the pattern encompasses the keybuffer.
  478. _i, _e = string.find(kb, patt) --attv used to stand for assignThingsToVars, it's meaningless now
  479. return _i == 1 and _e == #kb
  480. end
  481.  
  482. if attv("^i$") then --or I could just do `if kb == "i"`
  483. state = 2
  484. -- elseif attv("^a$") then
  485. -- move the cursor over a char, change to insert mode
  486. elseif attv("^%s*gg") then --string.sub is inclusive?
  487. _i, _e = string.find(kb, "gg")
  488. local _nums = string.sub(kb, 0, _i-1) --will have to debug this
  489. if not tonumber(nums) then error("!!!!!! in gg nums contained chars!") end --why did I do this?
  490. if _nums ~= "" then
  491. x, y = 1, tonumber(nums) --all this crap is to support numbers
  492. setCursor(x, y)
  493. else
  494. x, y = 1, 1
  495. setCursor(x, y)
  496. end
  497. elseif kb == "G" then --need to add support for a number. with num seems to do same as #gg
  498. x,y = 1,#tLines
  499. redrawCursor(x,y)
  500. elseif kb == "yy" then
  501.  
  502. clipboard = {tLines[y]}
  503. keybuffer = ""
  504. else
  505. noreset = true --set this elsewhere if you don't want kb to be reset
  506. end
  507. if not noreset then kb = "" end
  508. -- elseif sEvent == "click" then --hope for highlight select maybe
  509. end
  510. end
  511. end
  512.  
  513.  
  514. local function defaultmode() --event pulling is difficult to port
  515. local keybuffer = ""
  516. while state == 0 do
  517. local sEvent,param = os.pullEvent()
  518. if sEvent == "key" then
  519. if param == 28 then param = 208 end
  520. if param == 14 then param = 203 end
  521. if cursor(param) then
  522. bGPressed = false
  523. end
  524. elseif sEvent == "char" then --yep, this system sucks
  525. if param == 'i' then --and I will implement some regexes.
  526. state = 2
  527. elseif param == ":" then
  528. state = 1
  529. elseif param == "π" then
  530. state = 3
  531. elseif param == "G" then
  532. x = 1
  533. y = #tLines
  534. setCursor(x,y)
  535.  
  536. elseif param == "n" then
  537. if bSearchBack then
  538. setStatus("?" .. sSearch)
  539. x,y = searchB(sSearch)
  540. else
  541. setStatus("/" .. sSearch)
  542. x,y = searchF(sSearch)
  543. end
  544. setCursor(x,y)
  545.  
  546. elseif param == "N" then
  547. if bSearchBack then
  548. setStatus("/" .. sSearch)
  549. x,y = searchF(sSearch)
  550. else
  551. setStatus("?" .. sSearch)
  552. x,y = searchB(sSearch)
  553. end
  554.  
  555. elseif param == "p" then
  556. for i = #clipboard, 1, -1 do
  557. table.insert(tLines,y+1,clipboard[i])
  558. end
  559. redrawText()
  560. bChanged = true
  561.  
  562. elseif param == "P" then
  563. for i = #clipboard, 1, -1 do
  564. table.insert(tLines,y,clipboard[i])
  565. end
  566. redrawText()
  567. bChanged = true
  568. end
  569.  
  570. if param == "g" then --shouldn't this be up with G?
  571. if keybuffer == "g" then
  572. x = 1
  573. y = 1
  574. setCursor(x,y)
  575.  
  576. keybuffer = ""
  577. else
  578. keybuffer = "g" --reacts with gg and not g then, and in the crappy way
  579. end
  580.  
  581. elseif param == "y" then
  582. if keybuffer == "y" then
  583. clipboard = {tLines[y]}
  584. keybuffer = ""
  585. else
  586. keybuffer = "y"
  587. end
  588.  
  589. elseif param == "d" then
  590. if keybuffer == "d" then
  591. clipboard = {tLines[y]}
  592. table.remove(tLines,y)
  593. if #tLines == 0 then table.insert(tLines,"") end
  594.  
  595. redrawText()
  596.  
  597. if y > #tLines then
  598. y = y - 1
  599. setCursor(x,y)
  600. end
  601. if x > tLines[y]:len()+1 then
  602. x = tLines[y]:len()
  603. setCursor(x,y)
  604. end
  605.  
  606. bChanged = true
  607.  
  608. keybuffer = ""
  609. else
  610. keybuffer = "d"
  611. end
  612. else
  613. keybuffer = ""
  614. end
  615. end
  616. end
  617. end
  618.  
  619. local function commandmode() --
  620. local command = ":"
  621.  
  622. term.setCursor(2,h) --maybe I'll have to align the destination coords, not likely though
  623.  
  624. setStatus(":")
  625.  
  626. while state == 1 do
  627. local _x,_y = term.getCursor()
  628. local sEvent,param = os.pullEvent() --event.pull(nil, ???therestofthefunc)
  629.  
  630. if sEvent == "key" then
  631. if param == 28 then
  632. -- Return
  633. command = command:sub(2)
  634.  
  635. if command:sub(1,1) == "s" or command:sub(1,1) == "/" or command:sub(1,1) == "?" then
  636. executecmd(0,0,command,0,false)
  637. else
  638. local _,_,minmax,cmd,amnt,force = command:find("(%d*,?%d*)([a-zA-Z=]*)(%d*)(!?)")
  639. local minim,maxim = 0,0
  640.  
  641. local i = 1
  642. local minmax2,flag = minmax:sub(i,i), false
  643. while minmax2 ~= "" do
  644. if minmax2 == "," then
  645. flag = true
  646. else
  647. if flag then
  648. maxim = maxim * 10 + tonumber(minmax2)
  649. else
  650. minim = minim * 10 + tonumber(minmax2)
  651. end
  652. end
  653. i = i + 1
  654. minmax2 = minmax:sub(i,i)
  655. end
  656.  
  657. executecmd(minim,maxim,cmd,amnt,force == "!")
  658. end
  659. elseif param == 59 then
  660. -- F1, the escape of this vim
  661. state = 0
  662. elseif param == 14 then
  663. -- Backspace
  664. if _x > 1 then
  665. command = string.sub(command,1,_x-2) .. string.sub(command,_x)
  666. _x = _x - 1
  667. term.setCursor(_x,_y)
  668. end
  669. if command == "" then
  670. state = 0
  671. end
  672. setStatus(command)
  673. elseif param == 203 then --why is left special?
  674. -- Left
  675. if _x > 1 then
  676. _x = _x + 1
  677. term.setCursor(_x,_y)
  678. end
  679. end
  680. elseif sEvent == "char" then
  681. command = string.sub(command,1,_x-1) .. param .. string.sub(command,_x)
  682. setStatus(command)
  683. _x = _x + 1
  684. term.setCursor(_x,_y)
  685. end
  686. end
  687.  
  688. setCursor(x,y)
  689. end
  690.  
  691. local function insertmode()
  692. local _sStatus = "-- INSERT -- "
  693. if bReadOnly and not bReadOnlyW then
  694. _sStatus = _sStatus .. " W10: Changing a readonly file"
  695. bReadOnlyW = true
  696. end
  697.  
  698. setStatus(_sStatus)
  699.  
  700. while state == 2 do
  701. local sEvent,param = os.pullEvent()
  702. if sEvent == "key" and not cursor(param) then
  703. if param == 59 then
  704. -- F1
  705. state = 0
  706. elseif param == 28 then
  707. -- Return
  708. local sLine = tLines[y]
  709. tLines[y] = string.sub(sLine,1,x-1)
  710. table.insert(tLines,y+1,string.sub(sLine,x))
  711.  
  712. redrawText()
  713.  
  714. x = 1
  715. y = y + 1
  716. setCursor(x,y)
  717. bChanged = true
  718. elseif param == 14 then
  719. -- Backspace
  720. if x > 1 then
  721. local sLine = tLines[y]
  722. tLines[y] = string.sub(sLine,1,x-2) .. string.sub(sLine,x)
  723. redrawLine()
  724.  
  725. x = x - 1
  726. elseif y > 1 then
  727. local sPrevLine = tLines[y-1]
  728. tLines[y-1] = sPrevLine .. tLines[y]
  729. table.remove(tLines, y)
  730.  
  731. redrawText()
  732.  
  733. x = string.len(sPrevLine) + 1
  734. y = y - 1
  735. end
  736.  
  737. setCursor(x,y)
  738. bChanged = true
  739.  
  740. elseif param == 211 then
  741. -- Del
  742. local sLine = tLines[y]
  743. local len = string.len(sLine)+1
  744. if x < len then
  745. tLines[y] = string.sub(sLine,1,x-1) .. string.sub(sLine,x+1)
  746. redrawLine()
  747. elseif y < #tLines then
  748. tLines[y] = sLine .. tLines[y+1]
  749. table.remove(tLines, y+1)
  750. redrawText()
  751. end
  752.  
  753. bChanged = true
  754. elseif param == 15 then
  755. -- Tab
  756. local sLine = tLines[y]
  757. tLines[y] = string.sub(sLine,1,x-1) .. " " .. string.sub(sLine,x)
  758. redrawLine()
  759.  
  760. x = x + 4
  761. setCursor(x,y)
  762.  
  763. bChanged = true
  764. end
  765.  
  766. elseif sEvent == "char" then
  767. local sLine = tLines[y]
  768. tLines[y] = string.sub(sLine,1,x-1) .. param .. string.sub(sLine,x)
  769. redrawLine()
  770.  
  771. x = x + string.len(param)
  772. setCursor(x,y)
  773.  
  774. bChanged = true
  775. end
  776. end
  777. setStatus("")
  778. end
  779.  
  780. local function tsmode() -- From what I can tell, this is the quitting mode.
  781.  
  782. end
  783. print(4)
  784. -- Main routine
  785.  
  786. local tModes = {}
  787. tModes[0] = defaultmode
  788. tModes[1] = commandmode
  789. tModes[2] = insertmode
  790. tModes[3] = tsmode
  791. print(4.1)
  792. -- term.clear()
  793. -- term.setCursor(1,1) --not needed after clear()
  794. term.setCursorBlink(true)
  795. print(4.2)
  796. load() --Breakage happens here
  797. print(4.3)
  798. redrawText()
  799. print(4.4)
  800. redrawS = redrawStatus
  801.  
  802. redrawCursor()
  803. print(4.5)
  804. while state ~= -1 do
  805. tModes[state]()
  806. end
  807. print(4.6)
  808. -- term.clear()
  809. term.setCursor(1,1)
  810.  
  811.  
  812. print(5)
  813.  
  814.  
  815. --Output:
  816. --# vim file
  817. --1
  818. --2
  819. --3
  820. --4
  821. --4.1
  822. --4.2
  823. --/tmp/vim/69: attempt to call global `redrawCursor` (a nil value)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement