glimmer-cs-gladiator 0.1.2 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +24 -14
- data/bin/gladiator +8 -1
- data/lib/models/glimmer/gladiator/dir.rb +62 -22
- data/lib/models/glimmer/gladiator/file.rb +144 -50
- data/lib/views/glimmer/gladiator.rb +323 -122
- data/lib/views/glimmer/gladiator/text_editor.rb +119 -0
- metadata +27 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 18bd05231ab3815f4432ee79395284dbe6e5cd34244b1642b7bff4f7a3921c29
|
4
|
+
data.tar.gz: f2b2a7d6faf0154d878a3c25944a9b3a59c256a45feaf5b2b975379b357f598b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e82f4d0a5306bb03d767fa3dd1f7b23b970ba5fc5fbc87010c3388d2fcaec010134d3780d0fcc7d29b0c85113bb9f5c8daf8ef6284d4fc6b561064ccdd6ba88d
|
7
|
+
data.tar.gz: fb7a4b16181113d96478f0458a6abebe7c85c6be6d1b3568b39f412d56e278641a58d61e6aea1c977246aa21433f6084da7787db38ae3ee322d1ff5b1f1109f9
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Gladiator (Glimmer Editor) 0.1.
|
1
|
+
# Gladiator (Glimmer Editor) 0.1.7 - Glimmer Custom Shell
|
2
2
|
[](http://badge.fury.io/rb/glimmer-cs-gladiator)
|
3
3
|
|
4
4
|

|
@@ -9,19 +9,29 @@ Gladiator is also a personal tool for shaping an editor exactly the way I like.
|
|
9
9
|
I leave building truly professional text editors to software tooling experts who would hopefully use Glimmer one day.
|
10
10
|
|
11
11
|
Gladiator currently supports the following text editing features:
|
12
|
-
- File explorer navigation to open file
|
13
|
-
- File lookup by name
|
14
|
-
-
|
12
|
+
- File explorer navigation to open file, rename, delete, add new file, add new directory, or refresh tree (CMD+T)
|
13
|
+
- File lookup by name ignoring slashes, underscores, and dots to ease lookup (CMD+R)
|
14
|
+
- Watch open file for external changes to automatically refresh in editor
|
15
|
+
- Watch project subdirectories for changes to automatically refresh in file explorer/file lookup
|
16
|
+
- Find & Replace (CMD+F)
|
15
17
|
- Show Line Numbers
|
16
|
-
- Jump to Line
|
17
|
-
-
|
18
|
-
-
|
19
|
-
-
|
20
|
-
-
|
21
|
-
-
|
22
|
-
-
|
23
|
-
- Move
|
24
|
-
-
|
18
|
+
- Jump to Line (CMD+L)
|
19
|
+
- Multiple tab support (CMD+SHIFT+[ & CMD+SHIFT+] for tab navigation. CMD+1-9 to jump to a specific tab)
|
20
|
+
- Remember opened tabs, caret position, top line, window size, and window location
|
21
|
+
- Autosave on focus out/quit/open new file
|
22
|
+
- Duplicate Line(s)/selection (CMD+D)
|
23
|
+
- Kill Line(s)/selection (CMD+K)
|
24
|
+
- Move line/selection up (CMD+UP)
|
25
|
+
- Move line/selection down (CMD+DOWN)
|
26
|
+
- Comment/Uncomment line/selection (CMD+/)
|
27
|
+
- Indent/Unindent line/selection (CMD+] & CMD+[)
|
28
|
+
- Insert/Prefix New Line (CMD+ENTER & CMD+SHIFT+ENTER)
|
29
|
+
|
30
|
+
## Platforms
|
31
|
+
|
32
|
+
- Mac: Gladiator works best on the Mac.
|
33
|
+
- Linux: Gladiator works with handicaps on Linux (performing text editing operations causes scroll jitter)
|
34
|
+
- Windows: Not tested on Windows yet, but should theoretically work there too.
|
25
35
|
|
26
36
|
## Pre-requisites
|
27
37
|
|
@@ -50,7 +60,7 @@ To reuse Gladiator as a Glimmer Custom Shell inside another Glimmer application,
|
|
50
60
|
following to the application's `Gemfile`:
|
51
61
|
|
52
62
|
```
|
53
|
-
gem 'glimmer-cs-gladiator', '0.1.
|
63
|
+
gem 'glimmer-cs-gladiator', '0.1.7'
|
54
64
|
```
|
55
65
|
|
56
66
|
Run:
|
data/bin/gladiator
CHANGED
@@ -3,4 +3,11 @@
|
|
3
3
|
require 'glimmer/launcher'
|
4
4
|
|
5
5
|
gladiator_runner = File.expand_path('../gladiator_runner.rb', __FILE__)
|
6
|
-
Glimmer::Launcher.new([gladiator_runner, '-J-Xrs'] + ARGV)
|
6
|
+
launcher = Glimmer::Launcher.new([gladiator_runner, '-J-Xrs'] + ARGV)
|
7
|
+
launcher.application_paths.to_a.each do |file|
|
8
|
+
if file != gladiator_runner
|
9
|
+
launcher.application_paths.delete(file)
|
10
|
+
ENV['LOCAL_DIR'] ||= file
|
11
|
+
end
|
12
|
+
end
|
13
|
+
launcher.launch
|
@@ -15,41 +15,66 @@ module Glimmer
|
|
15
15
|
@thread = Thread.new(@filewatcher) do |fw|
|
16
16
|
fw.watch do |filename, event|
|
17
17
|
if @last_update.nil? || (Time.now.to_f - @last_update) > REFRESH_DELAY
|
18
|
-
dir.refresh if filename != dir.selected_child_path
|
18
|
+
dir.refresh if !filename.include?('new_file') && !dir.selected_child_path_history.include?(filename) && filename != dir.selected_child_path
|
19
19
|
end
|
20
20
|
@last_update = Time.now.to_f
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
|
-
end
|
24
|
+
end
|
25
25
|
end
|
26
26
|
|
27
|
-
attr_accessor :selected_child, :filter, :children, :filtered_path_options
|
28
|
-
attr_reader :
|
27
|
+
attr_accessor :selected_child, :filter, :children, :filtered_path_options, :filtered_path, :path, :display_path
|
28
|
+
attr_reader :name, :parent
|
29
|
+
attr_writer :all_children, :children
|
29
30
|
|
30
31
|
def initialize(path)
|
31
|
-
@
|
32
|
+
@display_path = path
|
33
|
+
@path = ::File.expand_path(@display_path)
|
34
|
+
@name = ::File.basename(::File.expand_path(path))
|
32
35
|
self.filtered_path_options = []
|
33
36
|
end
|
37
|
+
|
38
|
+
def name=(the_name)
|
39
|
+
self.display_path = display_path.sub(/#{Regexp.escape(@name)}$/, the_name)
|
40
|
+
@name = the_name
|
41
|
+
new_path = ::File.expand_path(display_path)
|
42
|
+
FileUtils.mv(path, new_path)
|
43
|
+
self.path = display_path
|
44
|
+
end
|
34
45
|
|
35
46
|
def children
|
36
47
|
@children ||= retrieve_children
|
37
48
|
end
|
38
|
-
|
49
|
+
|
39
50
|
def retrieve_children
|
40
|
-
::Dir.glob(::File.join(@
|
51
|
+
::Dir.glob(::File.join(@display_path, '*')).map {|p| ::File.file?(p) ? Gladiator::File.new(p) : Gladiator::Dir.new(p)}.sort_by {|c| c.path.to_s.downcase }.sort_by {|c| c.class.name }
|
41
52
|
end
|
42
53
|
|
43
|
-
def
|
54
|
+
def selected_child_path_history
|
55
|
+
@selected_child_path_history ||= []
|
56
|
+
end
|
57
|
+
|
58
|
+
def pause_refresh
|
59
|
+
@refresh_paused = true
|
60
|
+
end
|
61
|
+
|
62
|
+
def resume_refresh
|
63
|
+
@refresh_paused = false
|
64
|
+
end
|
65
|
+
|
66
|
+
def refresh(async: true, force: false)
|
67
|
+
return if @refresh_paused && !force
|
44
68
|
new_all_children = retrieve_all_children
|
45
|
-
new_children = retrieve_children
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
69
|
+
new_children = retrieve_children
|
70
|
+
refresh_operation = lambda do
|
71
|
+
self.all_children = new_all_children
|
72
|
+
self.children = new_children
|
73
|
+
end
|
74
|
+
if async
|
75
|
+
async_exec(&refresh_operation)
|
76
|
+
else
|
77
|
+
sync_exec(&refresh_operation)
|
53
78
|
end
|
54
79
|
end
|
55
80
|
|
@@ -66,7 +91,7 @@ module Glimmer
|
|
66
91
|
return if filter.nil?
|
67
92
|
all_children_files.select do |child|
|
68
93
|
child.path.downcase.include?(filter.downcase) ||
|
69
|
-
child.path.downcase.gsub(/[_
|
94
|
+
child.path.downcase.gsub(/[_\/\.]/, '').include?(filter.downcase)
|
70
95
|
end.sort_by {|c| c.path.to_s.downcase}
|
71
96
|
end
|
72
97
|
|
@@ -75,7 +100,7 @@ module Glimmer
|
|
75
100
|
end
|
76
101
|
|
77
102
|
def retrieve_all_children
|
78
|
-
::Dir.glob(::File.join(@
|
103
|
+
::Dir.glob(::File.join(@display_path, '**', '*')).map {|p| ::File.file?(p) ? Gladiator::File.new(p) : Gladiator::Dir.new(p)}
|
79
104
|
end
|
80
105
|
|
81
106
|
def all_children_files
|
@@ -83,31 +108,46 @@ module Glimmer
|
|
83
108
|
end
|
84
109
|
|
85
110
|
def selected_child_path=(selected_path)
|
86
|
-
if selected_path
|
111
|
+
return if selected_path.nil? ||
|
112
|
+
::Dir.exist?(selected_path) ||
|
113
|
+
(selected_child && ::File.expand_path(selected_child.path) == ::File.expand_path(selected_path))
|
114
|
+
if ::File.file?(selected_path)
|
87
115
|
@selected_child&.write_dirty_content
|
88
116
|
new_child = Gladiator::File.new(selected_path)
|
89
117
|
begin
|
90
118
|
unless new_child.dirty_content.nil?
|
91
119
|
self.selected_child&.stop_filewatcher
|
120
|
+
selected_child_path_history << new_child.path if new_child && !selected_child_path_history.include?(new_child.path)
|
92
121
|
self.selected_child = new_child
|
93
122
|
self.selected_child.start_filewatcher
|
94
123
|
end
|
95
124
|
rescue
|
96
125
|
# no op
|
97
126
|
end
|
127
|
+
else
|
128
|
+
refresh
|
98
129
|
end
|
99
130
|
end
|
100
131
|
|
101
132
|
def selected_child_path
|
102
133
|
@selected_child&.path
|
103
134
|
end
|
104
|
-
|
105
|
-
|
106
|
-
|
135
|
+
|
136
|
+
def delete!
|
137
|
+
FileUtils.rm_rf(path)
|
138
|
+
end
|
107
139
|
|
108
140
|
def to_s
|
109
141
|
path
|
110
142
|
end
|
143
|
+
|
144
|
+
def eql?(other)
|
145
|
+
self.path.eql?(other&.path)
|
146
|
+
end
|
147
|
+
|
148
|
+
def hash
|
149
|
+
self.path.hash
|
150
|
+
end
|
111
151
|
end
|
112
152
|
end
|
113
153
|
end
|
@@ -5,13 +5,17 @@ module Glimmer
|
|
5
5
|
class File
|
6
6
|
include Glimmer
|
7
7
|
|
8
|
-
attr_accessor :
|
9
|
-
attr_reader :
|
8
|
+
attr_accessor :line_numbers_content, :selection, :selection_count, :line_number, :find_text, :replace_text, :top_index, :path, :display_path
|
9
|
+
attr_reader :name, :dirty_content
|
10
10
|
|
11
11
|
def initialize(path)
|
12
12
|
raise "Not a file path: #{path}" unless ::File.file?(path)
|
13
13
|
@display_path = path
|
14
|
+
@name = ::File.basename(path)
|
14
15
|
@path = ::File.expand_path(path)
|
16
|
+
@top_index = 0
|
17
|
+
@selection_count = 0
|
18
|
+
@selection = Point.new(0, 0 + @selection_count)
|
15
19
|
read_dirty_content = ::File.read(path)
|
16
20
|
begin
|
17
21
|
# test read dirty content
|
@@ -20,21 +24,47 @@ module Glimmer
|
|
20
24
|
lines_text_size = lines.size.to_s.size
|
21
25
|
self.line_numbers_content = lines.size.times.map {|n| (' ' * (lines_text_size - (n+1).to_s.size)) + (n+1).to_s }.join("\n")
|
22
26
|
end
|
27
|
+
@line_number = 1
|
23
28
|
self.dirty_content = read_dirty_content
|
24
|
-
observe(self, :
|
29
|
+
observe(self, :selection) do
|
25
30
|
self.line_number = line_index_for_caret_position(caret_position) + 1
|
26
31
|
end
|
27
32
|
observe(self, :line_number) do
|
28
33
|
if line_number
|
29
34
|
line_index = line_number - 1
|
30
35
|
new_caret_position = caret_position_for_line_index(line_index)
|
31
|
-
self.caret_position = new_caret_position unless line_index_for_caret_position(new_caret_position) == line_index_for_caret_position(caret_position)
|
36
|
+
self.caret_position = new_caret_position unless self.caret_position && line_index_for_caret_position(new_caret_position) == line_index_for_caret_position(caret_position)
|
32
37
|
end
|
33
38
|
end
|
34
39
|
rescue
|
35
40
|
# no op in case of a binary file
|
36
41
|
end
|
37
42
|
end
|
43
|
+
|
44
|
+
def caret_position=(value)
|
45
|
+
self.selection = Point.new(value, value + selection_count.to_i)
|
46
|
+
if OS.linux?
|
47
|
+
async_exec do
|
48
|
+
self.top_index = line_index_for_caret_position(value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def caret_position
|
54
|
+
selection.x
|
55
|
+
end
|
56
|
+
|
57
|
+
def name=(the_name)
|
58
|
+
self.display_path = display_path.sub(/#{Regexp.escape(@name)}$/, the_name)
|
59
|
+
@name = the_name
|
60
|
+
new_path = ::File.expand_path(display_path)
|
61
|
+
FileUtils.mv(path, new_path)
|
62
|
+
self.path = new_path
|
63
|
+
end
|
64
|
+
|
65
|
+
def dirty_content=(the_content)
|
66
|
+
@dirty_content = the_content if ::File.exist?(path)
|
67
|
+
end
|
38
68
|
|
39
69
|
def start_filewatcher
|
40
70
|
@filewatcher = Filewatcher.new(@path)
|
@@ -57,23 +87,55 @@ module Glimmer
|
|
57
87
|
def stop_filewatcher
|
58
88
|
@filewatcher&.stop
|
59
89
|
end
|
60
|
-
|
61
|
-
def
|
90
|
+
|
91
|
+
def format_dirty_content_for_writing!
|
62
92
|
new_dirty_content = "#{dirty_content.gsub("\r\n", "\n").gsub("\r", "\n").sub(/\n+\z/, '')}\n"
|
63
93
|
self.dirty_content = new_dirty_content if new_dirty_content != self.dirty_content
|
64
|
-
|
94
|
+
end
|
95
|
+
|
96
|
+
def write_dirty_content
|
97
|
+
return unless ::File.exist?(path)
|
98
|
+
format_dirty_content_for_writing!
|
99
|
+
::File.write(path, dirty_content) if ::File.exists?(path)
|
65
100
|
rescue => e
|
66
101
|
puts "Error in writing dirty content for #{path}"
|
67
102
|
puts e.full_message
|
68
103
|
end
|
69
104
|
|
70
105
|
def write_raw_dirty_content
|
71
|
-
|
106
|
+
return unless ::File.exist?(path)
|
107
|
+
::File.write(path, dirty_content) if ::File.exists?(path)
|
72
108
|
rescue => e
|
73
109
|
puts "Error in writing raw dirty content for #{path}"
|
74
110
|
puts e.full_message
|
75
111
|
end
|
76
|
-
|
112
|
+
|
113
|
+
def current_line_indentation
|
114
|
+
current_line.to_s.match(/^(\s+)/).to_a[1].to_s
|
115
|
+
end
|
116
|
+
|
117
|
+
def current_line
|
118
|
+
lines[line_number - 1]
|
119
|
+
end
|
120
|
+
|
121
|
+
def delete!
|
122
|
+
FileUtils.rm(path)
|
123
|
+
end
|
124
|
+
|
125
|
+
def prefix_new_line!
|
126
|
+
the_lines = lines
|
127
|
+
the_lines[line_number-1...line_number-1] = [current_line_indentation]
|
128
|
+
self.dirty_content = the_lines.join("\n")
|
129
|
+
self.caret_position = caret_position_for_line_index(line_number-1) + current_line_indentation.size
|
130
|
+
end
|
131
|
+
|
132
|
+
def insert_new_line!
|
133
|
+
the_lines = lines
|
134
|
+
the_lines[line_number...line_number] = [current_line_indentation]
|
135
|
+
self.dirty_content = the_lines.join("\n")
|
136
|
+
self.caret_position = caret_position_for_line_index(line_number) + current_line_indentation.size
|
137
|
+
end
|
138
|
+
|
77
139
|
def comment_line!
|
78
140
|
old_lines = lines
|
79
141
|
return if old_lines.size < 1
|
@@ -99,7 +161,7 @@ module Glimmer
|
|
99
161
|
end
|
100
162
|
end
|
101
163
|
self.dirty_content = new_lines.join("\n")
|
102
|
-
if old_selection_count > 0
|
164
|
+
if old_selection_count.to_i > 0
|
103
165
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
104
166
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
105
167
|
else
|
@@ -125,7 +187,7 @@ module Glimmer
|
|
125
187
|
end
|
126
188
|
old_caret_position = self.caret_position
|
127
189
|
self.dirty_content = new_lines.join("\n")
|
128
|
-
if old_selection_count > 0
|
190
|
+
if old_selection_count.to_i > 0
|
129
191
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
130
192
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
131
193
|
else
|
@@ -145,7 +207,7 @@ module Glimmer
|
|
145
207
|
delta = 0
|
146
208
|
line_indices_for_selection(caret_position, selection_count).each do |the_line_index|
|
147
209
|
the_line = old_lines[the_line_index]
|
148
|
-
if the_line.start_with?(' ')
|
210
|
+
if the_line.to_s.start_with?(' ')
|
149
211
|
new_lines[the_line_index] = the_line.sub(/ /, '')
|
150
212
|
delta = -2
|
151
213
|
elsif the_line.start_with?(' ')
|
@@ -154,7 +216,7 @@ module Glimmer
|
|
154
216
|
end
|
155
217
|
end
|
156
218
|
self.dirty_content = new_lines.join("\n")
|
157
|
-
if old_selection_count > 0
|
219
|
+
if old_selection_count.to_i > 0
|
158
220
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
159
221
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
160
222
|
else
|
@@ -166,12 +228,15 @@ module Glimmer
|
|
166
228
|
|
167
229
|
def kill_line!
|
168
230
|
new_lines = lines
|
169
|
-
return if new_lines.size <
|
231
|
+
return if new_lines.size < 1
|
170
232
|
line_indices = line_indices_for_selection(caret_position, selection_count)
|
171
233
|
new_lines = new_lines[0...line_indices.first] + new_lines[(line_indices.last+1)...new_lines.size]
|
172
234
|
old_caret_position = self.caret_position
|
173
|
-
self.
|
174
|
-
|
235
|
+
old_line_index = self.line_number - 1
|
236
|
+
line_position = line_position_for_caret_position(old_caret_position)
|
237
|
+
self.dirty_content = "#{new_lines.join("\n")}\n"
|
238
|
+
self.caret_position = caret_position_for_line_index(old_line_index) + [line_position, lines[old_line_index].to_s.size].min
|
239
|
+
self.selection_count = 0
|
175
240
|
end
|
176
241
|
|
177
242
|
def duplicate_line!
|
@@ -190,7 +255,7 @@ module Glimmer
|
|
190
255
|
new_lines.insert(the_line_indices.first + i, the_line)
|
191
256
|
end
|
192
257
|
self.dirty_content = new_lines.join("\n")
|
193
|
-
if old_selection_count > 0
|
258
|
+
if old_selection_count.to_i > 0
|
194
259
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
195
260
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
196
261
|
else
|
@@ -202,12 +267,21 @@ module Glimmer
|
|
202
267
|
return if find_text.to_s.empty?
|
203
268
|
all_lines = lines
|
204
269
|
the_line_index = line_index_for_caret_position(caret_position)
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
270
|
+
line_position = line_position_for_caret_position(caret_position)
|
271
|
+
found =
|
272
|
+
2.times do |i|
|
273
|
+
rotation = the_line_index
|
274
|
+
all_lines.rotate(rotation).each_with_index do |the_line, the_index|
|
275
|
+
the_index = (the_index + rotation)%all_lines.size
|
276
|
+
start_position = 0
|
277
|
+
start_position = line_position + find_text.to_s.size if i == 0 && the_index == the_line_index && found_text?(caret_position)
|
278
|
+
text_to_find_in = the_line.downcase[start_position..-1]
|
279
|
+
occurrence_index = text_to_find_in&.index(find_text.to_s.downcase)
|
280
|
+
if occurrence_index
|
281
|
+
self.caret_position = caret_position_for_line_index(the_index) + start_position + occurrence_index
|
282
|
+
self.selection_count = find_text.to_s.size
|
283
|
+
return
|
284
|
+
end
|
211
285
|
end
|
212
286
|
end
|
213
287
|
end
|
@@ -216,21 +290,34 @@ module Glimmer
|
|
216
290
|
return if find_text.to_s.empty?
|
217
291
|
all_lines = lines
|
218
292
|
the_line_index = line_index_for_caret_position(caret_position)
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
293
|
+
line_position = line_position_for_caret_position(caret_position)
|
294
|
+
2.times do |i|
|
295
|
+
rotation = - the_line_index - 1 + all_lines.size
|
296
|
+
all_lines.reverse.rotate(rotation).each_with_index do |the_line, the_index|
|
297
|
+
the_index = all_lines.size - 1 - (the_index + rotation)%all_lines.size
|
298
|
+
if the_index == the_line_index
|
299
|
+
start_position = i > 0 ? 0 : (the_line.size - line_position)
|
300
|
+
else
|
301
|
+
start_position = 0
|
302
|
+
end
|
303
|
+
text_to_find_in = the_line.downcase.reverse[start_position...the_line.size].to_s
|
304
|
+
occurrence_index = text_to_find_in.index(find_text.to_s.downcase.reverse)
|
305
|
+
if occurrence_index
|
306
|
+
self.caret_position = caret_position_for_line_index(the_index) + (the_line.size - (start_position + occurrence_index + find_text.to_s.size))
|
307
|
+
self.selection_count = find_text.to_s.size
|
308
|
+
return
|
309
|
+
end
|
227
310
|
end
|
228
311
|
end
|
229
312
|
end
|
230
313
|
|
231
314
|
def ensure_find_next
|
232
315
|
return if find_text.to_s.empty? || dirty_content.to_s.strip.size < 1
|
233
|
-
find_next unless
|
316
|
+
find_next unless found_text?(self.caret_position)
|
317
|
+
end
|
318
|
+
|
319
|
+
def found_text?(caret_position)
|
320
|
+
dirty_content[caret_position.to_i, find_text.to_s.size].to_s.downcase == find_text.to_s.downcase
|
234
321
|
end
|
235
322
|
|
236
323
|
def replace_next!
|
@@ -243,10 +330,12 @@ module Glimmer
|
|
243
330
|
end
|
244
331
|
|
245
332
|
def page_up
|
333
|
+
self.selection_count = 0
|
246
334
|
self.line_number = [(self.line_number - 15), 1].max
|
247
335
|
end
|
248
336
|
|
249
337
|
def page_down
|
338
|
+
self.selection_count = 0
|
250
339
|
self.line_number = [(self.line_number + 15), lines.size].min
|
251
340
|
end
|
252
341
|
|
@@ -263,23 +352,18 @@ module Glimmer
|
|
263
352
|
return if old_lines.size < 2
|
264
353
|
old_selection_count = self.selection_count
|
265
354
|
old_caret_position = self.caret_position
|
266
|
-
|
267
|
-
|
355
|
+
old_caret_position_line_caret_position = caret_position_for_caret_position_start_of_line(old_caret_position)
|
356
|
+
old_caret_position_line_position = old_caret_position - old_caret_position_line_caret_position
|
268
357
|
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
269
358
|
new_lines = lines
|
270
359
|
the_line_indices = line_indices_for_selection(caret_position, selection_count)
|
271
360
|
the_lines = lines_for_selection(caret_position, selection_count)
|
272
361
|
new_line_index = [the_line_indices.first - 1, 0].max
|
273
|
-
delta = -1 * (new_lines[new_line_index].size + 1)
|
274
362
|
new_lines[the_line_indices.first..the_line_indices.last] = []
|
275
363
|
new_lines[new_line_index...new_line_index] = the_lines
|
276
364
|
self.dirty_content = new_lines.join("\n")
|
277
|
-
|
278
|
-
|
279
|
-
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position + delta)
|
280
|
-
else
|
281
|
-
self.caret_position = old_caret_position + delta
|
282
|
-
end
|
365
|
+
self.caret_position = caret_position_for_line_index(new_line_index) + [old_caret_position_line_position, new_lines[new_line_index].size].min
|
366
|
+
self.selection_count = old_selection_count.to_i if old_selection_count.to_i > 0
|
283
367
|
end
|
284
368
|
|
285
369
|
def move_down!
|
@@ -287,23 +371,18 @@ module Glimmer
|
|
287
371
|
return if old_lines.size < 2
|
288
372
|
old_selection_count = self.selection_count
|
289
373
|
old_caret_position = self.caret_position
|
290
|
-
|
291
|
-
|
374
|
+
old_caret_position_line_caret_position = caret_position_for_caret_position_start_of_line(old_caret_position)
|
375
|
+
old_caret_position_line_position = old_caret_position - old_caret_position_line_caret_position
|
292
376
|
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
293
377
|
new_lines = lines
|
294
378
|
the_line_indices = line_indices_for_selection(caret_position, selection_count)
|
295
379
|
the_lines = lines_for_selection(caret_position, selection_count)
|
296
380
|
new_line_index = [the_line_indices.first + 1, new_lines.size - 1].min
|
297
|
-
delta = new_lines[new_line_index].size + 1
|
298
381
|
new_lines[the_line_indices.first..the_line_indices.last] = []
|
299
382
|
new_lines[new_line_index...new_line_index] = the_lines
|
300
383
|
self.dirty_content = new_lines.join("\n")
|
301
|
-
|
302
|
-
|
303
|
-
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position + delta)
|
304
|
-
else
|
305
|
-
self.caret_position = old_caret_position + delta
|
306
|
-
end
|
384
|
+
self.caret_position = caret_position_for_line_index(new_line_index) + [old_caret_position_line_position, new_lines[new_line_index].size].min
|
385
|
+
self.selection_count = old_selection_count.to_i if old_selection_count.to_i > 0
|
307
386
|
end
|
308
387
|
|
309
388
|
def lines
|
@@ -327,6 +406,13 @@ module Glimmer
|
|
327
406
|
def caret_position_for_caret_position_start_of_line(caret_position)
|
328
407
|
caret_position_for_line_index(line_index_for_caret_position(caret_position))
|
329
408
|
end
|
409
|
+
|
410
|
+
# position within line containing "caret position" (e.g. for caret position 5 in 1st line, they match as 5, for 15 in line 2 with line 1 having 10 characters, line position is 4)
|
411
|
+
# TODO consider renaming to line_character_position_for_caret_position
|
412
|
+
def line_position_for_caret_position(caret_position)
|
413
|
+
caret_position = caret_position.to_i
|
414
|
+
caret_position - caret_position_for_caret_position_start_of_line(caret_position)
|
415
|
+
end
|
330
416
|
|
331
417
|
def line_caret_positions_for_selection(caret_position, selection_count)
|
332
418
|
line_indices = line_indices_for_selection(caret_position, selection_count)
|
@@ -361,6 +447,14 @@ module Glimmer
|
|
361
447
|
def to_s
|
362
448
|
path
|
363
449
|
end
|
450
|
+
|
451
|
+
def eql?(other)
|
452
|
+
self.path.eql?(other&.path)
|
453
|
+
end
|
454
|
+
|
455
|
+
def hash
|
456
|
+
self.path.hash
|
457
|
+
end
|
364
458
|
end
|
365
459
|
end
|
366
460
|
end
|