glimmer-cs-gladiator 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +20 -0
- data/README.md +110 -0
- data/bin/gladiator +6 -0
- data/bin/gladiator_runner.rb +5 -0
- data/lib/glimmer-cs-gladiator.rb +5 -0
- data/lib/models/glimmer/gladiator/dir.rb +116 -0
- data/lib/models/glimmer/gladiator/file.rb +357 -0
- data/lib/views/glimmer/gladiator.rb +319 -0
- metadata +142 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: af29d980faf6b1905a69f7a06bed1646fda6ebd1fd30f5016d5ca142afbefe98
|
4
|
+
data.tar.gz: a02ca4bb732b16bc26fb7c7f5d3c7644a7bb2a40ddd77458c96a4d1ecf0d0a87
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 962c8732ca907482bc9031f48974154a945d3276c3a7d7d2e10ee65899343070938bb3d140c7e03f8b2f13126a580ed4129c75503700336f58dffa0b3e17139a
|
7
|
+
data.tar.gz: 5e8e21ebf4e37d4ae244a92372f3d9d17dd8cbd4ee5ebbeedf3e8581493f5101d052e753764ed94c8a9119c6f0f72d9a453c7e168b22de919c31cc27ee3c4824
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2020 Andy Maleh
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
# Gladiator (Glimmer Editor) 0.1.0 - Glimmer Custom Shell
|
2
|
+
|
3
|
+
![Gladiator](images/glimmer-gladiator.png)
|
4
|
+
|
5
|
+
Gladiator (short for Glimmer Editor) is a Glimmer sample project under on-going development.
|
6
|
+
It is not intended to be a full-fledged editor by any means, yet mostly a fun educational exercise in using Glimmer to build a text editor.
|
7
|
+
Gladiator is also a personal tool for shaping an editor exactly the way I like.
|
8
|
+
I leave building truly professional text editors to software tooling experts who would hopefully use Glimmer one day.
|
9
|
+
|
10
|
+
Gladiator currently supports the following text editing features:
|
11
|
+
- File explorer navigation to open file
|
12
|
+
- File lookup by name
|
13
|
+
- Find & Replace
|
14
|
+
- Show Line Numbers
|
15
|
+
- Jump to Line
|
16
|
+
- Remember last opened file, caret position, and top line
|
17
|
+
- Autosave on focus out/quit/open new file
|
18
|
+
- Watch open file for external changes to reflect in editor
|
19
|
+
- Duplicate Line(s)
|
20
|
+
- Kill Line(s)
|
21
|
+
- Move up one line
|
22
|
+
- Move down one line
|
23
|
+
|
24
|
+
## Pre-requisites
|
25
|
+
|
26
|
+
- JRuby 9.2.11.1 (supporting Ruby 2.5.x syntax) (find at https://www.jruby.org/download)
|
27
|
+
- Java SE Runtime Environment 7 or higher (find at https://www.oracle.com/java/technologies/javase-downloads.html)
|
28
|
+
|
29
|
+
## Setup Instructions
|
30
|
+
|
31
|
+
Install Gladiator gem by running (`jgem`, `jruby -S gem`, or `gem` directly if you have RVM):
|
32
|
+
|
33
|
+
```
|
34
|
+
jgem install glimmer-cs-gladiator
|
35
|
+
```
|
36
|
+
|
37
|
+
Afterwards, you may run `gladiator` to bring up the text editor:
|
38
|
+
|
39
|
+
```
|
40
|
+
gladiator
|
41
|
+
```
|
42
|
+
|
43
|
+
Note: If you cloned this project and bundle installed, you may invoke via `bin/gladiator` instead.
|
44
|
+
|
45
|
+
### Glimmer Custom Shell Reuse
|
46
|
+
|
47
|
+
To reuse Gladiator as a Glimmer Custom Shell inside another Glimmer application, add the
|
48
|
+
following to the application's `Gemfile`:
|
49
|
+
|
50
|
+
```
|
51
|
+
gem 'glimmer-cs-gladiator', '0.1.0'
|
52
|
+
```
|
53
|
+
|
54
|
+
Run:
|
55
|
+
|
56
|
+
```
|
57
|
+
jruby -S bundle
|
58
|
+
```
|
59
|
+
|
60
|
+
And, then instantiate the Gladiator custom shell in your Glimmer application via the `gladiator` keyword.
|
61
|
+
|
62
|
+
## Env Var Options
|
63
|
+
|
64
|
+
Gladiator opens with the current directory as the root by default.
|
65
|
+
If you would like to open another directory, set `LOCAL_DIR` environment variable.
|
66
|
+
|
67
|
+
Example:
|
68
|
+
|
69
|
+
```
|
70
|
+
LOCAL_DIR="/Users/User/code" gladiator
|
71
|
+
```
|
72
|
+
|
73
|
+
Opens Gladiator with "/Users/User/code" as the root directory.
|
74
|
+
|
75
|
+
## Configuration
|
76
|
+
|
77
|
+
Gladiator automatically saves configuration data in a `.gladiator` file at the directory it is run from.
|
78
|
+
|
79
|
+
It currently remembers:
|
80
|
+
- Last opened file
|
81
|
+
- Caret position
|
82
|
+
- Top line position
|
83
|
+
|
84
|
+
## Gotcha
|
85
|
+
|
86
|
+
Gladiator repetitively displays a signaling error that is harmless in practice:
|
87
|
+
```
|
88
|
+
The signal HUP is in use by the JVM and will not work correctly on this platform
|
89
|
+
The signal INT is in use by the JVM and will not work correctly on this platform
|
90
|
+
The signal TERM is in use by the JVM and will not work correctly on this platform
|
91
|
+
```
|
92
|
+
|
93
|
+
## TODO
|
94
|
+
|
95
|
+
[TODO.md](TODO.md)
|
96
|
+
|
97
|
+
## Contributing to glimmer-cs-gladiator
|
98
|
+
|
99
|
+
- Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
100
|
+
- Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
101
|
+
- Fork the project.
|
102
|
+
- Start a feature/bugfix branch.
|
103
|
+
- Commit and push until you are happy with your contribution.
|
104
|
+
- Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
105
|
+
- Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
106
|
+
|
107
|
+
## Copyright
|
108
|
+
|
109
|
+
Copyright (c) 2020 Andy Maleh. See LICENSE.txt for
|
110
|
+
further details.
|
data/bin/gladiator
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'models/glimmer/gladiator/file'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
class Gladiator
|
5
|
+
class Dir
|
6
|
+
include Glimmer
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def local_dir
|
10
|
+
@local_dir ||= new(ENV['LOCAL_DIR'] || '.').tap do |dir|
|
11
|
+
dir.refresh
|
12
|
+
@filewatcher = Filewatcher.new(dir.path)
|
13
|
+
@thread = Thread.new(@filewatcher) do |fw|
|
14
|
+
fw.watch do |filename, event|
|
15
|
+
if @last_update.nil? || (Time.now.to_f - @last_update) > 10
|
16
|
+
dir.refresh if filename != dir.selected_child_path
|
17
|
+
end
|
18
|
+
@last_update = Time.now.to_f
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
attr_accessor :selected_child, :filter, :children, :filtered_path_options
|
26
|
+
attr_reader :path, :display_path
|
27
|
+
|
28
|
+
def initialize(path)
|
29
|
+
@path = @display_path = path
|
30
|
+
self.filtered_path_options = []
|
31
|
+
end
|
32
|
+
|
33
|
+
def children
|
34
|
+
@children ||= retrieve_children
|
35
|
+
end
|
36
|
+
|
37
|
+
def retrieve_children
|
38
|
+
::Dir.glob(::File.join(@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 }
|
39
|
+
end
|
40
|
+
|
41
|
+
def refresh
|
42
|
+
new_all_children = retrieve_all_children
|
43
|
+
new_children = retrieve_children
|
44
|
+
async_exec do
|
45
|
+
@all_children = new_all_children
|
46
|
+
@children ||= []
|
47
|
+
@children.clear
|
48
|
+
new_children.each do |child|
|
49
|
+
@children << child
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def filter=(value)
|
55
|
+
if value.to_s.empty?
|
56
|
+
@filter = nil
|
57
|
+
else
|
58
|
+
@filter = value
|
59
|
+
end
|
60
|
+
self.filtered_path_options = filtered.to_a.map(&:display_path)
|
61
|
+
end
|
62
|
+
|
63
|
+
def filtered
|
64
|
+
return if filter.nil?
|
65
|
+
all_children_files.select do |child|
|
66
|
+
child.path.downcase.include?(filter.downcase) ||
|
67
|
+
child.path.downcase.gsub(/[_\/]/, '').include?(filter.downcase)
|
68
|
+
end.sort_by {|c| c.path.to_s.downcase}
|
69
|
+
end
|
70
|
+
|
71
|
+
def all_children
|
72
|
+
@all_children ||= retrieve_all_children
|
73
|
+
end
|
74
|
+
|
75
|
+
def retrieve_all_children
|
76
|
+
::Dir.glob(::File.join(@path, '**', '*')).map {|p| ::File.file?(p) ? Gladiator::File.new(p) : Gladiator::Dir.new(p)}
|
77
|
+
end
|
78
|
+
|
79
|
+
def all_children_files
|
80
|
+
all_children.select {|child| child.is_a?(Gladiator::File) }
|
81
|
+
end
|
82
|
+
|
83
|
+
def selected_child_path=(selected_path)
|
84
|
+
if selected_path && ::File.file?(selected_path)
|
85
|
+
@selected_child&.write_dirty_content
|
86
|
+
new_child = Gladiator::File.new(selected_path)
|
87
|
+
begin
|
88
|
+
unless new_child.dirty_content.nil?
|
89
|
+
self.selected_child&.stop_filewatcher
|
90
|
+
self.selected_child = new_child
|
91
|
+
self.selected_child.start_filewatcher
|
92
|
+
end
|
93
|
+
rescue
|
94
|
+
# no op
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def selected_child_path
|
100
|
+
@selected_child&.path
|
101
|
+
end
|
102
|
+
|
103
|
+
alias filtered_path selected_child_path
|
104
|
+
alias filtered_path= selected_child_path=
|
105
|
+
|
106
|
+
def to_s
|
107
|
+
path
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
at_exit do
|
114
|
+
Glimmer::Gladiator::Dir.local_dir.selected_child&.write_raw_dirty_content
|
115
|
+
end
|
116
|
+
|
@@ -0,0 +1,357 @@
|
|
1
|
+
require 'models/glimmer/gladiator/dir'
|
2
|
+
|
3
|
+
module Glimmer
|
4
|
+
class Gladiator
|
5
|
+
class File
|
6
|
+
include Glimmer
|
7
|
+
|
8
|
+
attr_accessor :dirty_content, :line_numbers_content, :caret_position, :selection_count, :line_number, :find_text, :replace_text, :top_index
|
9
|
+
attr_reader :path, :display_path
|
10
|
+
|
11
|
+
def initialize(path)
|
12
|
+
raise "Not a file path: #{path}" unless ::File.file?(path)
|
13
|
+
@display_path = path
|
14
|
+
@path = ::File.expand_path(path)
|
15
|
+
read_dirty_content = ::File.read(path)
|
16
|
+
begin
|
17
|
+
# test read dirty content
|
18
|
+
read_dirty_content.split("\n")
|
19
|
+
observe(self, :dirty_content) do
|
20
|
+
lines_text_size = lines.size.to_s.size
|
21
|
+
self.line_numbers_content = lines.size.times.map {|n| (' ' * (lines_text_size - (n+1).to_s.size)) + (n+1).to_s }.join("\n")
|
22
|
+
end
|
23
|
+
self.dirty_content = read_dirty_content
|
24
|
+
observe(self, :caret_position) do
|
25
|
+
self.line_number = line_index_for_caret_position(caret_position) + 1
|
26
|
+
end
|
27
|
+
observe(self, :line_number) do
|
28
|
+
if line_number
|
29
|
+
new_caret_position = lines[0...(line_number.to_i - 1)].map(&:size).sum + line_number.to_i - 1
|
30
|
+
self.caret_position = new_caret_position unless line_index_for_caret_position(new_caret_position) == line_index_for_caret_position(caret_position)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
rescue
|
34
|
+
# no op in case of a binary file
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def start_filewatcher
|
39
|
+
@filewatcher = Filewatcher.new(@path)
|
40
|
+
@thread = Thread.new(@filewatcher) do |fw|
|
41
|
+
fw.watch do |filename, event|
|
42
|
+
begin
|
43
|
+
read_dirty_content = ::File.read(path)
|
44
|
+
# test read dirty content
|
45
|
+
read_dirty_content.split("\n")
|
46
|
+
async_exec do
|
47
|
+
self.dirty_content = read_dirty_content if read_dirty_content != dirty_content
|
48
|
+
end
|
49
|
+
rescue
|
50
|
+
# no op in case of a binary file
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def stop_filewatcher
|
57
|
+
@filewatcher&.stop
|
58
|
+
end
|
59
|
+
|
60
|
+
def write_dirty_content
|
61
|
+
new_dirty_content = "#{dirty_content.gsub("\r\n", "\n").gsub("\r", "\n").sub(/\n+\z/, '')}\n"
|
62
|
+
self.dirty_content = new_dirty_content if new_dirty_content != self.dirty_content
|
63
|
+
::File.write(path, dirty_content) if ::File.exists?(path) && dirty_content.to_s.strip.size > 0
|
64
|
+
end
|
65
|
+
|
66
|
+
def write_raw_dirty_content
|
67
|
+
::File.write(path, dirty_content) if ::File.exists?(path) && dirty_content.to_s.strip.size > 0
|
68
|
+
end
|
69
|
+
|
70
|
+
def comment_line!
|
71
|
+
old_lines = lines
|
72
|
+
return if old_lines.size < 1
|
73
|
+
old_selection_count = self.selection_count
|
74
|
+
old_caret_position = self.caret_position
|
75
|
+
old_caret_position_line_index = line_index_for_caret_position(old_caret_position)
|
76
|
+
old_caret_position_line_caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
77
|
+
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
78
|
+
new_lines = lines
|
79
|
+
delta = 0
|
80
|
+
line_indices_for_selection(caret_position, selection_count).reverse.each do | the_line_index |
|
81
|
+
delta = 0
|
82
|
+
the_line = old_lines[the_line_index]
|
83
|
+
if the_line.strip.start_with?('# ')
|
84
|
+
new_lines[the_line_index] = the_line.sub(/# /, '')
|
85
|
+
delta -= 2
|
86
|
+
elsif the_line.strip.start_with?('#')
|
87
|
+
new_lines[the_line_index] = the_line.sub(/#/, '')
|
88
|
+
delta -= 1
|
89
|
+
else
|
90
|
+
new_lines[the_line_index] = "# #{the_line}"
|
91
|
+
delta += 2
|
92
|
+
end
|
93
|
+
end
|
94
|
+
self.dirty_content = new_lines.join("\n")
|
95
|
+
if old_selection_count > 0
|
96
|
+
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
97
|
+
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
98
|
+
else
|
99
|
+
new_caret_position = old_caret_position + delta
|
100
|
+
new_caret_position = [new_caret_position, old_caret_position_line_caret_position].max
|
101
|
+
self.caret_position = new_caret_position
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def indent!
|
106
|
+
new_lines = lines
|
107
|
+
old_lines = lines
|
108
|
+
return if old_lines.size < 1
|
109
|
+
old_selection_count = self.selection_count
|
110
|
+
old_caret_position = self.caret_position
|
111
|
+
old_caret_position_line_index = line_index_for_caret_position(old_caret_position)
|
112
|
+
old_caret_position_line_caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
113
|
+
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
114
|
+
delta = 2
|
115
|
+
line_indices_for_selection(caret_position, selection_count).each do |the_line_index|
|
116
|
+
the_line = old_lines[the_line_index]
|
117
|
+
new_lines[the_line_index] = " #{the_line}"
|
118
|
+
end
|
119
|
+
old_caret_position = self.caret_position
|
120
|
+
self.dirty_content = new_lines.join("\n")
|
121
|
+
if old_selection_count > 0
|
122
|
+
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
123
|
+
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
124
|
+
else
|
125
|
+
self.caret_position = old_caret_position + delta
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def outdent!
|
130
|
+
new_lines = lines
|
131
|
+
old_lines = lines
|
132
|
+
return if old_lines.size < 1
|
133
|
+
old_selection_count = self.selection_count
|
134
|
+
old_caret_position = self.caret_position
|
135
|
+
old_caret_position_line_index = line_index_for_caret_position(old_caret_position)
|
136
|
+
old_caret_position_line_caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
137
|
+
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
138
|
+
delta = 0
|
139
|
+
line_indices_for_selection(caret_position, selection_count).each do |the_line_index|
|
140
|
+
the_line = old_lines[the_line_index]
|
141
|
+
if the_line.start_with?(' ')
|
142
|
+
new_lines[the_line_index] = the_line.sub(/ /, '')
|
143
|
+
delta = -2
|
144
|
+
elsif the_line.start_with?(' ')
|
145
|
+
new_lines[the_line_index] = the_line.sub(/ /, '')
|
146
|
+
delta = -1
|
147
|
+
end
|
148
|
+
end
|
149
|
+
self.dirty_content = new_lines.join("\n")
|
150
|
+
if old_selection_count > 0
|
151
|
+
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
152
|
+
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
153
|
+
else
|
154
|
+
new_caret_position = old_caret_position + delta
|
155
|
+
new_caret_position = [new_caret_position, old_caret_position_line_caret_position].max
|
156
|
+
self.caret_position = new_caret_position
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def kill_line!
|
161
|
+
new_lines = lines
|
162
|
+
return if new_lines.size < 2
|
163
|
+
line_indices = line_indices_for_selection(caret_position, selection_count)
|
164
|
+
new_lines = new_lines[0...line_indices.first] + new_lines[(line_indices.last+1)...new_lines.size]
|
165
|
+
old_caret_position = self.caret_position
|
166
|
+
self.dirty_content = new_lines.join("\n")
|
167
|
+
self.caret_position = old_caret_position
|
168
|
+
end
|
169
|
+
|
170
|
+
def duplicate_line!
|
171
|
+
new_lines = lines
|
172
|
+
old_lines = lines
|
173
|
+
return if old_lines.size < 1
|
174
|
+
old_selection_count = self.selection_count
|
175
|
+
old_caret_position = self.caret_position
|
176
|
+
old_caret_position_line_index = line_index_for_caret_position(old_caret_position)
|
177
|
+
old_caret_position_line_caret_position = caret_position_for_caret_position_start_of_line(old_caret_position_line_index)
|
178
|
+
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
179
|
+
the_line_indices = line_indices_for_selection(caret_position, selection_count)
|
180
|
+
the_lines = lines_for_selection(caret_position, selection_count)
|
181
|
+
delta = the_lines.join("\n").size + 1
|
182
|
+
the_lines.each_with_index do |the_line, i|
|
183
|
+
new_lines.insert(the_line_indices.first + i, the_line)
|
184
|
+
end
|
185
|
+
self.dirty_content = new_lines.join("\n")
|
186
|
+
if old_selection_count > 0
|
187
|
+
self.caret_position = caret_position_for_line_index(old_caret_position_line_index)
|
188
|
+
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
189
|
+
else
|
190
|
+
self.caret_position = old_caret_position + delta
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def find_next
|
195
|
+
return if find_text.to_s.empty?
|
196
|
+
all_lines = lines
|
197
|
+
the_line_index = line_index_for_caret_position(caret_position)
|
198
|
+
all_lines.rotate(the_line_index + 1).each_with_index do |the_line, the_index|
|
199
|
+
the_index = (the_index + the_line_index + 1)%all_lines.size
|
200
|
+
if the_line.downcase.include?(find_text.to_s.downcase)
|
201
|
+
self.caret_position = the_line.downcase.index(find_text.to_s.downcase) + caret_position_for_line_index(the_index)
|
202
|
+
self.selection_count = find_text.to_s.size
|
203
|
+
return
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def find_previous
|
209
|
+
return if find_text.to_s.empty?
|
210
|
+
all_lines = lines
|
211
|
+
the_line_index = line_index_for_caret_position(caret_position)
|
212
|
+
all_lines.rotate(the_line_index).each_with_index.map do |the_line, the_index|
|
213
|
+
the_index = (the_index + the_line_index)%all_lines.size
|
214
|
+
[the_line, the_index]
|
215
|
+
end.reverse.each do |the_line, the_index|
|
216
|
+
if the_line.downcase.include?(find_text.to_s.downcase)
|
217
|
+
self.caret_position = the_line.downcase.index(find_text.to_s.downcase) + caret_position_for_line_index(the_index)
|
218
|
+
self.selection_count = find_text.to_s.size
|
219
|
+
return
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def ensure_find_next
|
225
|
+
return if find_text.to_s.empty? || dirty_content.to_s.strip.size < 1
|
226
|
+
find_next unless dirty_content[caret_position.to_i, find_text.to_s.size] == find_text
|
227
|
+
end
|
228
|
+
|
229
|
+
def replace_next!
|
230
|
+
return if find_text.to_s.empty? || dirty_content.to_s.strip.size < 1
|
231
|
+
ensure_find_next
|
232
|
+
new_dirty_content = dirty_content
|
233
|
+
new_dirty_content[caret_position, find_text.size] = replace_text.to_s
|
234
|
+
self.dirty_content = new_dirty_content
|
235
|
+
find_next
|
236
|
+
end
|
237
|
+
|
238
|
+
def page_up
|
239
|
+
self.line_number = [(self.line_number - 15), 1].max
|
240
|
+
end
|
241
|
+
|
242
|
+
def page_down
|
243
|
+
self.line_number = [(self.line_number + 15), lines.size].min
|
244
|
+
end
|
245
|
+
|
246
|
+
def home
|
247
|
+
self.line_number = 1
|
248
|
+
end
|
249
|
+
|
250
|
+
def end
|
251
|
+
self.line_number = lines.size
|
252
|
+
end
|
253
|
+
|
254
|
+
def move_up!
|
255
|
+
old_lines = lines
|
256
|
+
return if old_lines.size < 2
|
257
|
+
old_selection_count = self.selection_count
|
258
|
+
old_caret_position = self.caret_position
|
259
|
+
old_caret_position_line_index = line_index_for_caret_position(old_caret_position)
|
260
|
+
old_caret_position_line_caret_position = caret_position_for_caret_position_start_of_line(old_caret_position_line_index)
|
261
|
+
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
262
|
+
new_lines = lines
|
263
|
+
the_line_indices = line_indices_for_selection(caret_position, selection_count)
|
264
|
+
the_lines = lines_for_selection(caret_position, selection_count)
|
265
|
+
new_line_index = [the_line_indices.first - 1, 0].max
|
266
|
+
delta = -1 * (new_lines[new_line_index].size + 1)
|
267
|
+
new_lines[the_line_indices.first..the_line_indices.last] = []
|
268
|
+
new_lines[new_line_index...new_line_index] = the_lines
|
269
|
+
self.dirty_content = new_lines.join("\n")
|
270
|
+
if old_selection_count > 0
|
271
|
+
self.caret_position = caret_position_for_line_index(old_caret_position_line_index) + delta
|
272
|
+
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position + delta)
|
273
|
+
else
|
274
|
+
self.caret_position = old_caret_position + delta
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def move_down!
|
279
|
+
old_lines = lines
|
280
|
+
return if old_lines.size < 2
|
281
|
+
old_selection_count = self.selection_count
|
282
|
+
old_caret_position = self.caret_position
|
283
|
+
old_caret_position_line_index = line_index_for_caret_position(old_caret_position)
|
284
|
+
old_caret_position_line_caret_position = caret_position_for_caret_position_start_of_line(old_caret_position_line_index)
|
285
|
+
old_end_caret_line_index = end_caret_position_line_index(caret_position, selection_count)
|
286
|
+
new_lines = lines
|
287
|
+
the_line_indices = line_indices_for_selection(caret_position, selection_count)
|
288
|
+
the_lines = lines_for_selection(caret_position, selection_count)
|
289
|
+
new_line_index = [the_line_indices.first + 1, new_lines.size - 1].min
|
290
|
+
delta = new_lines[new_line_index].size + 1
|
291
|
+
new_lines[the_line_indices.first..the_line_indices.last] = []
|
292
|
+
new_lines[new_line_index...new_line_index] = the_lines
|
293
|
+
self.dirty_content = new_lines.join("\n")
|
294
|
+
if old_selection_count > 0
|
295
|
+
self.caret_position = caret_position_for_line_index(old_caret_position_line_index) + delta
|
296
|
+
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position + delta)
|
297
|
+
else
|
298
|
+
self.caret_position = old_caret_position + delta
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
def lines
|
303
|
+
dirty_content.split("\n")
|
304
|
+
end
|
305
|
+
|
306
|
+
def line_for_caret_position(caret_position)
|
307
|
+
lines[line_index_for_caret_position(caret_position.to_i)]
|
308
|
+
end
|
309
|
+
|
310
|
+
def line_index_for_caret_position(caret_position)
|
311
|
+
dirty_content[0...caret_position.to_i].count("\n")
|
312
|
+
end
|
313
|
+
|
314
|
+
def caret_position_for_line_index(line_index)
|
315
|
+
lines[0...line_index].join("\n").size + 1
|
316
|
+
end
|
317
|
+
|
318
|
+
def caret_position_for_caret_position_start_of_line(caret_position)
|
319
|
+
caret_position_for_line_index(line_index_for_caret_position(caret_position))
|
320
|
+
end
|
321
|
+
|
322
|
+
def line_caret_positions_for_selection(caret_position, selection_count)
|
323
|
+
line_indices = line_indices_for_selection(caret_position, selection_count)
|
324
|
+
line_caret_positions = line_indices.map { |line_index| caret_position_for_line_index(line_index) }.to_a
|
325
|
+
end
|
326
|
+
|
327
|
+
def end_caret_position_line_index(caret_position, selection_count)
|
328
|
+
end_caret_position = caret_position + selection_count.to_i
|
329
|
+
end_caret_position -= 1 if dirty_content[end_caret_position - 1] == "\n"
|
330
|
+
end_line_index = line_index_for_caret_position(end_caret_position)
|
331
|
+
end
|
332
|
+
|
333
|
+
def lines_for_selection(caret_position, selection_count)
|
334
|
+
line_indices = line_indices_for_selection(caret_position, selection_count)
|
335
|
+
lines[line_indices.first..line_indices.last]
|
336
|
+
end
|
337
|
+
|
338
|
+
def line_indices_for_selection(caret_position, selection_count)
|
339
|
+
start_line_index = line_index_for_caret_position(caret_position)
|
340
|
+
if selection_count.to_i > 0
|
341
|
+
end_line_index = end_caret_position_line_index(caret_position, selection_count)
|
342
|
+
else
|
343
|
+
end_line_index = start_line_index
|
344
|
+
end
|
345
|
+
(start_line_index..end_line_index).to_a
|
346
|
+
end
|
347
|
+
|
348
|
+
def children
|
349
|
+
[]
|
350
|
+
end
|
351
|
+
|
352
|
+
def to_s
|
353
|
+
path
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
@@ -0,0 +1,319 @@
|
|
1
|
+
require 'models/glimmer/gladiator/dir'
|
2
|
+
require 'models/glimmer/gladiator/file'
|
3
|
+
|
4
|
+
Clipboard.implementation = Clipboard::Java
|
5
|
+
Clipboard.copy(Clipboard.paste) # pre-initialize library to avoid slowdown during use
|
6
|
+
|
7
|
+
module Glimmer
|
8
|
+
# Gladiator (Glimmer Editor)
|
9
|
+
class Gladiator
|
10
|
+
include Glimmer::UI::CustomShell
|
11
|
+
|
12
|
+
## Add options like the following to configure CustomShell by outside consumers
|
13
|
+
#
|
14
|
+
# options :title, :background_color
|
15
|
+
# option :width, 320
|
16
|
+
# option :height, 240
|
17
|
+
|
18
|
+
## Uncomment before_body block to pre-initialize variables to use in body
|
19
|
+
#
|
20
|
+
#
|
21
|
+
before_body {
|
22
|
+
Display.setAppName('Gladiator')
|
23
|
+
@config_file_path = '.gladiator'
|
24
|
+
@config = {}
|
25
|
+
Gladiator::Dir.local_dir.all_children # pre-caches children
|
26
|
+
load_config
|
27
|
+
@display = display {
|
28
|
+
on_event_keydown { |key_event|
|
29
|
+
if Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'f'
|
30
|
+
if @text.swt_widget.getSelectionText && @text.swt_widget.getSelectionText.size > 0
|
31
|
+
@find_text.swt_widget.setText @text.swt_widget.getSelectionText
|
32
|
+
end
|
33
|
+
@find_text.swt_widget.selectAll
|
34
|
+
@find_text.swt_widget.setFocus
|
35
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == 'c'
|
36
|
+
Clipboard.copy(Gladiator::Dir.local_dir.selected_child.path)
|
37
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == 'g'
|
38
|
+
Gladiator::Dir.local_dir.selected_child.find_previous
|
39
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'g'
|
40
|
+
Gladiator::Dir.local_dir.selected_child.find_next
|
41
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'l'
|
42
|
+
@line_number_text.swt_widget.selectAll
|
43
|
+
@line_number_text.swt_widget.setFocus
|
44
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'r'
|
45
|
+
@filter_text.swt_widget.selectAll
|
46
|
+
@filter_text.swt_widget.setFocus
|
47
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 't'
|
48
|
+
@tree.swt_widget.setFocus
|
49
|
+
end
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
## Uncomment after_body block to setup observers for widgets in body
|
55
|
+
#
|
56
|
+
after_body {
|
57
|
+
observe(Gladiator::Dir.local_dir, 'selected_child.line_numbers_content') do
|
58
|
+
if @last_line_numbers_content != Gladiator::Dir.local_dir.selected_child.line_numbers_content
|
59
|
+
body_root.pack_same_size
|
60
|
+
@last_line_numbers_content = Gladiator::Dir.local_dir.selected_child.line_numbers_content
|
61
|
+
end
|
62
|
+
end
|
63
|
+
observe(Gladiator::Dir.local_dir, 'selected_child.caret_position') do
|
64
|
+
save_config
|
65
|
+
end
|
66
|
+
observe(Gladiator::Dir.local_dir, 'selected_child.top_index') do
|
67
|
+
save_config
|
68
|
+
end
|
69
|
+
}
|
70
|
+
|
71
|
+
## Add widget content inside custom shell body
|
72
|
+
## Top-most widget must be a shell or another custom shell
|
73
|
+
#
|
74
|
+
body {
|
75
|
+
shell {
|
76
|
+
text "Gladiator - #{::File.expand_path(Gladiator::Dir.local_dir.path)}"
|
77
|
+
minimum_size 720, 450
|
78
|
+
size 1440, 900
|
79
|
+
grid_layout 2, false
|
80
|
+
on_event_close {
|
81
|
+
Gladiator::Dir.local_dir.selected_child&.write_dirty_content
|
82
|
+
}
|
83
|
+
on_widget_disposed {
|
84
|
+
Gladiator::Dir.local_dir.selected_child&.write_dirty_content
|
85
|
+
}
|
86
|
+
composite {
|
87
|
+
grid_layout 1, false
|
88
|
+
layout_data(:fill, :fill, false, true) {
|
89
|
+
width_hint 300
|
90
|
+
}
|
91
|
+
@filter_text = text {
|
92
|
+
layout_data :fill, :center, true, false
|
93
|
+
text bind(Gladiator::Dir.local_dir, 'filter')
|
94
|
+
on_key_pressed { |key_event|
|
95
|
+
if key_event.keyCode == swt(:tab) ||
|
96
|
+
key_event.keyCode == swt(:cr) ||
|
97
|
+
key_event.keyCode == swt(:lf) ||
|
98
|
+
key_event.keyCode == swt(:arrow_up) ||
|
99
|
+
key_event.keyCode == swt(:arrow_down)
|
100
|
+
@list.swt_widget.setFocus
|
101
|
+
elsif key_event.keyCode == swt(:esc)
|
102
|
+
@text.swt_widget.setFocus
|
103
|
+
end
|
104
|
+
}
|
105
|
+
}
|
106
|
+
composite {
|
107
|
+
layout_data(:fill, :fill, true, true)
|
108
|
+
@list = list(:border, :h_scroll, :v_scroll) {
|
109
|
+
layout_data(:fill, :fill, true, true) {
|
110
|
+
#exclude bind(Gladiator::Dir.local_dir, :filter) {|f| !f}
|
111
|
+
}
|
112
|
+
#visible bind(Gladiator::Dir, 'local_dir.filter') {|f| !!f}
|
113
|
+
selection bind(Gladiator::Dir.local_dir, :filtered_path)
|
114
|
+
on_widget_selected {
|
115
|
+
Gladiator::Dir.local_dir.selected_child_path = @list.swt_widget.getSelection.first
|
116
|
+
}
|
117
|
+
on_key_pressed { |key_event|
|
118
|
+
if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr) || Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :lf)
|
119
|
+
Gladiator::Dir.local_dir.selected_child_path = @list.swt_widget.getSelection.first
|
120
|
+
@text.swt_widget.setFocus
|
121
|
+
end
|
122
|
+
}
|
123
|
+
}
|
124
|
+
@tree = tree(:virtual, :border, :h_scroll, :v_scroll) {
|
125
|
+
layout_data(:fill, :fill, true, true) {
|
126
|
+
#exclude bind(Gladiator::Dir.local_dir, :filter) {|f| !!f}
|
127
|
+
}
|
128
|
+
#visible bind(Gladiator::Dir, 'local_dir.filter') {|f| !f}
|
129
|
+
items bind(Gladiator::Dir, :local_dir), tree_properties(children: :children, text: :display_path)
|
130
|
+
on_widget_selected {
|
131
|
+
Gladiator::Dir.local_dir.selected_child_path = @tree.swt_widget.getSelection.first.getText
|
132
|
+
}
|
133
|
+
on_key_pressed { |key_event|
|
134
|
+
if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr) || Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :lf)
|
135
|
+
Gladiator::Dir.local_dir.selected_child_path = @tree.swt_widget.getSelection.first.getText
|
136
|
+
@text.swt_widget.setFocus
|
137
|
+
end
|
138
|
+
}
|
139
|
+
on_paint_control {
|
140
|
+
root_item = @tree.swt_widget.getItems.first
|
141
|
+
if root_item && !root_item.getExpanded
|
142
|
+
root_item.setExpanded true
|
143
|
+
end
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
composite {
|
149
|
+
grid_layout 1, false
|
150
|
+
layout_data :fill, :fill, true, true
|
151
|
+
composite {
|
152
|
+
grid_layout 2, false
|
153
|
+
@file_path_label = styled_text(:none) {
|
154
|
+
layout_data(:fill, :fill, true, false) {
|
155
|
+
horizontal_span 2
|
156
|
+
}
|
157
|
+
background color(:widget_background)
|
158
|
+
editable false
|
159
|
+
caret nil
|
160
|
+
text bind(Gladiator::Dir.local_dir, 'selected_child.path')
|
161
|
+
on_mouse_up {
|
162
|
+
@file_path_label.swt_widget.selectAll
|
163
|
+
}
|
164
|
+
on_focus_lost {
|
165
|
+
@file_path_label.swt_widget.setSelection(0, 0)
|
166
|
+
}
|
167
|
+
}
|
168
|
+
label {
|
169
|
+
text 'Line:'
|
170
|
+
}
|
171
|
+
@line_number_text = text {
|
172
|
+
layout_data(:fill, :fill, true, false) {
|
173
|
+
minimum_width 300
|
174
|
+
}
|
175
|
+
text bind(Gladiator::Dir.local_dir, 'selected_child.line_number', on_read: :to_s, on_write: :to_i)
|
176
|
+
on_key_pressed { |key_event|
|
177
|
+
if key_event.keyCode == swt(:cr)
|
178
|
+
@text.swt_widget.setFocus
|
179
|
+
end
|
180
|
+
}
|
181
|
+
}
|
182
|
+
label {
|
183
|
+
text 'Find:'
|
184
|
+
}
|
185
|
+
@find_text = text {
|
186
|
+
layout_data(:fill, :fill, true, false) {
|
187
|
+
minimum_width 200
|
188
|
+
}
|
189
|
+
text bind(Gladiator::Dir.local_dir, 'selected_child.find_text')
|
190
|
+
on_key_pressed { |key_event|
|
191
|
+
if key_event.keyCode == swt(:cr)
|
192
|
+
Gladiator::Dir.local_dir.selected_child.find_next
|
193
|
+
elsif key_event.keyCode == swt(:esc)
|
194
|
+
@text.swt_widget.setFocus
|
195
|
+
end
|
196
|
+
}
|
197
|
+
}
|
198
|
+
label {
|
199
|
+
text 'Replace:'
|
200
|
+
}
|
201
|
+
@replace_text = text {
|
202
|
+
layout_data(:fill, :fill, true, false) {
|
203
|
+
minimum_width 200
|
204
|
+
}
|
205
|
+
text bind(Gladiator::Dir.local_dir, 'selected_child.replace_text')
|
206
|
+
on_focus_gained {
|
207
|
+
Gladiator::Dir.local_dir.selected_child.ensure_find_next
|
208
|
+
}
|
209
|
+
on_key_pressed { |key_event|
|
210
|
+
if key_event.keyCode == swt(:cr)
|
211
|
+
Gladiator::Dir.local_dir.selected_child.replace_next!
|
212
|
+
elsif key_event.keyCode == swt(:esc)
|
213
|
+
@text.swt_widget.setFocus
|
214
|
+
end
|
215
|
+
}
|
216
|
+
}
|
217
|
+
}
|
218
|
+
composite {
|
219
|
+
layout_data :fill, :fill, true, true
|
220
|
+
grid_layout 2, false
|
221
|
+
@line_numbers_text = text(:multi) {
|
222
|
+
layout_data(:right, :fill, false, true)
|
223
|
+
font name: 'Consolas', height: 15
|
224
|
+
background color(:widget_background)
|
225
|
+
foreground rgb(75, 75, 75)
|
226
|
+
text bind(Gladiator::Dir.local_dir, 'selected_child.line_numbers_content')
|
227
|
+
top_index bind(Gladiator::Dir.local_dir, 'selected_child.top_index')
|
228
|
+
on_focus_gained {
|
229
|
+
@text&.swt_widget.setFocus
|
230
|
+
}
|
231
|
+
on_key_pressed {
|
232
|
+
@text&.swt_widget.setFocus
|
233
|
+
}
|
234
|
+
on_mouse_up {
|
235
|
+
@text&.swt_widget.setFocus
|
236
|
+
}
|
237
|
+
}
|
238
|
+
@text = text(:multi, :border, :h_scroll, :v_scroll) {
|
239
|
+
layout_data :fill, :fill, true, true
|
240
|
+
font name: 'Consolas', height: 15
|
241
|
+
foreground rgb(75, 75, 75)
|
242
|
+
text bind(Gladiator::Dir.local_dir, 'selected_child.dirty_content')
|
243
|
+
focus true
|
244
|
+
caret_position bind(Gladiator::Dir.local_dir, 'selected_child.caret_position')
|
245
|
+
selection_count bind(Gladiator::Dir.local_dir, 'selected_child.selection_count')
|
246
|
+
top_index bind(Gladiator::Dir.local_dir, 'selected_child.top_index')
|
247
|
+
on_focus_lost {
|
248
|
+
Gladiator::Dir.local_dir.selected_child&.write_dirty_content
|
249
|
+
}
|
250
|
+
on_key_pressed { |key_event|
|
251
|
+
if Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '/'
|
252
|
+
Gladiator::Dir.local_dir.selected_child.comment_line!
|
253
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'k'
|
254
|
+
Gladiator::Dir.local_dir.selected_child.kill_line!
|
255
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'd'
|
256
|
+
Gladiator::Dir.local_dir.selected_child.duplicate_line!
|
257
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '['
|
258
|
+
Gladiator::Dir.local_dir.selected_child.outdent!
|
259
|
+
elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == ']'
|
260
|
+
Gladiator::Dir.local_dir.selected_child.indent!
|
261
|
+
elsif key_event.keyCode == swt(:page_up)
|
262
|
+
Gladiator::Dir.local_dir.selected_child.page_up
|
263
|
+
key_event.doit = false
|
264
|
+
elsif key_event.keyCode == swt(:page_down)
|
265
|
+
Gladiator::Dir.local_dir.selected_child.page_down
|
266
|
+
key_event.doit = false
|
267
|
+
elsif key_event.keyCode == swt(:home)
|
268
|
+
Gladiator::Dir.local_dir.selected_child.home
|
269
|
+
key_event.doit = false
|
270
|
+
elsif key_event.keyCode == swt(:end)
|
271
|
+
Gladiator::Dir.local_dir.selected_child.end
|
272
|
+
key_event.doit = false
|
273
|
+
elsif key_event.stateMask == swt(:command) && key_event.keyCode == swt(:arrow_up)
|
274
|
+
Gladiator::Dir.local_dir.selected_child.move_up!
|
275
|
+
key_event.doit = false
|
276
|
+
elsif key_event.stateMask == swt(:command) && key_event.keyCode == swt(:arrow_down)
|
277
|
+
Gladiator::Dir.local_dir.selected_child.move_down!
|
278
|
+
key_event.doit = false
|
279
|
+
end
|
280
|
+
}
|
281
|
+
on_verify_text { |verify_event|
|
282
|
+
key_code = verify_event.keyCode
|
283
|
+
case key_code
|
284
|
+
when swt(:tab)
|
285
|
+
verify_event.text = ' '
|
286
|
+
end
|
287
|
+
}
|
288
|
+
}
|
289
|
+
}
|
290
|
+
}
|
291
|
+
}
|
292
|
+
}
|
293
|
+
|
294
|
+
def load_config
|
295
|
+
if ::File.exists?(@config_file_path)
|
296
|
+
config_yaml = ::File.read(@config_file_path)
|
297
|
+
return if config_yaml.to_s.strip.empty?
|
298
|
+
@config = YAML.load(config_yaml)
|
299
|
+
Gladiator::Dir.local_dir.selected_child_path = @config[:selected_child_path] if @config[:selected_child_path]
|
300
|
+
Gladiator::Dir.local_dir.selected_child&.caret_position = Gladiator::Dir.local_dir.selected_child&.caret_position_for_caret_position_start_of_line(@config[:caret_position]) if @config[:caret_position]
|
301
|
+
Gladiator::Dir.local_dir.selected_child&.top_index = @config[:top_index] if @config[:top_index]
|
302
|
+
end
|
303
|
+
end
|
304
|
+
|
305
|
+
def save_config
|
306
|
+
child = Gladiator::Dir.local_dir.selected_child
|
307
|
+
return if child.nil?
|
308
|
+
@config = {
|
309
|
+
selected_child_path: child.path,
|
310
|
+
caret_position: child.caret_position,
|
311
|
+
top_index: child.top_index,
|
312
|
+
}
|
313
|
+
config_yaml = YAML.dump(@config)
|
314
|
+
::File.write(@config_file_path, config_yaml) unless config_yaml.to_s.empty?
|
315
|
+
rescue => e
|
316
|
+
puts e.full_message
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: glimmer-cs-gladiator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andy Maleh
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-05-03 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
15
|
+
requirements:
|
16
|
+
- - "~>"
|
17
|
+
- !ruby/object:Gem::Version
|
18
|
+
version: 0.7.0
|
19
|
+
name: glimmer
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.7.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
29
|
+
requirements:
|
30
|
+
- - "~>"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.1.1
|
33
|
+
name: filewatcher
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.1.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 1.3.4
|
47
|
+
name: clipboard
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.3.4
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 3.5.0
|
61
|
+
name: rspec
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.5.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: 2.3.9
|
75
|
+
name: jeweler
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.3.9
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
name: simplecov
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Gladiator (short for Glimmer Editor) is a Glimmer sample project under
|
98
|
+
on-going development. It is not intended to be a full-fledged editor by any means,
|
99
|
+
yet mostly a fun educational exercise in using Glimmer to build a text editor. Gladiator
|
100
|
+
is also a personal tool for shaping an editor exactly the way I like. I leave building
|
101
|
+
truly professional text editors to software tooling experts who would hopefully
|
102
|
+
use Glimmer one day.
|
103
|
+
email: andy.am@gmail.com
|
104
|
+
executables:
|
105
|
+
- gladiator
|
106
|
+
extensions: []
|
107
|
+
extra_rdoc_files:
|
108
|
+
- LICENSE.txt
|
109
|
+
- README.md
|
110
|
+
files:
|
111
|
+
- LICENSE.txt
|
112
|
+
- README.md
|
113
|
+
- bin/gladiator
|
114
|
+
- bin/gladiator_runner.rb
|
115
|
+
- lib/glimmer-cs-gladiator.rb
|
116
|
+
- lib/models/glimmer/gladiator/dir.rb
|
117
|
+
- lib/models/glimmer/gladiator/file.rb
|
118
|
+
- lib/views/glimmer/gladiator.rb
|
119
|
+
homepage: http://github.com/AndyObtiva/glimmer-cs-gladiator
|
120
|
+
licenses:
|
121
|
+
- MIT
|
122
|
+
metadata: {}
|
123
|
+
post_install_message:
|
124
|
+
rdoc_options: []
|
125
|
+
require_paths:
|
126
|
+
- lib
|
127
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
requirements: []
|
138
|
+
rubygems_version: 3.0.6
|
139
|
+
signing_key:
|
140
|
+
specification_version: 4
|
141
|
+
summary: Gladiator (Glimmer Editor) - Glimmer Custom Shell
|
142
|
+
test_files: []
|