glimmer-cs-gladiator 0.5.2 → 0.6.2
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 +56 -27
- data/VERSION +1 -1
- data/lib/models/glimmer/gladiator/command.rb +41 -8
- data/lib/models/glimmer/gladiator/dir.rb +44 -16
- data/lib/models/glimmer/gladiator/file.rb +133 -69
- data/lib/views/glimmer/gladiator.rb +585 -249
- data/lib/views/glimmer/gladiator/text_editor.rb +123 -95
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c07882b7fc3a12df1d64f02148ac6d018c1edd45fdea10c6d5285bdd55df137
|
4
|
+
data.tar.gz: fdacfe1e7f81879c96f0d746cc1e62ec66e6a202a934dae2f9bb7c1027f91a95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42e38a486000c47409ecefd8f120950e856abd9163a3131b8733e65f9bbb337437ed660374c363ccded21db8c4491c158922be6e5510b2af2a8ed2b3e5aa96f1
|
7
|
+
data.tar.gz: 36fcaddd1f4d6766f53fb19bd26aaeeaf5e2f86164e6244620f3d5cc5e9067bf48b2172005c850d408d1dc7a80c43dabbe5e9f59c6be53664de4f312d78de844
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
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.6.2 - [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
|
|
@@ -11,18 +11,14 @@ I leave building truly professional text editors to software tooling experts who
|
|
11
11
|
|
12
12
|
## Features
|
13
13
|
|
14
|
-
Gladiator currently supports the following text editing features (including keyboard shortcuts with Mac CMD=CTRL on Windows/Linux)
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
-
|
19
|
-
- Watch project subdirectories for changes to automatically refresh in file explorer/file lookup
|
20
|
-
- Find & Replace (CMD+F)
|
14
|
+
Gladiator currently supports the following text editing features (including keyboard shortcuts with Mac CMD=CTRL on Windows/Linux)
|
15
|
+
|
16
|
+
### Text Editor
|
17
|
+
|
18
|
+
- Text Editor with Colored Ruby Syntax Highlighting
|
21
19
|
- Show Line Numbers
|
22
|
-
-
|
23
|
-
-
|
24
|
-
- Remember opened tabs, caret position, top line, window size, and window location
|
25
|
-
- Autosave on focus out/quit/open new file
|
20
|
+
- Multi-tab support (CMD+SHIFT+[ & CMD+SHIFT+] for tab navigation. CMD+1-9 to jump to a specific tab)
|
21
|
+
- Drag and drop split pane (drag a file from File Tree or File Lookup List, and it splits the pane)
|
26
22
|
- Duplicate Line(s)/selection (CMD+D)
|
27
23
|
- Kill Line(s)/selection (CMD+K)
|
28
24
|
- Move line/selection up (CMD+UP)
|
@@ -30,10 +26,41 @@ Gladiator currently supports the following text editing features (including keyb
|
|
30
26
|
- Comment/Uncomment line/selection (CMD+/)
|
31
27
|
- Indent/Unindent line/selection (CMD+] & CMD+[)
|
32
28
|
- Insert/Prefix New Line (CMD+ENTER & CMD+SHIFT+ENTER)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
-
|
29
|
+
|
30
|
+
### File Explorer Tree
|
31
|
+
|
32
|
+
- Collapsable file explorer tree listing files and directories for open project
|
33
|
+
- Context menu to open file, rename, delete, add new file, add new directory, and refresh tree
|
34
|
+
- Jump to open file in tree (CMD+T)
|
35
|
+
|
36
|
+
### File Lookup List Filter
|
37
|
+
|
38
|
+
- Collapsable file lookup list filter (CMD+R)
|
39
|
+
- Semi-fuzzy filtering by ignoring slashes, underscores, and dots to ease lookup
|
40
|
+
|
41
|
+
### Navigation Area
|
42
|
+
|
43
|
+
- Show current text editor file name
|
44
|
+
- Show file navigation stats (Caret Position / Line Position / Selection Count / Top Pixel)
|
45
|
+
- Jump to Line (CMD+L)
|
46
|
+
- Find & Replace (CMD+F)
|
47
|
+
|
48
|
+
### Menus
|
49
|
+
|
50
|
+
- File Menu to Open Project (CMD+SHIFT+P) and open Scratchpad for running arbitrary Ruby/Glimmer code without saving to disk (CMD+SHIFT+S)
|
51
|
+
- View Menu to Split Pane & Change Split Orientation to Horizontal/Vertical (CMD+SHIFT+O)
|
52
|
+
- Run Menu to run Ruby code (CMD+SHIFT+R)
|
53
|
+
|
54
|
+
### Watch External Changes
|
55
|
+
|
56
|
+
- Watch open file for external changes to automatically refresh in editor
|
57
|
+
- Watch project subdirectories for changes to automatically refresh in file explorer/file lookup
|
58
|
+
|
59
|
+
### Automatic Data Management
|
60
|
+
|
61
|
+
- Autosave on focus out/quit/open new file
|
62
|
+
- Remember opened tabs, caret position, top pixel, window size, and window location
|
63
|
+
- [Default](#configuration) "ignore paths" to avoid bogging down editor with irrelevant directory files
|
37
64
|
|
38
65
|
## Platforms
|
39
66
|
|
@@ -43,7 +70,7 @@ Gladiator currently supports the following text editing features (including keyb
|
|
43
70
|
|
44
71
|
## Pre-requisites
|
45
72
|
|
46
|
-
- [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) (JRuby Desktop Development GUI
|
73
|
+
- [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) (JRuby Desktop Development GUI Framework): '>= 4.17.2.0', '< 5.0.0.0' (dependency included in Ruby gem).
|
47
74
|
- [JRuby](https://www.jruby.org/download): Same version required by [Glimmer](https://github.com/AndyObtiva/glimmer-dsl-swt)
|
48
75
|
- [JDK](https://www.oracle.com/java/technologies/javase-downloads.html): Same version required by [Glimmer](https://github.com/AndyObtiva/glimmer-dsl-swt)
|
49
76
|
|
@@ -77,6 +104,12 @@ You may run the `gladiator` command to bring up the text editor in the project d
|
|
77
104
|
gladiator
|
78
105
|
```
|
79
106
|
|
107
|
+
On Linux, you may need to run with extra memory via this command instead:
|
108
|
+
|
109
|
+
```
|
110
|
+
gladiator -J-Xmx1200M
|
111
|
+
```
|
112
|
+
|
80
113
|
On Windows, you may need to run with extra memory via this command instead:
|
81
114
|
|
82
115
|
```
|
@@ -103,7 +136,7 @@ To reuse Gladiator as a Glimmer Custom Shell inside another Glimmer application,
|
|
103
136
|
following to the application's `Gemfile`:
|
104
137
|
|
105
138
|
```
|
106
|
-
gem 'glimmer-cs-gladiator', '~> 0.
|
139
|
+
gem 'glimmer-cs-gladiator', '~> 0.6.2'
|
107
140
|
```
|
108
141
|
|
109
142
|
Run:
|
@@ -129,16 +162,12 @@ Opens Gladiator with "/Users/User/code" as the root directory.
|
|
129
162
|
|
130
163
|
## Configuration
|
131
164
|
|
132
|
-
Gladiator automatically saves configuration data in a `.gladiator` file at the directory it is run from.
|
165
|
+
Gladiator automatically saves configuration data in a `.gladiator` file at the directory it is run from. It may be edited to add extra ignore paths.
|
133
166
|
|
134
167
|
It currently remembers:
|
135
|
-
- Last opened
|
136
|
-
-
|
137
|
-
-
|
138
|
-
- Window size
|
139
|
-
- Opened tabs
|
140
|
-
- Split tabs
|
141
|
-
- Ignore Paths
|
168
|
+
- Last opened files (in both split panes if split)
|
169
|
+
- Window size and position
|
170
|
+
- Ignore Paths (default: '.gladiator', '.git', 'coverage', 'packages', 'node_modules', 'tmp', 'vendor')
|
142
171
|
|
143
172
|
## Gotcha
|
144
173
|
|
@@ -171,6 +200,6 @@ Copyright (c) 2020 Andy Maleh. See [LICENSE.txt](LICENSE.txt) for further detail
|
|
171
200
|
|
172
201
|
--
|
173
202
|
|
174
|
-
[<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=40 />](https://github.com/AndyObtiva/glimmer) Built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) (JRuby Desktop Development GUI
|
203
|
+
[<img src="https://raw.githubusercontent.com/AndyObtiva/glimmer/master/images/glimmer-logo-hi-res.png" height=40 />](https://github.com/AndyObtiva/glimmer) Built with [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer-dsl-swt) (JRuby Desktop Development GUI Framework)
|
175
204
|
|
176
205
|
Gladiator icon made by <a href="https://www.flaticon.com/authors/freepik" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a>
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.2
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Glimmer
|
2
2
|
class Gladiator
|
3
3
|
class Command
|
4
|
+
include Glimmer
|
5
|
+
|
4
6
|
class << self
|
5
7
|
include Glimmer
|
6
8
|
|
@@ -13,11 +15,18 @@ module Glimmer
|
|
13
15
|
command_history[file] ||= [Command.new(file)]
|
14
16
|
end
|
15
17
|
|
16
|
-
def do(file, method = nil, command: nil)
|
17
|
-
command
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
def do(file, method = nil, *args, command: nil)
|
19
|
+
if command.nil?
|
20
|
+
command ||= Command.new(file, method, *args)
|
21
|
+
command.previous_command = command_history_for(file).last
|
22
|
+
unless command_history_for(file).last.method == :change_content! && method == :change_content!
|
23
|
+
command_history_for(file).last.next_command = command
|
24
|
+
end
|
25
|
+
command.do
|
26
|
+
command_history_for(file) << command unless command_history_for(file).last.method == :change_content! && method == :change_content!
|
27
|
+
else
|
28
|
+
command_history_for(file) << command
|
29
|
+
end
|
21
30
|
end
|
22
31
|
|
23
32
|
def undo(file)
|
@@ -30,15 +39,22 @@ module Glimmer
|
|
30
39
|
command = command_history_for(file).last
|
31
40
|
command&.redo
|
32
41
|
end
|
42
|
+
|
43
|
+
def clear(file)
|
44
|
+
command_history[file] = [Command.new(file)]
|
45
|
+
end
|
33
46
|
end
|
34
47
|
|
35
|
-
attr_accessor :file, :method, :
|
48
|
+
attr_accessor :file, :method, :args, :previous_command, :next_command,
|
49
|
+
:file_dirty_content, :file_caret_position, :file_selection_count, :previous_file_dirty_content, :previous_file_caret_position, :previous_file_selection_count
|
36
50
|
|
37
|
-
def initialize(file, method = nil)
|
51
|
+
def initialize(file, method = nil, *args)
|
38
52
|
@file = file
|
39
53
|
@method = method
|
54
|
+
@args = args
|
40
55
|
end
|
41
56
|
|
57
|
+
|
42
58
|
def native?
|
43
59
|
@method.nil?
|
44
60
|
end
|
@@ -56,6 +72,9 @@ module Glimmer
|
|
56
72
|
|
57
73
|
def redo
|
58
74
|
return if next_command.nil?# || next_command.native?
|
75
|
+
@file.dirty_content = next_command.file_dirty_content.clone
|
76
|
+
@file.caret_position = next_command.file_caret_position
|
77
|
+
@file.selection_count = next_command.file_selection_count
|
59
78
|
Command.do(next_command.file, command: next_command)
|
60
79
|
end
|
61
80
|
|
@@ -63,6 +82,10 @@ module Glimmer
|
|
63
82
|
@previous_file_dirty_content = @file.dirty_content.clone
|
64
83
|
@previous_file_caret_position = @file.caret_position
|
65
84
|
@previous_file_selection_count = @file.selection_count
|
85
|
+
if @method == :change_content!
|
86
|
+
@previous_file_caret_position = @file.last_caret_position
|
87
|
+
@previous_file_selection_count = @file.last_selection_count
|
88
|
+
end
|
66
89
|
end
|
67
90
|
|
68
91
|
def restore
|
@@ -72,7 +95,17 @@ module Glimmer
|
|
72
95
|
end
|
73
96
|
|
74
97
|
def execute
|
75
|
-
@file.
|
98
|
+
@file.start_command
|
99
|
+
@file.send(@method, *@args)
|
100
|
+
@file.end_command
|
101
|
+
@file_dirty_content = @file.dirty_content.clone
|
102
|
+
@file_caret_position = @file.caret_position
|
103
|
+
@file_selection_count = @file.selection_count
|
104
|
+
if previous_command.method == :change_content! && @method == :change_content!
|
105
|
+
previous_command.file_dirty_content = @file_dirty_content
|
106
|
+
previous_command.file_caret_position = @file_caret_position
|
107
|
+
previous_command.file_selection_count = @file_selection_count
|
108
|
+
end
|
76
109
|
end
|
77
110
|
end
|
78
111
|
end
|
@@ -6,8 +6,6 @@ module Glimmer
|
|
6
6
|
include Glimmer
|
7
7
|
include Glimmer::DataBinding::ObservableModel
|
8
8
|
|
9
|
-
REFRESH_DELAY = 7
|
10
|
-
|
11
9
|
attr_accessor :selected_child, :filter, :children, :filtered_path_options, :filtered_path, :display_path, :ignore_paths
|
12
10
|
attr_reader :name, :parent, :path
|
13
11
|
attr_writer :all_children
|
@@ -15,19 +13,30 @@ module Glimmer
|
|
15
13
|
def initialize(path, project_dir = nil)
|
16
14
|
@project_dir = project_dir
|
17
15
|
if is_local_dir
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
16
|
+
@filewatcher = Filewatcher.new(path)
|
17
|
+
Thread.new(@filewatcher) do |fw|
|
18
|
+
begin
|
19
|
+
fw.watch do |filename, event|
|
20
|
+
# TODO do fine grained processing of events for enhanced performance (e.g. dir refresh vs file change)
|
21
|
+
# TODO do fine grained file change only without a refresh delay for enhanced performance
|
22
|
+
begin
|
23
|
+
if !@refresh_in_progress && !filename.include?('new_file') && (event != :updated || find_child_file(filename).nil?)
|
24
|
+
Thread.new {
|
25
|
+
refresh
|
26
|
+
}
|
27
|
+
end
|
28
|
+
rescue => e
|
29
|
+
puts e.full_message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
rescue => e
|
33
|
+
puts e.full_message
|
34
|
+
end
|
35
|
+
end
|
27
36
|
end
|
28
37
|
self.path = ::File.expand_path(path)
|
29
38
|
@name = ::File.basename(::File.expand_path(path))
|
30
|
-
@ignore_paths = ['.gladiator', '.git', 'coverage', 'packages', 'tmp', 'vendor']
|
39
|
+
@ignore_paths = ['.gladiator', '.git', 'coverage', 'packages', 'node_modules', 'tmp', 'vendor']
|
31
40
|
self.filtered_path_options = []
|
32
41
|
end
|
33
42
|
|
@@ -67,7 +76,7 @@ module Glimmer
|
|
67
76
|
result || p.include?(ignore_path)
|
68
77
|
end
|
69
78
|
end.map do |p|
|
70
|
-
::File.file?(p) ?
|
79
|
+
::File.file?(p) ? File.new(p, project_dir) : Dir.new(p, project_dir)
|
71
80
|
end.sort_by do |c|
|
72
81
|
c.path.to_s.downcase
|
73
82
|
end.sort_by do |c|
|
@@ -76,6 +85,22 @@ module Glimmer
|
|
76
85
|
child.retrieve_children if child.is_a?(Dir)
|
77
86
|
end
|
78
87
|
end
|
88
|
+
|
89
|
+
def find_child_file(child_path)
|
90
|
+
depth_first_search_file(self, child_path)
|
91
|
+
end
|
92
|
+
|
93
|
+
def depth_first_search_file(dir, file_path)
|
94
|
+
dir.children.each do |child|
|
95
|
+
if child.is_a?(File)
|
96
|
+
return child if child.path.include?(file_path)
|
97
|
+
else
|
98
|
+
result = depth_first_search_file(child, file_path)
|
99
|
+
return result unless result.nil?
|
100
|
+
end
|
101
|
+
end
|
102
|
+
nil
|
103
|
+
end
|
79
104
|
|
80
105
|
def selected_child_path_history
|
81
106
|
@selected_child_path_history ||= []
|
@@ -91,6 +116,7 @@ module Glimmer
|
|
91
116
|
|
92
117
|
def refresh(async: true, force: false)
|
93
118
|
return if @refresh_paused && !force
|
119
|
+
@refresh_in_progress = true
|
94
120
|
retrieve_children
|
95
121
|
collect_all_children
|
96
122
|
refresh_operation = lambda do
|
@@ -102,6 +128,7 @@ module Glimmer
|
|
102
128
|
else
|
103
129
|
sync_exec(&refresh_operation)
|
104
130
|
end
|
131
|
+
@refresh_in_progress = false
|
105
132
|
end
|
106
133
|
|
107
134
|
def filter=(value)
|
@@ -144,7 +171,7 @@ module Glimmer
|
|
144
171
|
def selected_child_path=(selected_path)
|
145
172
|
return (project_dir.selected_child = nil) if selected_path.nil?
|
146
173
|
# scratchpad scenario
|
147
|
-
if selected_path.empty? #
|
174
|
+
if selected_path.empty? # Scratchpad
|
148
175
|
@selected_child&.write_dirty_content
|
149
176
|
return (self.selected_child = File.new)
|
150
177
|
end
|
@@ -154,7 +181,7 @@ module Glimmer
|
|
154
181
|
selected_path = full_selected_path
|
155
182
|
if ::File.file?(selected_path)
|
156
183
|
@selected_child&.write_dirty_content
|
157
|
-
new_child =
|
184
|
+
new_child = find_child_file(selected_path)
|
158
185
|
begin
|
159
186
|
unless new_child.dirty_content.nil?
|
160
187
|
self.selected_child&.stop_filewatcher
|
@@ -175,6 +202,7 @@ module Glimmer
|
|
175
202
|
end
|
176
203
|
|
177
204
|
def selected_child=(new_child)
|
205
|
+
return if selected_child == new_child
|
178
206
|
file_properties = @selected_child&.backup_properties if @selected_child == new_child
|
179
207
|
@selected_child = new_child
|
180
208
|
@selected_child.restore_properties(file_properties) if file_properties
|
@@ -191,7 +219,7 @@ module Glimmer
|
|
191
219
|
def eql?(other)
|
192
220
|
self.path.eql?(other&.path)
|
193
221
|
end
|
194
|
-
|
222
|
+
|
195
223
|
def hash
|
196
224
|
self.path.hash
|
197
225
|
end
|
@@ -3,7 +3,7 @@ module Glimmer
|
|
3
3
|
class File
|
4
4
|
include Glimmer
|
5
5
|
|
6
|
-
attr_accessor :
|
6
|
+
attr_accessor :line_numbers_content, :line_number, :find_text, :replace_text, :top_pixel, :display_path, :case_sensitive, :caret_position, :selection_count, :last_caret_position, :last_selection_count, :line_position
|
7
7
|
attr_reader :name, :path, :project_dir
|
8
8
|
|
9
9
|
def initialize(path='', project_dir=nil)
|
@@ -13,33 +13,55 @@ module Glimmer
|
|
13
13
|
@name = path.empty? ? 'Scratchpad' : ::File.basename(path)
|
14
14
|
self.path = ::File.expand_path(path) unless path.empty?
|
15
15
|
@top_pixel = 0
|
16
|
+
@caret_position = 0
|
16
17
|
@selection_count = 0
|
17
|
-
@
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
18
|
+
@last_selection_count = 0
|
19
|
+
@line_number = 1
|
20
|
+
@init = nil
|
21
|
+
end
|
22
|
+
|
23
|
+
def init_content
|
24
|
+
unless @init
|
25
|
+
@init = true
|
26
|
+
begin
|
27
|
+
# test read dirty content
|
28
|
+
observe(self, :dirty_content) do
|
29
|
+
line_count = lines.empty? ? 1 : lines.size
|
30
|
+
lines_text_size = [line_count.to_s.size, 4].max
|
31
|
+
old_top_pixel = top_pixel
|
32
|
+
self.line_numbers_content = line_count.times.map {|n| (' ' * (lines_text_size - (n+1).to_s.size)) + (n+1).to_s }.join("\n")
|
33
|
+
self.top_pixel = old_top_pixel
|
34
|
+
end
|
35
|
+
the_dirty_content = read_dirty_content
|
36
|
+
the_dirty_content.split("\n") # test that it is not a binary file (crashes to rescue block otherwise)
|
37
|
+
self.dirty_content = the_dirty_content
|
38
|
+
observe(self, :caret_position) do |new_caret_position|
|
39
|
+
update_line_number_from_caret_position(new_caret_position)
|
40
|
+
end
|
41
|
+
observe(self, :line_number) do |new_line_number|
|
33
42
|
line_index = line_number - 1
|
34
43
|
new_caret_position = caret_position_for_line_index(line_index)
|
35
|
-
|
44
|
+
current_caret_position = caret_position
|
45
|
+
line_index_for_new_caret_position = line_index_for_caret_position(new_caret_position)
|
46
|
+
line_index_for_current_caret_position = line_index_for_caret_position(current_caret_position)
|
47
|
+
self.caret_position = new_caret_position unless (current_caret_position && line_index_for_new_caret_position == line_index_for_current_caret_position)
|
36
48
|
end
|
49
|
+
rescue # in case of a binary file
|
50
|
+
stop_filewatcher
|
37
51
|
end
|
38
|
-
rescue
|
39
|
-
# no op in case of a binary file
|
40
52
|
end
|
41
53
|
end
|
42
|
-
|
54
|
+
|
55
|
+
def update_line_number_from_caret_position(new_caret_position)
|
56
|
+
new_line_number = line_index_for_caret_position(caret_position) + 1
|
57
|
+
current_line_number = line_number
|
58
|
+
unless (current_line_number && current_line_number == new_line_number)
|
59
|
+
self.line_number = new_line_number
|
60
|
+
# TODO check if the following line is needed
|
61
|
+
self.line_position = caret_position - caret_position_for_line_index(line_number - 1) + 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
43
65
|
def path=(the_path)
|
44
66
|
@path = the_path
|
45
67
|
generate_display_path
|
@@ -49,6 +71,15 @@ module Glimmer
|
|
49
71
|
return if @path.empty?
|
50
72
|
@display_path = @path.sub(project_dir.path, '').sub(/^\//, '')
|
51
73
|
end
|
74
|
+
|
75
|
+
def name=(the_name)
|
76
|
+
new_path = path.sub(/#{Regexp.escape(@name)}$/, the_name) unless scratchpad?
|
77
|
+
@name = the_name
|
78
|
+
if !scratchpad? && ::File.exist?(path)
|
79
|
+
FileUtils.mv(path, new_path)
|
80
|
+
self.path = new_path
|
81
|
+
end
|
82
|
+
end
|
52
83
|
|
53
84
|
def scratchpad?
|
54
85
|
path.to_s.empty?
|
@@ -66,50 +97,74 @@ module Glimmer
|
|
66
97
|
send("#{property}=", value)
|
67
98
|
end
|
68
99
|
end
|
100
|
+
|
101
|
+
def caret_position=(value)
|
102
|
+
@last_caret_position = @caret_position
|
103
|
+
@caret_position = value
|
104
|
+
end
|
69
105
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
Command.do(self) # record a native (OS-widget) operation
|
75
|
-
self.dirty_content = value
|
76
|
-
end
|
106
|
+
def selection_count=(value)
|
107
|
+
#@last_selection_count = @selection_count
|
108
|
+
@selection_count = value
|
109
|
+
@last_selection_count = @selection_count
|
77
110
|
end
|
78
111
|
|
112
|
+
def dirty_content
|
113
|
+
init_content
|
114
|
+
@dirty_content
|
115
|
+
end
|
116
|
+
|
117
|
+
def dirty_content=(the_content)
|
118
|
+
# TODO set partial dirty content by line(s) for enhanced performance
|
119
|
+
@dirty_content = the_content
|
120
|
+
old_caret_position = caret_position
|
121
|
+
old_top_pixel = top_pixel
|
122
|
+
|
123
|
+
notify_observers(:content)
|
124
|
+
if @formatting_dirty_content_for_writing
|
125
|
+
self.caret_position = old_caret_position
|
126
|
+
self.top_pixel = old_top_pixel
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
79
130
|
def content
|
80
131
|
dirty_content
|
81
132
|
end
|
82
133
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
134
|
+
# to use for widget data-binding
|
135
|
+
def content=(value)
|
136
|
+
value = value.gsub("\t", ' ')
|
137
|
+
if dirty_content != value
|
138
|
+
Command.do(self, :change_content!, value)
|
139
|
+
end
|
87
140
|
end
|
88
|
-
|
89
|
-
def
|
90
|
-
|
141
|
+
|
142
|
+
def change_content!(value)
|
143
|
+
self.dirty_content = value
|
144
|
+
update_line_number_from_caret_position(caret_position)
|
91
145
|
end
|
92
146
|
|
93
|
-
def
|
94
|
-
|
147
|
+
def start_command
|
148
|
+
@commmand_in_progress = true
|
95
149
|
end
|
96
|
-
|
97
|
-
def
|
98
|
-
|
150
|
+
|
151
|
+
def end_command
|
152
|
+
@commmand_in_progress = false
|
99
153
|
end
|
100
|
-
|
101
|
-
def
|
102
|
-
|
103
|
-
@name = the_name
|
104
|
-
if !scratchpad? && ::File.exist?(path)
|
105
|
-
FileUtils.mv(path, new_path)
|
106
|
-
self.path = new_path
|
107
|
-
end
|
154
|
+
|
155
|
+
def command_in_progress?
|
156
|
+
@commmand_in_progress
|
108
157
|
end
|
109
158
|
|
110
|
-
def
|
111
|
-
|
112
|
-
|
159
|
+
def close
|
160
|
+
stop_filewatcher
|
161
|
+
remove_all_observers
|
162
|
+
initialize(path, project_dir)
|
163
|
+
Command.clear(self)
|
164
|
+
end
|
165
|
+
|
166
|
+
def read_dirty_content
|
167
|
+
path.empty? ? '' : ::File.read(path)
|
113
168
|
end
|
114
169
|
|
115
170
|
def start_filewatcher
|
@@ -117,15 +172,13 @@ module Glimmer
|
|
117
172
|
@filewatcher = Filewatcher.new(@path)
|
118
173
|
@thread = Thread.new(@filewatcher) do |fw|
|
119
174
|
fw.watch do |filename, event|
|
120
|
-
|
121
|
-
|
122
|
-
# test read dirty content
|
123
|
-
read_dirty_content.split("\n")
|
124
|
-
async_exec do
|
175
|
+
async_exec do
|
176
|
+
begin
|
125
177
|
self.dirty_content = read_dirty_content if read_dirty_content != dirty_content
|
178
|
+
rescue StandardError, Errno::ENOENT
|
179
|
+
# in case of a binary file
|
180
|
+
stop_filewatcher
|
126
181
|
end
|
127
|
-
rescue
|
128
|
-
# no op in case of a binary file
|
129
182
|
end
|
130
183
|
end
|
131
184
|
end
|
@@ -135,21 +188,28 @@ module Glimmer
|
|
135
188
|
@filewatcher&.stop
|
136
189
|
end
|
137
190
|
|
138
|
-
def format_dirty_content_for_writing!
|
139
|
-
new_dirty_content = dirty_content.split("\n").map {|line| line.strip.empty? ? line : line.rstrip }.join("\n")
|
140
|
-
new_dirty_content = "#{new_dirty_content.gsub("\r\n", "\n").gsub("\r", "\n").sub(/\n+\z/, '')}\n"
|
141
|
-
self.dirty_content = new_dirty_content if new_dirty_content != self.dirty_content
|
142
|
-
end
|
143
|
-
|
144
191
|
def write_dirty_content
|
145
|
-
|
192
|
+
# TODO write partial dirty content by line(s) for enhanced performance
|
193
|
+
return if scratchpad? || !::File.exist?(path) || !::File.exists?(path) || read_dirty_content == dirty_content
|
146
194
|
format_dirty_content_for_writing!
|
147
|
-
::File.write(path, dirty_content)
|
148
|
-
rescue => e
|
195
|
+
::File.write(path, dirty_content)
|
196
|
+
rescue StandardError, ArgumentError => e
|
149
197
|
puts "Error in writing dirty content for #{path}"
|
150
198
|
puts e.full_message
|
151
199
|
end
|
152
200
|
|
201
|
+
def format_dirty_content_for_writing!
|
202
|
+
return if @commmand_in_progress
|
203
|
+
# TODO f ix c ar e t pos it ion after formatting dirty content (diff?)
|
204
|
+
new_dirty_content = dirty_content.to_s.split("\n").map {|line| line.strip.empty? ? line : line.rstrip }.join("\n")
|
205
|
+
new_dirty_content = "#{new_dirty_content.gsub("\r\n", "\n").gsub("\r", "\n").sub(/\n+\z/, '')}\n"
|
206
|
+
if new_dirty_content != self.dirty_content
|
207
|
+
@formatting_dirty_content_for_writing = true
|
208
|
+
self.dirty_content = new_dirty_content
|
209
|
+
@formatting_dirty_content_for_writing = false
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
153
213
|
def write_raw_dirty_content
|
154
214
|
return if scratchpad? || !::File.exist?(path)
|
155
215
|
::File.write(path, dirty_content) if ::File.exists?(path)
|
@@ -185,7 +245,7 @@ module Glimmer
|
|
185
245
|
self.caret_position = caret_position_for_line_index(line_number) + current_line_indentation.size
|
186
246
|
self.selection_count = 0
|
187
247
|
end
|
188
|
-
|
248
|
+
|
189
249
|
def comment_line!
|
190
250
|
old_lines = lines
|
191
251
|
return if old_lines.size < 1
|
@@ -219,6 +279,7 @@ module Glimmer
|
|
219
279
|
new_caret_position = old_caret_position + delta
|
220
280
|
new_caret_position = [new_caret_position, old_caret_position_line_caret_position].max
|
221
281
|
self.caret_position = new_caret_position
|
282
|
+
self.selection_count = 0
|
222
283
|
end
|
223
284
|
end
|
224
285
|
|
@@ -243,6 +304,7 @@ module Glimmer
|
|
243
304
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
244
305
|
else
|
245
306
|
self.caret_position = old_caret_position + delta
|
307
|
+
self.selection_count = 0
|
246
308
|
end
|
247
309
|
end
|
248
310
|
|
@@ -274,6 +336,7 @@ module Glimmer
|
|
274
336
|
new_caret_position = old_caret_position + delta
|
275
337
|
new_caret_position = [new_caret_position, old_caret_position_line_caret_position].max
|
276
338
|
self.caret_position = new_caret_position
|
339
|
+
self.selection_count = 0
|
277
340
|
end
|
278
341
|
end
|
279
342
|
|
@@ -311,6 +374,7 @@ module Glimmer
|
|
311
374
|
self.selection_count = (caret_position_for_line_index(old_end_caret_line_index + 1) - self.caret_position)
|
312
375
|
else
|
313
376
|
self.caret_position = old_caret_position + delta
|
377
|
+
self.selection_count = 0
|
314
378
|
end
|
315
379
|
end
|
316
380
|
|
@@ -471,7 +535,7 @@ module Glimmer
|
|
471
535
|
def line_index_for_caret_position(caret_position)
|
472
536
|
dirty_content[0...caret_position.to_i].count("\n")
|
473
537
|
end
|
474
|
-
|
538
|
+
|
475
539
|
def caret_position_for_line_index(line_index)
|
476
540
|
cp = lines[0...line_index].join("\n").size
|
477
541
|
cp += 1 if line_index > 0
|