diakonos 0.8.11 → 0.9.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +433 -0
  3. data/LICENCE.md +675 -0
  4. data/bin/diakonos +6 -0
  5. data/diakonos-256-colour.conf +220 -0
  6. data/diakonos.conf +1802 -0
  7. data/help/about-help.dhf +31 -0
  8. data/help/clipboard.dhf +45 -0
  9. data/help/close-file.dhf +6 -0
  10. data/help/code-block-navigation.dhf +16 -0
  11. data/help/column-markers.dhf +15 -0
  12. data/help/config.dhf +69 -0
  13. data/help/cursor-stack.dhf +19 -0
  14. data/help/delete.dhf +41 -0
  15. data/help/extensions.dhf +125 -0
  16. data/help/file-type.dhf +24 -0
  17. data/help/key-mapping.dhf +127 -0
  18. data/help/line-numbers.dhf +22 -0
  19. data/help/macros.dhf +27 -0
  20. data/help/new-file.dhf +6 -0
  21. data/help/open-file.dhf +21 -0
  22. data/help/quit.dhf +7 -0
  23. data/help/resizing.dhf +19 -0
  24. data/help/ruby.dhf +17 -0
  25. data/help/save-file.dhf +10 -0
  26. data/help/scripting.dhf +92 -0
  27. data/help/search.dhf +103 -0
  28. data/help/shell.dhf +60 -0
  29. data/help/speed.dhf +23 -0
  30. data/help/support.dhf +15 -0
  31. data/help/switch-buffers.dhf +15 -0
  32. data/help/tabs.dhf +36 -0
  33. data/help/undo.dhf +9 -0
  34. data/help/uninstall.dhf +18 -0
  35. data/help/welcome.dhf +32 -0
  36. data/help/word-wrap.dhf +17 -0
  37. data/lib/diakonos/about.rb +69 -0
  38. data/lib/diakonos/bookmark.rb +46 -0
  39. data/lib/diakonos/buffer/bookmarking.rb +47 -0
  40. data/lib/diakonos/buffer/cursor.rb +335 -0
  41. data/lib/diakonos/buffer/delete.rb +170 -0
  42. data/lib/diakonos/buffer/display.rb +356 -0
  43. data/lib/diakonos/buffer/file.rb +157 -0
  44. data/lib/diakonos/buffer/indentation.rb +175 -0
  45. data/lib/diakonos/buffer/searching.rb +552 -0
  46. data/lib/diakonos/buffer/selection.rb +360 -0
  47. data/lib/diakonos/buffer/undo.rb +73 -0
  48. data/lib/diakonos/buffer-hash.rb +60 -0
  49. data/lib/diakonos/buffer-management.rb +59 -0
  50. data/lib/diakonos/buffer.rb +698 -0
  51. data/lib/diakonos/clipboard-klipper-dbus.rb +62 -0
  52. data/lib/diakonos/clipboard-klipper.rb +62 -0
  53. data/lib/diakonos/clipboard-osx.rb +59 -0
  54. data/lib/diakonos/clipboard-xclip.rb +60 -0
  55. data/lib/diakonos/clipboard.rb +47 -0
  56. data/lib/diakonos/config-file.rb +67 -0
  57. data/lib/diakonos/config.rb +381 -0
  58. data/lib/diakonos/core-ext/enumerable.rb +15 -0
  59. data/lib/diakonos/core-ext/hash.rb +60 -0
  60. data/lib/diakonos/core-ext/object.rb +6 -0
  61. data/lib/diakonos/core-ext/regexp.rb +6 -0
  62. data/lib/diakonos/core-ext/string.rb +122 -0
  63. data/lib/diakonos/ctag.rb +28 -0
  64. data/lib/diakonos/cursor.rb +27 -0
  65. data/lib/diakonos/display/format.rb +75 -0
  66. data/lib/diakonos/display.rb +336 -0
  67. data/lib/diakonos/extension-set.rb +49 -0
  68. data/lib/diakonos/extension.rb +34 -0
  69. data/lib/diakonos/finding.rb +40 -0
  70. data/lib/diakonos/functions/basics.rb +34 -0
  71. data/lib/diakonos/functions/bookmarking.rb +61 -0
  72. data/lib/diakonos/functions/buffers.rb +489 -0
  73. data/lib/diakonos/functions/clipboard.rb +70 -0
  74. data/lib/diakonos/functions/cursor.rb +264 -0
  75. data/lib/diakonos/functions/grepping.rb +83 -0
  76. data/lib/diakonos/functions/indentation.rb +71 -0
  77. data/lib/diakonos/functions/readline.rb +93 -0
  78. data/lib/diakonos/functions/search.rb +179 -0
  79. data/lib/diakonos/functions/selection.rb +98 -0
  80. data/lib/diakonos/functions/sessions.rb +78 -0
  81. data/lib/diakonos/functions/shell.rb +250 -0
  82. data/lib/diakonos/functions/tags.rb +65 -0
  83. data/lib/diakonos/functions/text-manipulation.rb +196 -0
  84. data/lib/diakonos/functions-deprecated.rb +77 -0
  85. data/lib/diakonos/functions.rb +292 -0
  86. data/lib/diakonos/grep.rb +98 -0
  87. data/lib/diakonos/help.rb +47 -0
  88. data/lib/diakonos/hooks.rb +13 -0
  89. data/lib/diakonos/installation.rb +19 -0
  90. data/lib/diakonos/interaction-handler.rb +216 -0
  91. data/lib/diakonos/interaction.rb +52 -0
  92. data/lib/diakonos/key-map.rb +62 -0
  93. data/lib/diakonos/keying.rb +442 -0
  94. data/lib/diakonos/line-mover.rb +42 -0
  95. data/lib/diakonos/list.rb +59 -0
  96. data/lib/diakonos/logging.rb +27 -0
  97. data/lib/diakonos/mode.rb +17 -0
  98. data/lib/diakonos/mouse.rb +18 -0
  99. data/lib/diakonos/number-fitter.rb +11 -0
  100. data/lib/diakonos/range.rb +31 -0
  101. data/lib/diakonos/readline/functions.rb +82 -0
  102. data/lib/diakonos/readline.rb +222 -0
  103. data/lib/diakonos/search.rb +58 -0
  104. data/lib/diakonos/sessions.rb +257 -0
  105. data/lib/diakonos/sized-array.rb +48 -0
  106. data/lib/diakonos/text-mark.rb +19 -0
  107. data/lib/diakonos/vendor/fuzzy_file_finder.rb +365 -0
  108. data/lib/diakonos/version.rb +25 -0
  109. data/lib/diakonos/window.rb +43 -0
  110. data/lib/diakonos.rb +592 -0
  111. metadata +160 -68
