glimmer-cs-gladiator 0.4.1 → 0.5.0
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 +10 -11
- data/VERSION +1 -1
- data/bin/gladiator_runner.rb +2 -1
- data/lib/models/glimmer/gladiator/dir.rb +51 -51
- data/lib/models/glimmer/gladiator/file.rb +106 -76
- data/lib/views/glimmer/gladiator.rb +358 -278
- data/lib/views/glimmer/gladiator/text_editor.rb +21 -16
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bb031342309fc665039e7a7a64e4a3996f3e659a17767527d47da00e5d7ede50
|
4
|
+
data.tar.gz: 434912cc7be89f07d1e14cdf94ff1511ea7c6ca8e5b09d19654850c3680cb443
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c594f90f5643023e7424747b9abd1959778c9d8d878a99e6b577f7f94e796f5c930c68eccfe267b84860f330cc0ca3004db784fbd6e59f73d62abe41988a6d9
|
7
|
+
data.tar.gz: db5c00808053ba03f441fc3fdf9d00afd627cc688cb8baa036fe749a679eba34628dd5dd629d7d20ef56614f2429bdce0918c7f294cf10fec611e74b20251923
|
data/README.md
CHANGED
@@ -1,14 +1,12 @@
|
|
1
|
-
# <img src='https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/master/images/glimmer-cs-gladiator-logo.svg' height=85 /> Gladiator 0.
|
1
|
+
# <img src='https://raw.githubusercontent.com/AndyObtiva/glimmer-cs-gladiator/master/images/glimmer-cs-gladiator-logo.svg' height=85 /> Gladiator 0.5.0 - [Ugliest Text Editor Ever](https://www.reddit.com/r/ruby/comments/hgve8k/gladiator_glimmer_editor_ugliest_text_editor_ever/)
|
2
2
|
## [<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=40 /> Glimmer Custom Shell](https://github.com/AndyObtiva/glimmer-dsl-swt#custom-shell-gem)
|
3
3
|
[](http://badge.fury.io/rb/glimmer-cs-gladiator)
|
4
4
|
|
5
5
|

|
6
6
|
|
7
|
-
(Now, slightly less ugly with Ruby syntax highlighting colors)
|
8
|
-
|
9
7
|
Gladiator (short for Glimmer Editor) is a [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) sample project under on-going development that demonstrates how to build a text editor in Ruby using [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) (JRuby Desktop Development GUI Library).
|
10
8
|
It is not intended to be a full-fledged editor by any means, yet mostly a fun educational exercise in using [Glimmer](https://github.com/AndyObtiva/glimmer).
|
11
|
-
Gladiator is also a personal tool for shaping an editor exactly the way I like, with all the keyboard shortcuts I prefer.
|
9
|
+
Gladiator is also a personal tool for shaping an editor exactly the way I like, with all the keyboard shortcuts I prefer.
|
12
10
|
I leave building truly professional text editors to software tooling experts who would hopefully use [Glimmer](https://github.com/AndyObtiva/glimmer) one day. Otherwise, I have been happily using Gladiator to develop all my [open-source projects](https://github.com/AndyObtiva) since May of 2020.
|
13
11
|
|
14
12
|
## Features
|
@@ -24,7 +22,7 @@ Gladiator currently supports the following text editing features (including keyb
|
|
24
22
|
- Jump to Line (CMD+L)
|
25
23
|
- Multiple tab support (CMD+SHIFT+[ & CMD+SHIFT+] for tab navigation. CMD+1-9 to jump to a specific tab)
|
26
24
|
- Remember opened tabs, caret position, top line, window size, and window location
|
27
|
-
- Autosave on focus out/quit/open new file
|
25
|
+
- Autosave on focus out/quit/open new file
|
28
26
|
- Duplicate Line(s)/selection (CMD+D)
|
29
27
|
- Kill Line(s)/selection (CMD+K)
|
30
28
|
- Move line/selection up (CMD+UP)
|
@@ -33,14 +31,15 @@ Gladiator currently supports the following text editing features (including keyb
|
|
33
31
|
- Indent/Unindent line/selection (CMD+] & CMD+[)
|
34
32
|
- Insert/Prefix New Line (CMD+ENTER & CMD+SHIFT+ENTER)
|
35
33
|
- Drag and Drop Text Editor Split Screen (drag a file from File Tree or File Lookup List, and it splits the screen)
|
36
|
-
- Run
|
34
|
+
- Run Ruby code (CMD+SHIFT+R)
|
35
|
+
- Scratchpad for running arbitrary Ruby/Glimmer code without saving to disk (CMD+SHIFT+S)
|
37
36
|
- Change Split Orientation to Horizontal/Vertical via View Menu (CMD+SHIFT+O)
|
38
37
|
|
39
38
|
## Platforms
|
40
39
|
|
41
40
|
- Mac: Gladiator works best on the Mac. This is the platform it is most used on and receives the most maintenance for.
|
42
|
-
- Windows: Gladiator works OK on Windows, but has some annoying bugs.
|
43
|
-
- Linux: Gladiator works with
|
41
|
+
- Windows: Gladiator works OK on Windows, but has some annoying bugs. Contributers could help fix.
|
42
|
+
- Linux: Gladiator works with handicaps on Linux (performing some text editing operations causes scroll jitter). Contributers could help fix.
|
44
43
|
|
45
44
|
## Pre-requisites
|
46
45
|
|
@@ -100,11 +99,11 @@ bin/gladiator relative-or-absolute-path/to/project
|
|
100
99
|
|
101
100
|
### Glimmer Custom Shell Reuse
|
102
101
|
|
103
|
-
To reuse Gladiator as a Glimmer Custom Shell inside another Glimmer application, add the
|
102
|
+
To reuse Gladiator as a Glimmer Custom Shell inside another Glimmer application, add the
|
104
103
|
following to the application's `Gemfile`:
|
105
104
|
|
106
105
|
```
|
107
|
-
gem 'glimmer-cs-gladiator', '~> 0.
|
106
|
+
gem 'glimmer-cs-gladiator', '~> 0.5.0'
|
108
107
|
```
|
109
108
|
|
110
109
|
Run:
|
@@ -117,7 +116,7 @@ And, then instantiate the Gladiator [custom shell](https://github.com/AndyObtiva
|
|
117
116
|
|
118
117
|
## Env Var Options
|
119
118
|
|
120
|
-
Gladiator opens with the current directory as the root by default.
|
119
|
+
Gladiator opens with the current directory as the root by default.
|
121
120
|
If you would like to open another directory, set `LOCAL_DIR` environment variable.
|
122
121
|
|
123
122
|
Example:
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/bin/gladiator_runner.rb
CHANGED
@@ -4,39 +4,40 @@ module Glimmer
|
|
4
4
|
class Gladiator
|
5
5
|
class Dir
|
6
6
|
include Glimmer
|
7
|
+
include Glimmer::DataBinding::ObservableModel
|
7
8
|
|
8
9
|
REFRESH_DELAY = 7
|
9
10
|
|
10
|
-
class << self
|
11
|
-
def local_dir
|
12
|
-
unless @local_dir
|
13
|
-
@local_dir = new(ENV['LOCAL_DIR'] || '.', true)
|
14
|
-
# @local_dir.refresh
|
15
|
-
@filewatcher = Filewatcher.new(@local_dir.path)
|
16
|
-
@thread = Thread.new(@filewatcher) do |fw|
|
17
|
-
fw.watch do |filename, event|
|
18
|
-
if @last_update.nil? || (Time.now.to_f - @last_update) > REFRESH_DELAY
|
19
|
-
@local_dir.refresh if !filename.include?('new_file') && !@local_dir.selected_child_path_history.include?(filename) && filename != @local_dir.selected_child_path
|
20
|
-
end
|
21
|
-
@last_update = Time.now.to_f
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
@local_dir
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
11
|
attr_accessor :selected_child, :filter, :children, :filtered_path_options, :filtered_path, :display_path, :ignore_paths
|
30
|
-
attr_reader :name, :parent, :path
|
12
|
+
attr_reader :name, :parent, :path
|
31
13
|
attr_writer :all_children
|
32
14
|
|
33
|
-
def initialize(path,
|
34
|
-
@
|
15
|
+
def initialize(path, project_dir = nil)
|
16
|
+
@project_dir = project_dir
|
17
|
+
if is_local_dir
|
18
|
+
@filewatcher = Filewatcher.new(path)
|
19
|
+
@thread = Thread.new(@filewatcher) do |fw|
|
20
|
+
fw.watch do |filename, event|
|
21
|
+
if @last_update.nil? || (Time.now.to_f - @last_update) > REFRESH_DELAY
|
22
|
+
refresh if !filename.include?('new_file') && !selected_child_path_history.include?(filename) && filename != selected_child_path
|
23
|
+
end
|
24
|
+
@last_update = Time.now.to_f
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
35
28
|
self.path = ::File.expand_path(path)
|
36
29
|
@name = ::File.basename(::File.expand_path(path))
|
37
|
-
@ignore_paths = ['packages', 'tmp', 'vendor']
|
30
|
+
@ignore_paths = ['.gladiator', '.git', 'coverage', 'packages', 'tmp', 'vendor']
|
38
31
|
self.filtered_path_options = []
|
39
32
|
end
|
33
|
+
|
34
|
+
def is_local_dir
|
35
|
+
@project_dir.nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
def project_dir
|
39
|
+
@project_dir || self
|
40
|
+
end
|
40
41
|
|
41
42
|
def path=(the_path)
|
42
43
|
@path = the_path
|
@@ -44,32 +45,24 @@ module Glimmer
|
|
44
45
|
end
|
45
46
|
|
46
47
|
def generate_display_path
|
47
|
-
is_local_dir ? path : @display_path = @path.sub(
|
48
|
+
is_local_dir ? path : @display_path = @path.sub(project_dir.path, '').sub(/^\//, '')
|
48
49
|
end
|
49
50
|
|
50
|
-
def name=(the_name)
|
51
|
-
self.display_path = display_path.sub(/#{Regexp.escape(@name)}$/, the_name)
|
52
|
-
@name = the_name
|
53
|
-
new_path = ::File.expand_path(display_path)
|
54
|
-
FileUtils.mv(path, new_path)
|
55
|
-
self.path = display_path
|
56
|
-
end
|
57
|
-
|
58
51
|
def children
|
59
52
|
@children ||= retrieve_children
|
60
53
|
end
|
61
54
|
|
62
55
|
def retrieve_children
|
63
56
|
@children = ::Dir.glob(::File.join(@path, '*')).reject do |p|
|
64
|
-
# TODO make sure to configure ignore_paths in a preferences dialog
|
65
|
-
|
57
|
+
# TODO make sure to configure ignore_paths in a preferences dialog
|
58
|
+
project_dir.ignore_paths.reduce(false) do |result, ignore_path|
|
66
59
|
result || p.include?(ignore_path)
|
67
60
|
end
|
68
|
-
end.map do |p|
|
69
|
-
::File.file?(p) ? Gladiator::File.new(p) : Gladiator::Dir.new(p)
|
70
|
-
end.sort_by do |c|
|
71
|
-
c.path.to_s.downcase
|
72
|
-
end.sort_by do |c|
|
61
|
+
end.map do |p|
|
62
|
+
::File.file?(p) ? Gladiator::File.new(p, project_dir) : Gladiator::Dir.new(p, project_dir)
|
63
|
+
end.sort_by do |c|
|
64
|
+
c.path.to_s.downcase
|
65
|
+
end.sort_by do |c|
|
73
66
|
c.class.name
|
74
67
|
end.each do |child|
|
75
68
|
child.retrieve_children if child.is_a?(Dir)
|
@@ -105,7 +98,7 @@ module Glimmer
|
|
105
98
|
|
106
99
|
def filter=(value)
|
107
100
|
if value.to_s.empty?
|
108
|
-
@filter = nil
|
101
|
+
@filter = nil
|
109
102
|
else
|
110
103
|
@filter = value
|
111
104
|
end
|
@@ -117,8 +110,8 @@ module Glimmer
|
|
117
110
|
def filtered
|
118
111
|
return if filter.nil?
|
119
112
|
children_files = !@last_filter.to_s.empty? && filter.downcase.start_with?(@last_filter.downcase) ? @last_filtered : all_children_files
|
120
|
-
children_files.select do |child|
|
121
|
-
child_path = child.path.to_s.sub(
|
113
|
+
children_files.select do |child|
|
114
|
+
child_path = child.path.to_s.sub(project_dir.path, '')
|
122
115
|
child_path.downcase.include?(filter.downcase) ||
|
123
116
|
child_path.downcase.gsub(/[_\/.-]/, '').include?(filter.downcase.gsub(/[_\/.-]/, ''))
|
124
117
|
end.sort_by {|c| c.path.to_s.downcase}
|
@@ -141,14 +134,19 @@ module Glimmer
|
|
141
134
|
end
|
142
135
|
|
143
136
|
def selected_child_path=(selected_path)
|
144
|
-
|
145
|
-
|
146
|
-
|
137
|
+
# scratchpad scenario
|
138
|
+
if selected_path&.empty? #scratchpad
|
139
|
+
@selected_child&.write_dirty_content
|
140
|
+
return (self.selected_child = File.new)
|
141
|
+
end
|
142
|
+
full_selected_path = selected_path.include?(project_dir.path) ? selected_path : ::File.join(project_dir.path, selected_path)
|
143
|
+
return if selected_path.nil? ||
|
144
|
+
::Dir.exist?(full_selected_path) ||
|
147
145
|
(selected_child && selected_child.path == full_selected_path)
|
148
146
|
selected_path = full_selected_path
|
149
147
|
if ::File.file?(selected_path)
|
150
148
|
@selected_child&.write_dirty_content
|
151
|
-
new_child = Gladiator::File.new(selected_path)
|
149
|
+
new_child = Gladiator::File.new(selected_path, project_dir)
|
152
150
|
begin
|
153
151
|
unless new_child.dirty_content.nil?
|
154
152
|
self.selected_child&.stop_filewatcher
|
@@ -168,6 +166,12 @@ module Glimmer
|
|
168
166
|
@selected_child&.path
|
169
167
|
end
|
170
168
|
|
169
|
+
def selected_child=(new_child)
|
170
|
+
file_properties = @selected_child&.backup_properties if @selected_child == new_child
|
171
|
+
@selected_child = new_child
|
172
|
+
@selected_child.restore_properties(file_properties) if file_properties
|
173
|
+
end
|
174
|
+
|
171
175
|
def delete!
|
172
176
|
FileUtils.rm_rf(path)
|
173
177
|
end
|
@@ -183,11 +187,7 @@ module Glimmer
|
|
183
187
|
def hash
|
184
188
|
self.path.hash
|
185
189
|
end
|
186
|
-
end
|
190
|
+
end
|
187
191
|
end
|
188
192
|
end
|
189
|
-
|
190
|
-
at_exit do
|
191
|
-
Glimmer::Gladiator::Dir.local_dir.selected_child&.write_raw_dirty_content
|
192
|
-
end
|
193
193
|
|
@@ -1,22 +1,21 @@
|
|
1
|
-
require 'models/glimmer/gladiator/dir'
|
2
|
-
|
3
1
|
module Glimmer
|
4
2
|
class Gladiator
|
5
3
|
class File
|
6
4
|
include Glimmer
|
7
|
-
|
5
|
+
|
8
6
|
attr_accessor :dirty_content, :line_numbers_content, :selection, :line_number, :find_text, :replace_text, :top_pixel, :display_path, :case_sensitive
|
9
|
-
attr_reader :name, :path
|
7
|
+
attr_reader :name, :path, :project_dir
|
10
8
|
|
11
|
-
def initialize(path)
|
12
|
-
raise "Not a file path: #{path}"
|
9
|
+
def initialize(path='', project_dir=nil)
|
10
|
+
raise "Not a file path: #{path}" if path.nil? || (!path.empty? && !::File.file?(path))
|
11
|
+
@project_dir = project_dir
|
13
12
|
@command_history = []
|
14
|
-
@name = ::File.basename(path)
|
15
|
-
self.path = ::File.expand_path(path)
|
13
|
+
@name = path.empty? ? 'Scratchpad' : ::File.basename(path)
|
14
|
+
self.path = ::File.expand_path(path) unless path.empty?
|
16
15
|
@top_pixel = 0
|
17
16
|
@selection_count = 0
|
18
17
|
@selection = Point.new(0, 0 + @selection_count)
|
19
|
-
read_dirty_content = ::File.read(path)
|
18
|
+
read_dirty_content = path.empty? ? '' : ::File.read(path)
|
20
19
|
begin
|
21
20
|
# test read dirty content
|
22
21
|
read_dirty_content.split("\n")
|
@@ -40,16 +39,34 @@ module Glimmer
|
|
40
39
|
# no op in case of a binary file
|
41
40
|
end
|
42
41
|
end
|
43
|
-
|
42
|
+
|
44
43
|
def path=(the_path)
|
45
44
|
@path = the_path
|
46
45
|
generate_display_path
|
47
46
|
end
|
48
|
-
|
47
|
+
|
49
48
|
def generate_display_path
|
50
|
-
|
49
|
+
return if @path.empty?
|
50
|
+
@display_path = @path.sub(project_dir.path, '').sub(/^\//, '')
|
51
51
|
end
|
52
52
|
|
53
|
+
def scratchpad?
|
54
|
+
path.empty?
|
55
|
+
end
|
56
|
+
|
57
|
+
def backup_properties
|
58
|
+
[:find_text, :replace_text, :case_sensitive, :top_pixel, :caret_position, :selection_count].reduce({}) do |hash, property|
|
59
|
+
hash.merge(property => send(property))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def restore_properties(properties_hash)
|
64
|
+
return if properties_hash[:caret_position] == 0 && properties_hash[:selection_count] == 0 && properties_hash[:find_text].nil? && properties_hash[:replace_text].nil? && properties_hash[:top_pixel] == 0 && properties_hash[:case_sensitive].nil?
|
65
|
+
properties_hash.each do |property, value|
|
66
|
+
send("#{property}=", value)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
53
70
|
# to use for widget data-binding
|
54
71
|
def content=(value)
|
55
72
|
value = value.gsub("\t", ' ')
|
@@ -68,7 +85,7 @@ module Glimmer
|
|
68
85
|
self.selection = Point.new(value, value + selection_count.to_i)
|
69
86
|
self.top_pixel = old_top_pixel
|
70
87
|
end
|
71
|
-
|
88
|
+
|
72
89
|
def caret_position
|
73
90
|
selection.x
|
74
91
|
end
|
@@ -76,28 +93,20 @@ module Glimmer
|
|
76
93
|
def selection_count
|
77
94
|
selection.y - selection.x
|
78
95
|
end
|
79
|
-
|
96
|
+
|
80
97
|
def selection_count=(value)
|
81
98
|
self.selection = Point.new(caret_position, caret_position + value.to_i)
|
82
|
-
end
|
83
|
-
|
84
|
-
def name=(the_name)
|
85
|
-
new_path = path.sub(/#{Regexp.escape(@name)}$/, the_name)
|
86
|
-
@name = the_name
|
87
|
-
if ::File.exists?(path)
|
88
|
-
FileUtils.mv(path, new_path)
|
89
|
-
self.path = new_path
|
90
|
-
end
|
91
99
|
end
|
92
|
-
|
100
|
+
|
93
101
|
def dirty_content=(the_content)
|
94
|
-
@dirty_content = the_content
|
102
|
+
@dirty_content = the_content
|
95
103
|
notify_observers(:content)
|
96
104
|
end
|
97
|
-
|
105
|
+
|
98
106
|
def start_filewatcher
|
107
|
+
return if scratchpad?
|
99
108
|
@filewatcher = Filewatcher.new(@path)
|
100
|
-
@thread = Thread.new(@filewatcher) do |fw|
|
109
|
+
@thread = Thread.new(@filewatcher) do |fw|
|
101
110
|
fw.watch do |filename, event|
|
102
111
|
begin
|
103
112
|
read_dirty_content = ::File.read(path)
|
@@ -112,27 +121,28 @@ module Glimmer
|
|
112
121
|
end
|
113
122
|
end
|
114
123
|
end
|
115
|
-
|
124
|
+
|
116
125
|
def stop_filewatcher
|
117
126
|
@filewatcher&.stop
|
118
127
|
end
|
119
128
|
|
120
129
|
def format_dirty_content_for_writing!
|
121
|
-
new_dirty_content =
|
130
|
+
new_dirty_content = dirty_content.split("\n").map {|line| line.strip.empty? ? line : line.rstrip }.join("\n")
|
131
|
+
new_dirty_content = "#{new_dirty_content.gsub("\r\n", "\n").gsub("\r", "\n").sub(/\n+\z/, '')}\n"
|
122
132
|
self.dirty_content = new_dirty_content if new_dirty_content != self.dirty_content
|
123
133
|
end
|
124
|
-
|
134
|
+
|
125
135
|
def write_dirty_content
|
126
|
-
return
|
136
|
+
return if scratchpad? || !::File.exist?(path)
|
127
137
|
format_dirty_content_for_writing!
|
128
138
|
::File.write(path, dirty_content) if ::File.exists?(path)
|
129
139
|
rescue => e
|
130
140
|
puts "Error in writing dirty content for #{path}"
|
131
141
|
puts e.full_message
|
132
142
|
end
|
133
|
-
|
143
|
+
|
134
144
|
def write_raw_dirty_content
|
135
|
-
return
|
145
|
+
return if scratchpad? || !::File.exist?(path)
|
136
146
|
::File.write(path, dirty_content) if ::File.exists?(path)
|
137
147
|
rescue => e
|
138
148
|
puts "Error in writing raw dirty content for #{path}"
|
@@ -143,19 +153,20 @@ module Glimmer
|
|
143
153
|
current_line.to_s.match(/^(\s+)/).to_a[1].to_s
|
144
154
|
end
|
145
155
|
|
146
|
-
def current_line
|
156
|
+
def current_line
|
147
157
|
lines[line_number - 1]
|
148
158
|
end
|
149
159
|
|
150
160
|
def delete!
|
151
|
-
FileUtils.rm(path)
|
161
|
+
FileUtils.rm(path) unless scratchpad?
|
152
162
|
end
|
153
|
-
|
163
|
+
|
154
164
|
def prefix_new_line!
|
155
165
|
the_lines = lines
|
156
166
|
the_lines[line_number-1...line_number-1] = [current_line_indentation]
|
157
167
|
self.dirty_content = the_lines.join("\n")
|
158
168
|
self.caret_position = caret_position_for_line_index(line_number-1) + current_line_indentation.size
|
169
|
+
self.selection_count = 0
|
159
170
|
end
|
160
171
|
|
161
172
|
def insert_new_line!
|
@@ -163,6 +174,7 @@ module Glimmer
|
|
163
174
|
the_lines[line_number...line_number] = [current_line_indentation]
|
164
175
|
self.dirty_content = the_lines.join("\n")
|
165
176
|
self.caret_position = caret_position_for_line_index(line_number) + current_line_indentation.size
|
177
|
+
self.selection_count = 0
|
166
178
|
end
|
167
179
|
|
168
180
|
def comment_line!
|
@@ -190,7 +202,7 @@ module Glimmer
|
|
190
202
|
delta += 2
|
191
203
|
end
|
192
204
|
end
|
193
|
-
self.dirty_content = new_lines.join("\n")
|
205
|
+
self.dirty_content = new_lines.join("\n")
|
194
206
|
if old_selection_count.to_i > 0
|
195
207
|
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
196
208
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
@@ -200,7 +212,7 @@ module Glimmer
|
|
200
212
|
self.caret_position = new_caret_position
|
201
213
|
end
|
202
214
|
end
|
203
|
-
|
215
|
+
|
204
216
|
def indent!
|
205
217
|
new_lines = lines
|
206
218
|
old_lines = lines
|
@@ -216,16 +228,15 @@ module Glimmer
|
|
216
228
|
new_lines[the_line_index] = " #{the_line}"
|
217
229
|
end
|
218
230
|
old_caret_position = self.caret_position
|
219
|
-
self.dirty_content = new_lines.join("\n")
|
231
|
+
self.dirty_content = new_lines.join("\n")
|
220
232
|
if old_selection_count.to_i > 0
|
221
|
-
|
222
|
-
|
223
|
-
self.selection = Point.new(caret_position_value, caret_position_value + selection_count_value)
|
233
|
+
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
234
|
+
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
224
235
|
else
|
225
236
|
self.caret_position = old_caret_position + delta
|
226
237
|
end
|
227
238
|
end
|
228
|
-
|
239
|
+
|
229
240
|
def outdent!
|
230
241
|
new_lines = lines
|
231
242
|
old_lines = lines
|
@@ -246,18 +257,17 @@ module Glimmer
|
|
246
257
|
delta = -1
|
247
258
|
end
|
248
259
|
end
|
249
|
-
self.dirty_content = new_lines.join("\n")
|
260
|
+
self.dirty_content = new_lines.join("\n")
|
250
261
|
if old_selection_count.to_i > 0
|
251
|
-
|
252
|
-
|
253
|
-
self.selection = Point.new(caret_position_value, caret_position_value + selection_count_value)
|
262
|
+
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
263
|
+
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
254
264
|
else
|
255
265
|
new_caret_position = old_caret_position + delta
|
256
266
|
new_caret_position = [new_caret_position, old_caret_position_line_caret_position].max
|
257
267
|
self.caret_position = new_caret_position
|
258
268
|
end
|
259
269
|
end
|
260
|
-
|
270
|
+
|
261
271
|
def kill_line!
|
262
272
|
new_lines = lines
|
263
273
|
return if new_lines.size < 1
|
@@ -270,7 +280,7 @@ module Glimmer
|
|
270
280
|
self.caret_position = caret_position_for_line_index(old_line_index) + [line_position, lines[old_line_index].to_s.size].min
|
271
281
|
self.selection_count = 0
|
272
282
|
end
|
273
|
-
|
283
|
+
|
274
284
|
def duplicate_line!
|
275
285
|
new_lines = lines
|
276
286
|
old_lines = lines
|
@@ -294,9 +304,9 @@ module Glimmer
|
|
294
304
|
self.caret_position = old_caret_position + delta
|
295
305
|
end
|
296
306
|
end
|
297
|
-
|
307
|
+
|
298
308
|
def find_next
|
299
|
-
return if find_text.to_s.empty?
|
309
|
+
return if find_text.to_s.empty?
|
300
310
|
all_lines = lines
|
301
311
|
the_line_index = line_index_for_caret_position(caret_position)
|
302
312
|
line_position = line_position_for_caret_position(caret_position)
|
@@ -312,13 +322,12 @@ module Glimmer
|
|
312
322
|
if occurrence_index
|
313
323
|
self.caret_position = caret_position_for_line_index(the_index) + start_position + occurrence_index
|
314
324
|
self.selection_count = find_text.to_s.size
|
315
|
-
self.selection = Point.new(self.caret_position, self.caret_position + self.selection_count)
|
316
325
|
return
|
317
326
|
end
|
318
327
|
end
|
319
328
|
end
|
320
329
|
end
|
321
|
-
|
330
|
+
|
322
331
|
def find_previous
|
323
332
|
return if find_text.to_s.empty?
|
324
333
|
all_lines = lines
|
@@ -343,7 +352,7 @@ module Glimmer
|
|
343
352
|
end
|
344
353
|
end
|
345
354
|
end
|
346
|
-
|
355
|
+
|
347
356
|
def ensure_find_next
|
348
357
|
return if find_text.to_s.empty? || dirty_content.to_s.strip.size < 1
|
349
358
|
find_next unless found_text?(self.caret_position)
|
@@ -352,37 +361,45 @@ module Glimmer
|
|
352
361
|
def found_text?(caret_position)
|
353
362
|
dirty_content[caret_position.to_i, find_text.to_s.size].to_s.downcase == find_text.to_s.downcase
|
354
363
|
end
|
355
|
-
|
364
|
+
|
356
365
|
def replace_next!
|
357
366
|
return if find_text.to_s.empty? || dirty_content.to_s.strip.size < 1
|
358
367
|
ensure_find_next
|
359
368
|
new_dirty_content = dirty_content
|
360
369
|
new_dirty_content[caret_position, find_text.size] = replace_text.to_s
|
361
370
|
self.dirty_content = new_dirty_content
|
362
|
-
find_next
|
371
|
+
find_next
|
363
372
|
find_next if replace_text.to_s.include?(find_text) && !replace_text.to_s.start_with?(find_text)
|
364
373
|
end
|
365
|
-
|
374
|
+
|
366
375
|
def page_up
|
367
376
|
self.selection_count = 0
|
368
377
|
self.line_number = [(self.line_number - 15), 1].max
|
369
378
|
end
|
370
|
-
|
379
|
+
|
371
380
|
def page_down
|
372
381
|
self.selection_count = 0
|
373
382
|
self.line_number = [(self.line_number + 15), lines.size].min
|
374
383
|
end
|
375
|
-
|
384
|
+
|
376
385
|
def home
|
377
386
|
self.selection_count = 0
|
378
387
|
self.line_number = 1
|
379
388
|
end
|
380
|
-
|
389
|
+
|
381
390
|
def end
|
382
391
|
self.selection_count = 0
|
383
392
|
self.line_number = lines.size
|
384
393
|
end
|
385
|
-
|
394
|
+
|
395
|
+
def start_of_line
|
396
|
+
self.caret_position = caret_position_for_line_index(self.line_number - 1)
|
397
|
+
end
|
398
|
+
|
399
|
+
def end_of_line
|
400
|
+
self.caret_position = caret_position_for_line_index(self.line_number) - 1
|
401
|
+
end
|
402
|
+
|
386
403
|
def move_up!
|
387
404
|
old_lines = lines
|
388
405
|
return if old_lines.size < 2
|
@@ -401,7 +418,7 @@ module Glimmer
|
|
401
418
|
self.caret_position = caret_position_for_line_index(new_line_index) + [old_caret_position_line_position, new_lines[new_line_index].size].min
|
402
419
|
self.selection_count = old_selection_count.to_i if old_selection_count.to_i > 0
|
403
420
|
end
|
404
|
-
|
421
|
+
|
405
422
|
def move_down!
|
406
423
|
old_lines = lines
|
407
424
|
return if old_lines.size < 2
|
@@ -420,25 +437,38 @@ module Glimmer
|
|
420
437
|
self.caret_position = caret_position_for_line_index(new_line_index) + [old_caret_position_line_position, new_lines[new_line_index].size].min
|
421
438
|
self.selection_count = old_selection_count.to_i if old_selection_count.to_i > 0
|
422
439
|
end
|
423
|
-
|
440
|
+
|
441
|
+
def run
|
442
|
+
begin
|
443
|
+
if scratchpad?
|
444
|
+
eval content
|
445
|
+
else
|
446
|
+
write_dirty_content
|
447
|
+
load path
|
448
|
+
end
|
449
|
+
rescue SyntaxError, StandardError => e
|
450
|
+
puts e.full_message
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
424
454
|
def lines
|
425
455
|
dirty_content.split("\n")
|
426
456
|
end
|
427
|
-
|
457
|
+
|
428
458
|
def line_for_caret_position(caret_position)
|
429
459
|
lines[line_index_for_caret_position(caret_position.to_i)]
|
430
460
|
end
|
431
|
-
|
461
|
+
|
432
462
|
def line_index_for_caret_position(caret_position)
|
433
463
|
dirty_content[0...caret_position.to_i].count("\n")
|
434
464
|
end
|
435
|
-
|
465
|
+
|
436
466
|
def caret_position_for_line_index(line_index)
|
437
467
|
cp = lines[0...line_index].join("\n").size
|
438
468
|
cp += 1 if line_index > 0
|
439
469
|
cp
|
440
470
|
end
|
441
|
-
|
471
|
+
|
442
472
|
def caret_position_for_caret_position_start_of_line(caret_position)
|
443
473
|
caret_position_for_line_index(line_index_for_caret_position(caret_position))
|
444
474
|
end
|
@@ -449,23 +479,23 @@ module Glimmer
|
|
449
479
|
caret_position = caret_position.to_i
|
450
480
|
caret_position - caret_position_for_caret_position_start_of_line(caret_position)
|
451
481
|
end
|
452
|
-
|
482
|
+
|
453
483
|
def line_caret_positions_for_selection(caret_position, selection_count)
|
454
484
|
line_indices = line_indices_for_selection(caret_position, selection_count)
|
455
485
|
line_caret_positions = line_indices.map { |line_index| caret_position_for_line_index(line_index) }.to_a
|
456
486
|
end
|
457
|
-
|
487
|
+
|
458
488
|
def end_caret_position_line_index(caret_position, selection_count)
|
459
489
|
end_caret_position = caret_position + selection_count.to_i
|
460
490
|
end_caret_position -= 1 if dirty_content[end_caret_position - 1] == "\n"
|
461
491
|
end_line_index = line_index_for_caret_position(end_caret_position)
|
462
492
|
end
|
463
|
-
|
493
|
+
|
464
494
|
def lines_for_selection(caret_position, selection_count)
|
465
495
|
line_indices = line_indices_for_selection(caret_position, selection_count)
|
466
496
|
lines[line_indices.first..line_indices.last]
|
467
497
|
end
|
468
|
-
|
498
|
+
|
469
499
|
def line_indices_for_selection(caret_position, selection_count)
|
470
500
|
start_line_index = line_index_for_caret_position(caret_position)
|
471
501
|
if selection_count.to_i > 0
|
@@ -475,22 +505,22 @@ module Glimmer
|
|
475
505
|
end
|
476
506
|
(start_line_index..end_line_index).to_a
|
477
507
|
end
|
478
|
-
|
508
|
+
|
479
509
|
def children
|
480
510
|
[]
|
481
511
|
end
|
482
|
-
|
512
|
+
|
483
513
|
def to_s
|
484
514
|
path
|
485
515
|
end
|
486
|
-
|
516
|
+
|
487
517
|
def eql?(other)
|
488
518
|
self.path.eql?(other&.path)
|
489
519
|
end
|
490
|
-
|
520
|
+
|
491
521
|
def hash
|
492
522
|
self.path.hash
|
493
523
|
end
|
494
|
-
end
|
524
|
+
end
|
495
525
|
end
|
496
526
|
end
|