Guest User

Untitled

a guest
Jan 22nd, 2018
291
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.50 KB | None | 0 0
  1. # =========================================
  2. # A toy text editor written in CoffeeScript
  3. # =========================================
  4. #
  5. # Requires ncurses bindings for node.js:
  6. # npm install ncurses
  7. #
  8. # Usage:
  9. # coffee editor.coffee FILENAME
  10. #
  11. # Ctrl+w saves
  12. # Ctrl+x exits
  13. #
  14. # =========================================
  15.  
  16. fs = require 'fs'
  17. ncurses = require 'ncurses'
  18.  
  19. class Position
  20. constructor: ->
  21. @x = 0
  22. @y = 0
  23.  
  24. set: (content, index) ->
  25. lines = content[0...index].split "\n"
  26. @x = lines[lines.length - 1].length
  27. @y = lines.length - 1
  28.  
  29. index: (content) ->
  30. lines = content.split "\n"
  31. index = lines[0...@y].join("\n").length + @x
  32. index += 1 if @y > 0
  33. index
  34.  
  35. move: (content, dx, dy) ->
  36. lines = content.split "\n"
  37. @y = Math.min Math.max(@y + dy, 0), lines.length - 1
  38. @x = Math.min Math.max(@x + dx, 0), (lines[@y] || '').length
  39.  
  40. class Viewport
  41. constructor: (@width, @height) ->
  42. @offset = { x: 0, y: 0 }
  43. @cursor = { x: 0, y: 0 }
  44.  
  45. adjust: (position) ->
  46. @reposition position
  47. @scroll position
  48. @reposition position
  49.  
  50. scroll: (position) ->
  51. if @cursor.x >= @width
  52. @offset.x = position.x - @width + 1
  53. @offset.x = Math.min Math.max(@offset.x, 0), position.x
  54. if @cursor.y >= @height
  55. @offset.y = position.y - @height + 1
  56. @offset.y = Math.min Math.max(@offset.y, 0), position.y
  57.  
  58. reposition: (position) ->
  59. @cursor.x = position.x - @offset.x
  60. @cursor.y = position.y - @offset.y
  61.  
  62. crop: (content) ->
  63. lines = content.split "\n"
  64. line[@offset.x...@offset.x + @width] for line in lines[@offset.y...@offset.y + @height]
  65.  
  66. class Editor
  67. constructor: (@viewport, @content) ->
  68. @position = new Position()
  69.  
  70. view: ->
  71. @viewport.crop @content
  72.  
  73. move: (dx, dy) ->
  74. @position.move @content, dx, dy
  75. @viewport.adjust @position
  76.  
  77. insert: (text) ->
  78. index = @position.index @content
  79. @content = @content[0...index] + text + @content[index...]
  80. newlines = text.split "\n"
  81. @move newlines[newlines.length - 1].length, newlines.length - 1
  82.  
  83. backspace: (count) ->
  84. index = @position.index(@content) - count
  85. if index < 0
  86. count += index
  87. index = 0
  88. @content = @content[0...index] + @content[index + count...]
  89. @position.set @content, index
  90. @viewport.adjust @position
  91.  
  92. class Application
  93. constructor: (@file) ->
  94. @window = new ncurses.Window
  95. @viewport = new Viewport @window.width, @window.height
  96. @editor = new Editor @viewport, fs.readFileSync @file, 'utf8'
  97.  
  98. @window.on 'inputChar', (c, i) =>
  99. switch i
  100. when ncurses.keys.UP
  101. @editor.move 0, -1
  102. when ncurses.keys.RIGHT
  103. @editor.move 1, 0
  104. when ncurses.keys.DOWN
  105. @editor.move 0, 1
  106. when ncurses.keys.LEFT
  107. @editor.move -1, 0
  108. when ncurses.keys.NEWLINE
  109. @editor.insert "\n"
  110. when ncurses.keys.BACKSPACE, 127
  111. @editor.backspace 1
  112. when 23 # Ctrl+w
  113. fs.writeFileSync @file, @editor.content
  114. when 24 # Ctrl+x
  115. @window.close()
  116. return
  117. else
  118. if i in [32..126]
  119. @editor.insert c
  120. @refresh()
  121.  
  122. @refresh()
  123. @window.refresh()
  124.  
  125. refresh: ->
  126. for line, i in @editor.view()
  127. padding = Array(@viewport.width - line.length + 1).join ' '
  128. @window.addstr i, 0, line + padding
  129. @window.cursor @viewport.cursor.y, @viewport.cursor.x
  130.  
  131. do ->
  132. file = process.argv[2]
  133. unless file?
  134. console.warn 'Must specify a file'
  135. else
  136. app = new Application file
Add Comment
Please, Sign In to add comment