@@ -0,0 +1,98 @@
1
+ module Diakonos
2
+ module Functions
3
+
4
+ # Begins selecting text by anchoring (marking) the start of a selection.
5
+ def anchor_selection
6
+ buffer_current.anchor_selection
7
+ update_status_line
8
+ end
9
+
10
+ # Used for "shift+arrow" style selection.
11
+ def anchor_unanchored_selection( *method_and_args )
12
+ buffer_current.anchor_unanchored_selection
13
+ if method_and_args[0]
14
+ self.send method_and_args[0], *method_and_args[1..-1]
15
+ end
16
+ update_status_line
17
+ end
18
+
19
+ # Removes the highlighting from any text that matches the most recent
20
+ # search.
21
+ def clear_matches
22
+ buffer_current.clear_matches Buffer::DO_DISPLAY
23
+ end
24
+
25
+ # Unselects any current selection (stops selecting).
26
+ def remove_selection
27
+ buffer_current.remove_selection
28
+ update_status_line
29
+ end
30
+
31
+ # Selects the entire buffer contents.
32
+ def select_all
33
+ buffer_current.select_all
34
+ end
35
+
36
+ # Selects text between two regexps.
37
+ def select_block( beginning = nil, ending = nil, including_ending = true )
38
+ if beginning.nil?
39
+ input = get_user_input( "Start at regexp: " )
40
+ if input
41
+ beginning = Regexp.new input
42
+ end
43
+ end
44
+ if beginning && ending.nil?
45
+ input = get_user_input( "End before regexp: " )
46
+ if input
47
+ ending = Regexp.new input
48
+ end
49
+ end
50
+ if beginning && ending
51
+ buffer_current.select( beginning, ending, including_ending )
52
+ end
53
+ end
54
+
55
+ # Changes selection mode to block mode (rectangular selection).
56
+ def selection_mode_block
57
+ buffer_current.selection_mode_block
58
+ update_status_line
59
+ end
60
+
61
+ # Changes selection mode to normal mode (flow selection).
62
+ def selection_mode_normal
63
+ buffer_current.selection_mode_normal
64
+ update_status_line
65
+ end
66
+
67
+ # If currently selecting, stops selecting.
68
+ # If not currently selecting, begins selecting.
69
+ def toggle_selection
70
+ buffer_current.toggle_selection
71
+ update_status_line
72
+ end
73
+
74
+ # Selects the current line.
75
+ def select_line
76
+ buffer_current.select_current_line
77
+ update_status_line
78
+ end
79
+
80
+ # Selects the code block which wraps the current cursor position.
81
+ # Execute multiple times in succession to select increasingly outer code blocks.
82
+ def select_wrapping_block
83
+ buffer_current.select_wrapping_block
84
+ update_status_line
85
+ end
86
+
87
+ # Selects the word at the current cursor position.
88
+ # If the cursor is not on a word character, the first word following the cursor is selected.
89
+ def select_word
90
+ buffer_current.select_word
91
+ end
92
+
93
+ def select_word_another
94
+ buffer_current.select_word_another
95
+ end
96
+
97
+ end
98
+ end
@@ -0,0 +1,78 @@
1
+ module Diakonos
2
+ module Functions
3
+
4
+ def merge_session_settings
5
+ @settings.merge! @session.settings
6
+ end
7
+
8
+ def change_session_setting( key_ = nil, value = nil, do_redraw = DONT_REDRAW )
9
+ if key_.nil?
10
+ key = get_user_input( "Setting: " )
11
+ else
12
+ key = key_
13
+ end
14
+
15
+ if key
16
+ if value.nil?
17
+ value = get_user_input( "Value: " )
18
+ end
19
+ case @settings[ key ]
20
+ when String
21
+ value = value.to_s
22
+ when Integer
23
+ value = value.to_i
24
+ when TrueClass, FalseClass
25
+ value = value.to_b
26
+ end
27
+ @session.settings[ key ] = value
28
+ merge_session_settings
29
+ redraw if do_redraw
30
+ set_iline "#{key} = #{value}"
31
+ end
32
+ end
33
+
34
+ def name_session
35
+ name = get_user_input( 'Session name: ' )
36
+ if name
37
+ @session = Session.new("#{@session_dir}/#{name}")
38
+ save_session
39
+ end
40
+ end
41
+
42
+ def set_session_dir
43
+ path = get_user_input(
44
+ "Session directory: ",
45
+ history: @rlh_files,
46
+ initial_text: @session.dir,
47
+ do_complete: DONT_COMPLETE,
48
+ on_dirs: :accept_dirs
49
+ )
50
+ if path
51
+ @session.dir = File.expand_path( path )
52
+ save_session
53
+ set_iline "Session dir changed to: #{@session.dir}"
54
+ else
55
+ set_iline "(Session dir is: #{@session.dir})"
56
+ end
57
+ end
58
+
59
+ def toggle_session_setting( key_ = nil, do_redraw = DONT_REDRAW )
60
+ key = key_ || get_user_input( "Setting: " )
61
+ return if key.nil?
62
+
63
+ value = nil
64
+ if @session.settings[ key ].class == TrueClass || @session.settings[ key ].class == FalseClass
65
+ value = ! @session.settings[ key ]
66
+ elsif @settings[ key ].class == TrueClass || @settings[ key ].class == FalseClass
67
+ value = ! @settings[ key ]
68
+ end
69
+ if value != nil # explicitly true or false
70
+ @session.settings[ key ] = value
71
+ merge_session_settings
72
+ redraw if do_redraw
73
+ set_iline "#{key} = #{value}"
74
+ end
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,250 @@
1
+ module Diakonos
2
+ module Functions
3
+
4
+ # Change the current working directory (CWD) of the Diakonos process.
5
+ # @param [String] dir The directory to change to
6
+ def chdir( dir = nil )
7
+ dir ||= get_user_input( "Change to directory: ", initial_text: Dir.pwd )
8
+ if dir
9
+ Dir.chdir dir
10
+ end
11
+ end
12
+
13
+ # Substitutes Diakonos shell variables in a String.
14
+ # - $f: The current buffer's filename
15
+ # - $d: The current buffer's directory
16
+ # - $F: A space-separated list of all buffer filenames
17
+ # - $i: A string acquired from the user with a prompt
18
+ # - $c: The current clipboard text
19
+ # - $s: The currently selected text
20
+ # @param [String] string
21
+ # The string containing variables to substitute
22
+ # @return [String]
23
+ # A new String with values substituted for all variables
24
+ def sub_shell_variables( string )
25
+ return if string.nil?
26
+
27
+ retval = string.dup
28
+
29
+ # Current buffer filename
30
+ retval.gsub!( /\$f/, ( $1 || "" ) + File.expand_path( buffer_current.name || "" ) )
31
+ # Current buffer dir
32
+ retval.gsub!( /\$d/, ( $1 || "" ) + File.dirname( File.expand_path( buffer_current.name || '' ) ) )
33
+
34
+ # space-separated list of all buffer filenames
35
+ name_array = Array.new
36
+ @buffers.each do |b|
37
+ name_array.push b.name
38
+ end
39
+ retval.gsub!( /\$F/, ( $1 || "" ) + ( name_array.join(' ') || "" ) )
40
+
41
+ # Get user input, sub it in
42
+ if retval =~ /\$i/
43
+ user_input = get_user_input(
44
+ "Argument: ",
45
+ history: @rlh_shell,
46
+ initial_text: buffer_current.selected_string
47
+ )
48
+ retval.gsub!( /\$i/, user_input )
49
+ end
50
+
51
+ # Current clipboard text
52
+ if retval =~ /\$[ck]/
53
+ clip_filename = @diakonos_home + "/clip.txt"
54
+ File.open( clip_filename, "w" ) do |clipfile|
55
+ if @clipboard.clip
56
+ clipfile.puts( @clipboard.clip.join( "\n" ) )
57
+ end
58
+ end
59
+ retval.gsub!( /\$[ck]/, clip_filename )
60
+ end
61
+
62
+ # Currently selected text
63
+ if retval =~ /\$s/
64
+ text_filename = @diakonos_home + "/selected.txt"
65
+
66
+ File.open( text_filename, "w" ) do |textfile|
67
+ selected_text = buffer_current.selected_text
68
+ if selected_text
69
+ textfile.puts( selected_text.join( "\n" ) )
70
+ end
71
+ end
72
+ retval.gsub!( /\$s/, text_filename )
73
+ end
74
+
75
+ retval
76
+ end
77
+
78
+ # Executes a command in a shell, captures the results, and displays them
79
+ # (if any) in a new buffer. Substitutes Diakonos shell variables.
80
+ # Interaction with Diakonos is not possible while the shell is running.
81
+ # For asynchronous shelling, use #spawn. The shell function does not
82
+ # allow interaction with applications run in the shell. Use #execute
83
+ # for interactivity.
84
+ #
85
+ # @param [String] command_
86
+ # The shell command to execute
87
+ # @param [String] result_filename
88
+ # The name of the temporary file to write the shell results to
89
+ # @see #sub_shell_variables
90
+ # @see #execute
91
+ # @see #spawn
92
+ # @see #paste_shell_result
93
+ def shell( command_ = nil, result_filename = 'shell-result.txt' )
94
+ command = command_ || get_user_input( "Command: ", history: @rlh_shell )
95
+
96
+ return if command.nil?
97
+
98
+ command = sub_shell_variables( command )
99
+
100
+ completed = false
101
+ result_file = "#{@diakonos_home}/#{result_filename}"
102
+ File.open( result_file , "w" ) do |f|
103
+ Curses::close_screen
104
+
105
+ stdin, stdout, stderr = Open3.popen3( command )
106
+
107
+ t1 = Thread.new do
108
+ stdout.each_line do |line|
109
+ f.puts line
110
+ end
111
+ end
112
+ t2 = Thread.new do
113
+ stderr.each_line do |line|
114
+ f.puts line
115
+ end
116
+ end
117
+
118
+ catch :stop do
119
+ loop do
120
+ begin
121
+ Timeout::timeout( 5 ) do
122
+ t1.join
123
+ t2.join
124
+ Curses::init_screen
125
+ refresh_all
126
+ completed = true
127
+ throw :stop
128
+ end
129
+ rescue Timeout::Error => e
130
+ choice = get_choice(
131
+ "Keep waiting for shell results?",
132
+ [ CHOICE_YES, CHOICE_NO ],
133
+ CHOICE_YES
134
+ )
135
+ if choice != CHOICE_YES
136
+ t1.terminate
137
+ t2.terminate
138
+ throw :stop
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ end
145
+ if File.size?( result_file )
146
+ open_file result_file
147
+ set_iline "#{completed ? '' : '(interrupted) '}Results for: #{command}"
148
+ else
149
+ set_iline "Empty result for: #{command}"
150
+ end
151
+ end
152
+
153
+ # Executes a command in a shell, and displays the exit code.
154
+ # Results of the shell command are discarded.
155
+ # Substitutes Diakonos shell variables.
156
+ # Interaction with Diakonos is not possible while the shell is running.
157
+ # For asynchronous shelling, use #spawn. The #execute function allows
158
+ # interaction with shell programs that accept keyboard interaction.
159
+ #
160
+ # @param [String] command_
161
+ # The shell command to execute
162
+ # @see #sub_shell_variables
163
+ # @see #shell
164
+ # @see #spawn
165
+ # @see #paste_shell_result
166
+ def execute( command_ = nil )
167
+ command = command_ || get_user_input( "Command: ", history: @rlh_shell )
168
+
169
+ return if command.nil?
170
+
171
+ command = sub_shell_variables( command )
172
+
173
+ Curses::close_screen
174
+
175
+ success = system( command )
176
+ if ! success
177
+ result = "Could not execute: #{command}"
178
+ else
179
+ result = "Exit code: #{$?}"
180
+ end
181
+
182
+ Curses::init_screen
183
+ refresh_all
184
+
185
+ set_iline result
186
+ end
187
+
188
+ # Executes a command in a shell, captures the results, and pastes them
189
+ # in the current buffer at the current cursor location.
190
+ # Substitutes Diakonos shell variables.
191
+ # Interaction with Diakonos is not possible while the shell is running.
192
+ # For asynchronous shelling, use #spawn.
193
+ #
194
+ # @param [String] command_
195
+ # The shell command to execute
196
+ # @see #sub_shell_variables
197
+ # @see #execute
198
+ # @see #shell
199
+ # @see #spawn
200
+ def paste_shell_result( command_ = nil )
201
+ command = command_ || get_user_input( "Command: ", history: @rlh_shell )
202
+
203
+ return if command.nil?
204
+
205
+ command = sub_shell_variables( command )
206
+
207
+ Curses::close_screen
208
+
209
+ begin
210
+ buffer_current.paste( `#{command} 2<&1`.split( /\n/, -1 ) )
211
+ rescue Exception => e
212
+ debug_log e.message
213
+ debug_log e.backtrace.join( "\n\t" )
214
+ show_exception e
215
+ end
216
+
217
+ Curses::init_screen
218
+ refresh_all
219
+ end
220
+
221
+ # Executes a command in a shell, captures the results, and pastes them
222
+ # in the current buffer at the current cursor location.
223
+ # Substitutes Diakonos shell variables.
224
+ # The shell is executed in a separate thread, so interaction with Diakonos
225
+ # is possible during execution.
226
+ #
227
+ # @param [String] command_
228
+ # The shell command to execute
229
+ # @see #sub_shell_variables
230
+ # @see #execute
231
+ # @see #shell
232
+ # @see #paste_shell_result
233
+ def spawn( command_ = nil )
234
+ command = command_ || get_user_input( "Command: ", history: @rlh_shell )
235
+
236
+ return if command.nil?
237
+
238
+ command = sub_shell_variables( command )
239
+
240
+ Thread.new do
241
+ if system( command )
242
+ set_iline "Return code #{$?} from '#{command}'"
243
+ else
244
+ set_iline "Error code #{$?} executing '#{command}'"
245
+ end
246
+ end
247
+ end
248
+
249
+ end
250
+ end
@@ -0,0 +1,65 @@
1
+ module Diakonos
2
+ module Functions
3
+
4
+ def go_to_tag( tag_ = nil )
5
+ load_tags
6
+
7
+ # If necessary, prompt for tag name.
8
+
9
+ if tag_.nil?
10
+ if buffer_current.changing_selection
11
+ selected_text = buffer_current.copy_selection[ 0 ]
12
+ end
13
+ tag_name = get_user_input(
14
+ "Tag name: ",
15
+ history: @rlh_general,
16
+ initial_text: selected_text || "",
17
+ completion_array: @tags.keys
18
+ )
19
+ else
20
+ tag_name = tag_
21
+ end
22
+
23
+ tag_array = @tags[ tag_name ]
24
+ if tag_array && tag_array.length > 0
25
+ if i = tag_array.index( @last_tag )
26
+ tag = ( tag_array[ i + 1 ] || tag_array[ 0 ] )
27
+ else
28
+ tag = tag_array[ 0 ]
29
+ end
30
+ @last_tag = tag
31
+ @tag_stack.push [ buffer_current.name, buffer_current.last_row, buffer_current.last_col ]
32
+ if switch_to( @buffers.find { |b| b.name == tag.file } )
33
+ #buffer_current.go_to_line( 0 )
34
+ else
35
+ open_file tag.file
36
+ end
37
+ line_number = tag.command.to_i
38
+ if line_number > 0
39
+ buffer_current.go_to_line( line_number - 1 )
40
+ else
41
+ find tag.command case_sensitive: true
42
+ end
43
+ elsif tag_name
44
+ set_iline "No such tag: '#{tag_name}'"
45
+ end
46
+ end
47
+
48
+ def go_to_tag_under_cursor
49
+ go_to_tag buffer_current.word_under_cursor
50
+ end
51
+
52
+ def pop_tag
53
+ tag = @tag_stack.pop
54
+ if tag
55
+ if ! switch_to( @buffers.find { |b| b.name == tag[ 0 ] } )
56
+ open_file tag[ 0 ]
57
+ end
58
+ buffer_current.cursor_to( tag[ 1 ], tag[ 2 ], Buffer::DO_DISPLAY )
59
+ else
60
+ set_iline "Tag stack empty."
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,196 @@
1
+ require 'diakonos/line-mover'
2
+
3
+ module Diakonos
4
+ module Functions
5
+
6
+ def close_code
7
+ buffer_current.close_code
8
+ end
9
+
10
+ def collapse_whitespace
11
+ buffer_current.collapse_whitespace
12
+ end
13
+
14
+
15
+ def columnize( delimiter = nil, num_spaces_padding = 0 )
16
+ delimiter ||= get_user_input(
17
+ "Column delimiter (regexp): ",
18
+ history: @rlh_general,
19
+ initial_text: @settings[ "lang.#{buffer_current.original_language}.column_delimiters" ] || ''
20
+ )
21
+ if delimiter && num_spaces_padding
22
+ buffer_current.columnize Regexp.new( delimiter ), num_spaces_padding
23
+ end
24
+ end
25
+
26
+ def comment_out
27
+ buffer_current.comment_out
28
+ end
29
+
30
+ def complete_word( direction = :down )
31
+ b = buffer_current
32
+ if b.selecting?
33
+ old_word = b.word_before_cursor
34
+ b.delete_selection
35
+ end
36
+ partial = b.word_before_cursor
37
+ return if partial.nil?
38
+
39
+ all_words = @buffers.find_all { |b_|
40
+ b_.original_language == b.original_language
41
+ }.collect { |b_|
42
+ b_.words( /^#{Regexp.escape(partial)}./ )
43
+ }.flatten
44
+ if all_words.any?
45
+ words = all_words.uniq.sort
46
+ if old_word
47
+ i = (
48
+ ( direction == :up ? words.size - 1 : 1 ) +
49
+ words.find_index { |w|
50
+ w == old_word
51
+ }
52
+ ) % words.size
53
+ else
54
+ freq_word = words.sort_by { |word|
55
+ all_words.find_all { |w| w == word }.size
56
+ }[ -1 ]
57
+ i = words.find_index { |w| w == freq_word }
58
+ end
59
+ word = words[ i ]
60
+ b.insert_string word[ partial.length..-1 ]
61
+ r, c = b.last_row, b.last_col
62
+ b.cursor_to( b.last_row, b.last_col + word.length - partial.length )
63
+ b.set_selection( r, c, r, c + word.length - partial.length )
64
+ n = words.size
65
+ middle_word = words[ i ].center( Curses::cols / 4, ' ' )
66
+ shown_words = [
67
+ words[ ( n+i-2 ) % n ],
68
+ words[ ( n+i-1 ) % n ],
69
+ middle_word,
70
+ words[ ( n+i+1 ) % n ],
71
+ words[ ( n+i+2 ) % n ],
72
+ ].compact.uniq.reject { |w| w == middle_word.strip }.join( ' ' )
73
+ mi = shown_words.index( middle_word )
74
+ padding = " " * ( Curses::cols / 2 - mi - ( middle_word.length / 2 ) )
75
+ set_iline padding + shown_words
76
+ end
77
+ end
78
+
79
+ def join_lines_upward
80
+ buffer_current.join_lines_upward( buffer_current.current_row, Buffer::STRIP_LINE )
81
+ end
82
+
83
+ def join_lines
84
+ buffer_current.join_lines( buffer_current.current_row, Buffer::STRIP_LINE )
85
+ end
86
+
87
+ def move_lines(direction:)
88
+ mover = LineMover.new(buffer: buffer_current)
89
+ mover.move_selected_lines(direction: direction)
90
+ end
91
+
92
+ def operate_on_string(
93
+ ruby_code = get_user_input(
94
+ 'Ruby code: ',
95
+ history: @rlh_general,
96
+ initial_text: 'str.'
97
+ )
98
+ )
99
+ if ruby_code
100
+ str = buffer_current.selected_string
101
+ if str && ! str.empty?
102
+ buffer_current.paste eval( ruby_code )
103
+ end
104
+ end
105
+ end
106
+
107
+ def operate_on_lines(
108
+ ruby_code = get_user_input(
109
+ 'Ruby code: ',
110
+ history: @rlh_general,
111
+ initial_text: 'lines.collect { |l| l }'
112
+ )
113
+ )
114
+ if ruby_code
115
+ lines = buffer_current.selected_text
116
+ if lines && ! lines.empty?
117
+ if lines[ -1 ].empty?
118
+ lines.pop
119
+ popped = true
120
+ end
121
+ new_lines = eval( ruby_code )
122
+ if popped
123
+ new_lines << ''
124
+ end
125
+ buffer_current.paste new_lines
126
+ end
127
+ end
128
+ end
129
+
130
+ def operate_on_each_line(
131
+ ruby_code = get_user_input(
132
+ 'Ruby code: ',
133
+ history: @rlh_general,
134
+ initial_text: 'line.'
135
+ )
136
+ )
137
+ if ruby_code
138
+ lines = buffer_current.selected_text
139
+ if lines && ! lines.empty?
140
+ if lines[ -1 ].empty?
141
+ lines.pop
142
+ popped = true
143
+ end
144
+ new_lines = eval( "lines.collect { |line| #{ruby_code} }" )
145
+ if popped
146
+ new_lines << ''
147
+ end
148
+ buffer_current.paste new_lines
149
+ end
150
+ end
151
+ end
152
+
153
+ def surround_line( envelope = nil )
154
+ buffer_current.set_selection_current_line
155
+ surround_selection envelope
156
+ end
157
+
158
+ def surround_paragraph( envelope = nil )
159
+ ( first, _ ), ( last, length ) = buffer_current.paragraph_under_cursor_pos
160
+ buffer_current.set_selection( first, 0, last, length+1 )
161
+ surround_selection envelope
162
+ end
163
+
164
+ def surround_selection( parenthesis = nil )
165
+ if ! buffer_current.selecting?
166
+ set_iline "Nothing selected."
167
+ return
168
+ end
169
+
170
+ parenthesis ||= get_user_input( "Surround with: " )
171
+ if parenthesis
172
+ text = buffer_current.surround( buffer_current.selected_text, parenthesis )
173
+ if text
174
+ buffer_current.paste text
175
+ end
176
+ end
177
+ end
178
+
179
+ def surround_word( envelope = nil )
180
+ ( start_row, start_col ), ( end_row, end_col ) = buffer_current.word_under_cursor_pos
181
+ if start_row && start_col && end_row && end_col
182
+ buffer_current.set_selection( start_row, start_col, end_row, end_col )
183
+ surround_selection envelope
184
+ end
185
+ end
186
+
187
+ def uncomment
188
+ buffer_current.uncomment
189
+ end
190
+
191
+ def wrap_paragraph
192
+ buffer_current.wrap_paragraph
193
+ end
194
+
195
+ end
196
+ end