Class: Xim::Editor

Inherits:
Object
  • Object
show all
Includes:
Curses
Defined in:
lib/xim/editor.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Editor

Returns a new instance of Editor.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/xim/editor.rb', line 9

def initialize(opts = {})
  @opts = opts

  @mode = :normal

  file = @opts[:file]

  init_screens

  if file
    load_file(:file => file)
  else
    new_file
  end

  main_loop
end

Instance Attribute Details

#modeObject

Returns the value of attribute mode.



7
8
9
# File 'lib/xim/editor.rb', line 7

def mode
  @mode
end

Instance Method Details

#command_area_clearObject



337
338
339
340
341
# File 'lib/xim/editor.rb', line 337

def command_area_clear
  @command_scr.attrset(A_NORMAL)
  @command_scr.clear
  @command_scr.refresh
end

#command_deleteObject



276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/xim/editor.rb', line 276

def command_delete
  if @command_x == 0
    command_area_clear
    normal_mode
  else
    @command_scr.setpos(0, @command_scr.curx - 1)
    @command_x -= 1
    @command_scr.delch
    @command_string.slice!(@command_x)
    @command_scr.refresh
  end
end

#command_entry(ch) ⇒ Object



269
270
271
272
273
274
# File 'lib/xim/editor.rb', line 269

def command_entry(ch)
  @command_scr.addch(ch)
  @command_string = @command_string.insert(@command_x, ch)
  @command_x += 1
  @command_scr.refresh
end

#command_modeObject



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/xim/editor.rb', line 243

def command_mode
  @main_x = @main_scr.curx
  @main_y = @main_scr.cury

  @command_string = ""
  @command_x = 0
  @command_y = 0

  @command_scr.setpos(0, 0)
  @command_scr.deleteln
  @command_scr.addstr(":")
  @command_scr.refresh

  @mode = :command
end

#command_status_error(error) ⇒ Object



329
330
331
332
333
334
335
# File 'lib/xim/editor.rb', line 329

def command_status_error(error)
  command_area_clear
  @command_scr.attron(color_pair(COLOR_RED)|A_BOLD)
  @command_scr.addstr(error)
  @command_scr.attrset(A_NORMAL)
  @command_scr.refresh
end

#command_status_update(status) ⇒ Object



323
324
325
326
327
# File 'lib/xim/editor.rb', line 323

def command_status_update(status)
  command_area_clear
  @command_scr.addstr(status)
  @command_scr.refresh
end

#command_submitObject



289
290
291
292
293
# File 'lib/xim/editor.rb', line 289

def command_submit
  command_area_clear
  command_submit_process(@command_string)
  normal_mode
end

#command_submit_process(command) ⇒ Object



295
296
297
298
299
300
301
302
# File 'lib/xim/editor.rb', line 295

def command_submit_process(command)
  case command
  when 'w'
    command_write
  when 'q'
    quit
  end
end

#command_writeObject



304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'lib/xim/editor.rb', line 304

def command_write
  if @file_name
    tmpf = temp_file(@file_name)
    f = File.open(tmpf, 'w')
    @file_contents.each do |line|
      f.write(line)
    end
    f.close
    File.rename(tmpf, @file_name)
    command_status_update("\"#{@file_name}\" written")
  else
    command_status_error("E32: No file name")
  end
end

#cursor_delObject



195
196
197
198
199
200
201
202
203
204
205
# File 'lib/xim/editor.rb', line 195

def cursor_del
  if @file_x < (@file_contents[@file_y].length - 2)
    @main_scr.delch
    @file_contents[@file_y].slice!(@file_x)
  elsif @file_x == (@file_contents[@file_y].length - 2)
    @main_scr.delch
    cursor_left
    @file_contents[@file_y].slice!(@file_x)
  end
  @main_scr.refresh
end

#cursor_del_leftObject



207
208
209
210
211
212
213
214
215
216
# File 'lib/xim/editor.rb', line 207

def cursor_del_left
  if @file_x < (@file_contents[@file_y].length - 2)
    unless @main_scr.curx == 0
      cursor_left
      @main_scr.delch
      @file_contents[@file_y].slice!(@file_x)
    end
  end
  @main_scr.refresh
end

#cursor_downObject



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/xim/editor.rb', line 160

def cursor_down
  if @file_y < (@file_contents.length - 1)
    if @main_scr.cury == (@main_scr.maxy - 1)
      scroll_down
    else
      @main_scr.setpos(@main_scr.cury + 1, @main_scr.curx)
    end
    @file_y += 1

    if @file_x >= (@file_contents[@file_y].length - 2)
      @max_x = @file_contents[@file_y].length - 1
      @main_scr.setpos(@main_scr.cury, @max_x)
      @file_x = @max_x
    end

    update_status_line
  end
end

#cursor_leftObject



187
188
189
190
191
192
193
# File 'lib/xim/editor.rb', line 187

def cursor_left
  if @file_x > 0
    @main_scr.setpos(@main_scr.cury, @main_scr.curx - 1)
    @file_x -= 1
    update_status_line
  end
end

#cursor_rightObject



179
180
181
182
183
184
185
# File 'lib/xim/editor.rb', line 179

def cursor_right
  if @file_x < (@file_contents[@file_y].length - 2)
    @main_scr.setpos(@main_scr.cury, @main_scr.curx + 1)
    @file_x += 1
    update_status_line
  end
end

#cursor_upObject



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/xim/editor.rb', line 141

