glimmer-cs-gladiator 0.5.2 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gem Version](https://badge.fury.io/rb/glimmer-cs-gladiator.svg)](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
|