glimmer-cs-gladiator 0.1.2 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/glimmer-cs-gladiator.svg)](http://badge.fury.io/rb/glimmer-cs-gladiator)
|
3
3
|
|
4
4
|
![Gladiator](images/glimmer-gladiator.png)
|
@@ -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
|