glimmer-cs-gladiator 0.1.1 → 0.1.6
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 -13
- data/bin/gladiator +8 -1
- data/lib/models/glimmer/gladiator/dir.rb +62 -22
- data/lib/models/glimmer/gladiator/file.rb +149 -52
- data/lib/views/glimmer/gladiator.rb +327 -123
- data/lib/views/glimmer/gladiator/text_editor.rb +119 -0
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8d758e5b444ef3d48c0214ffb763e3dab3f9ca9748961e879b9ebdb626e9c2ea
|
4
|
+
data.tar.gz: cb575fbe30017319190278483334256aeb04d277798a5e3351f944c3d3a61481
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4223591b0608f621432a7ee1a1f710ad4a1684aaafb6d1d9152f064b8d707216ba3dc5fece5836764db058a9a88d209d161ee8abc5062d4fb9a4a821cb986c61
|
7
|
+
data.tar.gz: 3296674924ae085c139919e9e22a32d1c5a322b163b7fc6954e89bc02af4cb2a7c80e9a49359d9d136f4113206c48ebfcedbbe917e3f97e35529575abed1832a
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Gladiator (Glimmer Editor) 0.1.
|
1
|
+
# Gladiator (Glimmer Editor) 0.1.6 - Glimmer Custom Shell
|
2
2
|
[](http://badge.fury.io/rb/glimmer-cs-gladiator)
|
3
3
|
|
4
4
|

|
@@ -9,18 +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
|
-
- Duplicate Line(s)
|
21
|
-
- Kill Line(s)
|
22
|
-
- Move up
|
23
|
-
- Move down
|
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.
|
24
35
|
|
25
36
|
## Pre-requisites
|
26
37
|
|
@@ -49,7 +60,7 @@ To reuse Gladiator as a Glimmer Custom Shell inside another Glimmer application,
|
|
49
60
|
following to the application's `Gemfile`:
|
50
61
|
|
51
62
|
```
|
52
|
-
gem 'glimmer-cs-gladiator', '0.1.
|
63
|
+
gem 'glimmer-cs-gladiator', '0.1.6'
|
53
64
|
```
|
54
65
|
|
55
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,20 +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
|
-
|
30
|
-
|
34
|
+
line_index = line_number - 1
|
35
|
+
new_caret_position = caret_position_for_line_index(line_index)
|
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)
|
31
37
|
end
|
32
38
|
end
|
33
39
|
rescue
|
34
40
|
# no op in case of a binary file
|
35
41
|
end
|
36
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
|
37
68
|
|
38
69
|
def start_filewatcher
|
39
70
|
@filewatcher = Filewatcher.new(@path)
|
@@ -56,23 +87,55 @@ module Glimmer
|
|
56
87
|
def stop_filewatcher
|
57
88
|
@filewatcher&.stop
|
58
89
|
end
|
59
|
-
|
60
|
-
def
|
90
|
+
|
91
|
+
def format_dirty_content_for_writing!
|
61
92
|
new_dirty_content = "#{dirty_content.gsub("\r\n", "\n").gsub("\r", "\n").sub(/\n+\z/, '')}\n"
|
62
93
|
self.dirty_content = new_dirty_content if new_dirty_content != self.dirty_content
|
63
|
-
|
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)
|
64
100
|
rescue => e
|
65
101
|
puts "Error in writing dirty content for #{path}"
|
66
102
|
puts e.full_message
|
67
103
|
end
|
68
104
|
|
69
105
|
def write_raw_dirty_content
|
70
|
-
|
106
|
+
return unless ::File.exist?(path)
|
107
|
+
::File.write(path, dirty_content) if ::File.exists?(path)
|
71
108
|
rescue => e
|
72
109
|
puts "Error in writing raw dirty content for #{path}"
|
73
110
|
puts e.full_message
|
74
111
|
end
|
75
|
-
|
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
|
+
|
76
139
|
def comment_line!
|
77
140
|
old_lines = lines
|
78
141
|
return if old_lines.size < 1
|
@@ -98,7 +161,7 @@ module Glimmer
|
|
98
161
|
end
|
99
162
|
end
|
100
163
|
self.dirty_content = new_lines.join("\n")
|
101
|
-
if old_selection_count > 0
|
164
|
+
if old_selection_count.to_i > 0
|
102
165
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
103
166
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
104
167
|
else
|
@@ -124,7 +187,7 @@ module Glimmer
|
|
124
187
|
end
|
125
188
|
old_caret_position = self.caret_position
|
126
189
|
self.dirty_content = new_lines.join("\n")
|
127
|
-
if old_selection_count > 0
|
190
|
+
if old_selection_count.to_i > 0
|
128
191
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
129
192
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
130
193
|
else
|
@@ -144,7 +207,7 @@ module Glimmer
|
|
144
207
|
delta = 0
|
145
208
|
line_indices_for_selection(caret_position, selection_count).each do |the_line_index|
|
146
209
|
the_line = old_lines[the_line_index]
|
147
|
-
if the_line.start_with?(' ')
|
210
|
+
if the_line.to_s.start_with?(' ')
|
148
211
|
new_lines[the_line_index] = the_line.sub(/ /, '')
|
149
212
|
delta = -2
|
150
213
|
elsif the_line.start_with?(' ')
|
@@ -153,7 +216,7 @@ module Glimmer
|
|
153
216
|
end
|
154
217
|
end
|
155
218
|
self.dirty_content = new_lines.join("\n")
|
156
|
-
if old_selection_count > 0
|
219
|
+
if old_selection_count.to_i > 0
|
157
220
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
158
221
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
159
222
|
else
|
@@ -165,12 +228,15 @@ module Glimmer
|
|
165
228
|
|
166
229
|
def kill_line!
|
167
230
|
new_lines = lines
|
168
|
-
return if new_lines.size <
|
231
|
+
return if new_lines.size < 1
|
169
232
|
line_indices = line_indices_for_selection(caret_position, selection_count)
|
170
233
|
new_lines = new_lines[0...line_indices.first] + new_lines[(line_indices.last+1)...new_lines.size]
|
171
234
|
old_caret_position = self.caret_position
|
172
|
-
self.
|
173
|
-
|
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
|
174
240
|
end
|
175
241
|
|
176
242
|
def duplicate_line!
|
@@ -189,7 +255,7 @@ module Glimmer
|
|
189
255
|
new_lines.insert(the_line_indices.first + i, the_line)
|
190
256
|
end
|
191
257
|
self.dirty_content = new_lines.join("\n")
|
192
|
-
if old_selection_count > 0
|
258
|
+
if old_selection_count.to_i > 0
|
193
259
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
194
260
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
195
261
|
else
|
@@ -201,12 +267,21 @@ module Glimmer
|
|
201
267
|
return if find_text.to_s.empty?
|
202
268
|
all_lines = lines
|
203
269
|
the_line_index = line_index_for_caret_position(caret_position)
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
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
|
210
285
|
end
|
211
286
|
end
|
212
287
|
end
|
@@ -215,21 +290,34 @@ module Glimmer
|
|
215
290
|
return if find_text.to_s.empty?
|
216
291
|
all_lines = lines
|
217
292
|
the_line_index = line_index_for_caret_position(caret_position)
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
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
|
226
310
|
end
|
227
311
|
end
|
228
312
|
end
|
229
313
|
|
230
314
|
def ensure_find_next
|
231
315
|
return if find_text.to_s.empty? || dirty_content.to_s.strip.size < 1
|
232
|
-
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
|
233
321
|
end
|
234
322
|
|
235
323
|
def replace_next!
|
@@ -242,10 +330,12 @@ module Glimmer
|
|
242
330
|
end
|
243
331
|
|
244
332
|
def page_up
|
333
|
+
self.selection_count = 0
|
245
334
|
self.line_number = [(self.line_number - 15), 1].max
|
246
335
|
end
|
247
336
|
|
248
337
|
def page_down
|
338
|
+
self.selection_count = 0
|
249
339
|
self.line_number = [(self.line_number + 15), lines.size].min
|
250
340
|
end
|
251
341
|
|
@@ -262,23 +352,18 @@ module Glimmer
|
|
262
352
|
return if old_lines.size < 2
|
263
353
|
old_selection_count = self.selection_count
|
264
354
|
old_caret_position = self.caret_position
|
265
|
-
|
266
|
-
|
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
|
267
357
|
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
268
358
|
new_lines = lines
|
269
359
|
the_line_indices = line_indices_for_selection(caret_position, selection_count)
|
270
360
|
the_lines = lines_for_selection(caret_position, selection_count)
|
271
361
|
new_line_index = [the_line_indices.first - 1, 0].max
|
272
|
-
delta = -1 * (new_lines[new_line_index].size + 1)
|
273
362
|
new_lines[the_line_indices.first..the_line_indices.last] = []
|
274
363
|
new_lines[new_line_index...new_line_index] = the_lines
|
275
364
|
self.dirty_content = new_lines.join("\n")
|
276
|
-
|
277
|
-
|
278
|
-
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position + delta)
|
279
|
-
else
|
280
|
-
self.caret_position = old_caret_position + delta
|
281
|
-
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
|
282
367
|
end
|
283
368
|
|
284
369
|
def move_down!
|
@@ -286,23 +371,18 @@ module Glimmer
|
|
286
371
|
return if old_lines.size < 2
|
287
372
|
old_selection_count = self.selection_count
|
288
373
|
old_caret_position = self.caret_position
|
289
|
-
|
290
|
-
|
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
|
291
376
|
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
292
377
|
new_lines = lines
|
293
378
|
the_line_indices = line_indices_for_selection(caret_position, selection_count)
|
294
379
|
the_lines = lines_for_selection(caret_position, selection_count)
|
295
380
|
new_line_index = [the_line_indices.first + 1, new_lines.size - 1].min
|
296
|
-
delta = new_lines[new_line_index].size + 1
|
297
381
|
new_lines[the_line_indices.first..the_line_indices.last] = []
|
298
382
|
new_lines[new_line_index...new_line_index] = the_lines
|
299
383
|
self.dirty_content = new_lines.join("\n")
|
300
|
-
|
301
|
-
|
302
|
-
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position + delta)
|
303
|
-
else
|
304
|
-
self.caret_position = old_caret_position + delta
|
305
|
-
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
|
306
386
|
end
|
307
387
|
|
308
388
|
def lines
|
@@ -318,12 +398,21 @@ module Glimmer
|
|
318
398
|
end
|
319
399
|
|
320
400
|
def caret_position_for_line_index(line_index)
|
321
|
-
lines[0...line_index].join("\n").size
|
401
|
+
cp = lines[0...line_index].join("\n").size
|
402
|
+
cp += 1 if line_index > 0
|
403
|
+
cp
|
322
404
|
end
|
323
405
|
|
324
406
|
def caret_position_for_caret_position_start_of_line(caret_position)
|
325
407
|
caret_position_for_line_index(line_index_for_caret_position(caret_position))
|
326
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
|
327
416
|
|
328
417
|
def line_caret_positions_for_selection(caret_position, selection_count)
|
329
418
|
line_indices = line_indices_for_selection(caret_position, selection_count)
|
@@ -358,6 +447,14 @@ module Glimmer
|
|
358
447
|
def to_s
|
359
448
|
path
|
360
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
|
361
458
|
end
|
362
459
|
end
|
363
460
|
end
|