def cursor_up
  if @file_y > 0
    if (@main_scr.cury == 0)
      scroll_up
    else
      @main_scr.setpos(@main_scr.cury - 1, @main_scr.curx)
    end
    @file_y -= 1

    if @file_x >= (@file_contents[@file_y].length - 2)
      @max_x = @file_contents[@file_y].length - 1
      @main_scr.setpos(@main_scr.cury, @max_x)
      @file_x = @max_x
    end

    update_status_line
  end
end

#init_screensObject



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/xim/editor.rb', line 27

def init_screens
  Curses.init_screen
  Curses.start_color

  Curses.init_pair(COLOR_RED,COLOR_WHITE,COLOR_RED)

  @screen = Curses::Window.new(0,0,0,0)
  @screen.keypad(true)

  @main_scr = @screen.subwin(@screen.maxy-2,0,0,0)
  @main_scr.keypad(true)
  @main_scr.idlok(true)
  @main_scr.scrollok(true)
  @main_scr.setscrreg(0, @screen.maxy)
  @main_scr.refresh

  @status_scr = @screen.subwin(1,0,@screen.maxy-2,0)
  @status_scr.keypad(true)
  @status_scr.refresh
  @status_scr.attrset(Curses::A_REVERSE)

  @command_scr = @screen.subwin(1,0,@screen.maxy-1,0)
  @command_scr.keypad(true)
  @command_scr.refresh

  Curses.noecho
  Curses.cbreak
  Curses.raw

  @screen.setpos(0, 0)
  @screen.refresh
end

#insert_entry(ch) ⇒ Object



343
344
345
346
347
348
# File 'lib/xim/editor.rb', line 343

def insert_entry(ch)
  @main_scr.insch(ch)
  @file_contents[@file_y] = @file_contents[@file_y].insert(@file_x, ch)
  cursor_right
  @main_scr.refresh
end

#insert_modeObject



265
266
267
# File 'lib/xim/editor.rb', line 265

def insert_mode
  @mode = :insert
end

#load_file(opts = {}) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/xim/editor.rb', line 60

def load_file(opts = {})
  @file_name = opts[:file]

  @file_x = 0
  @file_y = 0

  f = File.open(@file_name)
  @file_contents = f.readlines()

  @file_contents.each do |line|
    @main_scr.addstr(line)
  end

  @main_scr.setpos(0,0)
  @main_scr.refresh
  update_status_line
end

#main_loopObject



92
93
94
95
96
97
98
# File 'lib/xim/editor.rb', line 92

def main_loop
  loop do
    react_to_key
  end
rescue Interrupt => e
  quit
end

#new_file(opts = {}) ⇒ Object



78
79
80
81
82
83
84
# File 'lib/xim/editor.rb', line 78

def new_file(opts = {})
  @file_x = 0
  @file_y = 0
  @file_contents = ["\n"]
  @file_name = nil
  update_status_line
end

#normal_modeObject



259
260
261
262
263
# File 'lib/xim/editor.rb', line 259

def normal_mode
  @main_scr.refresh

  @mode = :normal
end

#quitObject



86
87
88
89
90
# File 'lib/xim/editor.rb', line 86

def quit
  Curses.close_screen
  puts "closing ..."
  exit(0)
end

#react_to_keyObject



100
101
102
103
104
105
106
# File 'lib/xim/editor.rb', line 100

def react_to_key
  case @mode
  when :normal then react_to_key_normal
  when :command then react_to_key_command
  when :insert then react_to_key_insert
  end
end

#react_to_key_commandObject



123
124
125
126
127
128
129
130
131
# File 'lib/xim/editor.rb', line 123

def react_to_key_command
  ch = @command_scr.getch
  case ch.ord
  when 10 then command_submit
  when 32..126 then command_entry(ch)
  when 127 then command_delete
  when 27 then normal_mode
  end
end

#react_to_key_insertObject



133
134
135
136
137
138
139
# File 'lib/xim/editor.rb', line 133

def react_to_key_insert
  ch = @screen.getch
  case ch.ord
  when 10, 32..126 then insert_entry(ch)
  when 27 then normal_mode
  end
end

#react_to_key_normalObject



108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/xim/editor.rb', line 108

def react_to_key_normal
  case @screen.getch
  when Curses::Key::UP then cursor_up
  when Curses::Key::DOWN then cursor_down
  when Curses::Key::RIGHT then cursor_right
  when Curses::Key::LEFT then cursor_left
  when ?x then cursor_del
  when ?X then cursor_del_left
  when ?u then scroll_up
  when ?d then scroll_down
  when ?: then command_mode
  when ?i then insert_mode
  end
end

#scroll_downObject



222
223
224
# File 'lib/xim/editor.rb', line 222

def scroll_down
  @main_scr.scrl(1)
end

#scroll_upObject



218
219
220
# File 'lib/xim/editor.rb', line 218

def scroll_up
  @main_scr.scrl(-1)
end

#status_lineObject



239
240
241
# File 'lib/xim/editor.rb', line 239

def status_line
  "#{@file_name ? @file_name : '[No Name]'} [#{@file_x},#{@file_y}]"
end

#temp_file(orig_file) ⇒ Object



319
320
321
# File 'lib/xim/editor.rb', line 319

def temp_file(orig_file)
  orig_file + '.tmp.' + Random.new.rand(1000000).to_s
end

#update_status_lineObject



226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/xim/editor.rb', line 226

def update_status_line
  x = @main_scr.curx
  y = @main_scr.cury

  @status_scr.setpos(0, 0)
  @status_scr.deleteln
  @status_scr.addstr(status_line)
  @status_scr.refresh

  @main_scr.setpos(y,x)
  @main_scr.refresh
end