glimmer-cs-gladiator 0.1.4 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3b934c1a94dfd1a6544aeecc4b4be8296ba361725a3c5a668a41411eb6b2d6c5
4
- data.tar.gz: 6060afe18157c255ad483b26ff1bf137d3f9e7083df4945876ac258e85ef412f
3
+ metadata.gz: 9397375fcae09b0628d7cea62e30cf9e10e1bccc236a10717bf442824adf9bb4
4
+ data.tar.gz: 46500cd7bcc7636295ea1466369f9ef4a819dac0f27e87615ffec510634ec078
5
5
  SHA512:
6
- metadata.gz: 9f225ed4adab885600d43209c7f21fed87d78b584f47fd9b6a35d07d39b784208d1c8df6ca0e7e8b616cb593a3d35625c48b6ff3c5b4121c49c59ce7a2dcb990
7
- data.tar.gz: 858eff913bfd012b0aaf9511141cb55f1d427ea57a6b01bb85d7403e3e0e1c5f57000c1878efdacad0504e67949ba59a915d279165669f36d7d410b98922aee8
6
+ metadata.gz: f266d9d55637f38f001f6e80b553a704d85e809b3ccd9fd29ac942bf7ce1b747133964176a42d0cc4fa7e07474fed78c03cce611fadd7d90b0ee5206282d18ac
7
+ data.tar.gz: 4a4f36dac54c4069ef32268342e2698092dff0b19df564e8173db73b63bfa1b515274eb54353ed09f6417afcfa2967f9e2b538caf980d88683d4cff6f753d629
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Gladiator (Glimmer Editor) 0.1.4 - Glimmer Custom Shell
1
+ # Gladiator (Glimmer Editor) 0.2.0 - Glimmer Custom Shell
2
2
  [![Gem Version](https://badge.fury.io/rb/glimmer-cs-gladiator.svg)](http://badge.fury.io/rb/glimmer-cs-gladiator)
3
3
 
4
4
  ![Gladiator](images/glimmer-gladiator.png)
@@ -9,27 +9,35 @@ Gladiator is also a personal tool for shaping an editor exactly the way I like.
9
9
  I leave building truly professional text editors to software tooling experts who would hopefully use Glimmer one day.
10
10
 
11
11
  Gladiator currently supports the following text editing features:
12
- - File explorer navigation to open file, rename, delete, add new file, add new directory, or refresh tree
13
- - File lookup by name ignoring slashes, underscores, and dots to ease lookup
12
+ - File explorer navigation to open file, rename, delete, add new file, add new directory, or refresh tree (CMD+T)
13
+ - File lookup by name ignoring slashes, underscores, and dots to ease lookup (CMD+R)
14
14
  - Watch open file for external changes to automatically refresh in editor
15
15
  - Watch project subdirectories for changes to automatically refresh in file explorer/file lookup
16
- - Find & Replace
16
+ - Find & Replace (CMD+F)
17
17
  - Show Line Numbers
18
- - Jump to Line
19
- - Multiple tab support
20
- - Remember last opened file, caret position, top line, window size, and window location
21
- - Autosave on focus out/quit/open new file
22
- - Duplicate Line(s)/selection
23
- - Kill Line(s)/selection
24
- - Move line/selection up
25
- - Move line/selection down
26
- - Comment/Uncomment line/selection
27
- - Indent/Unindent line/selection
18
+ - Jump to Line (CMD+L)
19
+ - Multiple tab support (CMD+SHIFT+[ & CMD+SHIFT+] for tab navigation. CMD+1-9 to jump to a specific tab)
20
+ - Remember opened tabs, caret position, top line, window size, and window location
21
+ - Autosave on focus out/quit/open new file
22
+ - Duplicate Line(s)/selection (CMD+D)
23
+ - Kill Line(s)/selection (CMD+K)
24
+ - Move line/selection up (CMD+UP)
25
+ - Move line/selection down (CMD+DOWN)
26
+ - Comment/Uncomment line/selection (CMD+/)
27
+ - Indent/Unindent line/selection (CMD+] & CMD+[)
28
+ - Insert/Prefix New Line (CMD+ENTER & CMD+SHIFT+ENTER)
29
+
30
+ ## Platforms
31
+
32
+ - Mac: Gladiator works best on the Mac.
33
+ - Linux: Gladiator works with handicaps on Linux (performing text editing operations causes scroll jitter)
34
+ - Windows: Not tested on Windows yet, but should theoretically work there too.
28
35
 
29
36
  ## Pre-requisites
30
37
 
31
- - JRuby 9.2.11.1 (supporting Ruby 2.5.x syntax) (find at https://www.jruby.org/download)
32
- - Java SE Runtime Environment 7 or higher (find at https://www.oracle.com/java/technologies/javase-downloads.html)
38
+ - [Glimmer DSL for SWT](https://github.com/AndyObtiva/glimmer) (Ruby Desktop Development GUI Library): '>= 0.1.0', '< 2.0.0' (dependency included in Ruby gem).
39
+ - [JRuby](https://www.jruby.org/download): Same version required by [Glimmer](https://github.com/AndyObtiva/glimmer)
40
+ - [JDK](https://www.oracle.com/java/technologies/javase-downloads.html): Same version required by [Glimmer](https://github.com/AndyObtiva/glimmer)
33
41
 
34
42
  ## Setup Instructions
35
43
 
@@ -53,7 +61,7 @@ To reuse Gladiator as a Glimmer Custom Shell inside another Glimmer application,
53
61
  following to the application's `Gemfile`:
54
62
 
55
63
  ```
56
- gem 'glimmer-cs-gladiator', '0.1.4'
64
+ gem 'glimmer-cs-gladiator', '0.2.0'
57
65
  ```
58
66
 
59
67
  Run:
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -3,4 +3,11 @@
3
3
  require 'glimmer/launcher'
4
4
 
5
5
  gladiator_runner = File.expand_path('../gladiator_runner.rb', __FILE__)
6
- Glimmer::Launcher.new([gladiator_runner, '-J-Xrs'] + ARGV).launch
6
+ launcher = Glimmer::Launcher.new([gladiator_runner, '-J-Xrs'] + ARGV)
7
+ launcher.application_paths.to_a.each do |file|
8
+ if file != gladiator_runner
9
+ launcher.application_paths.delete(file)
10
+ ENV['LOCAL_DIR'] ||= file
11
+ end
12
+ end
13
+ launcher.launch
@@ -0,0 +1,75 @@
1
+ module Glimmer
2
+ class Gladiator
3
+ class Command
4
+ class << self
5
+ def command_history
6
+ @command_history ||= {}
7
+ end
8
+
9
+ def command_history_for(file)
10
+ # keeping a first command to make redo support work by remembering next command after undoing all
11
+ command_history[file] ||= [Command.new(file)]
12
+ end
13
+
14
+ def do(file, method = nil, command: nil)
15
+ command ||= Command.new(file, method)
16
+ command_history_for(file)&.last&.next_command = command
17
+ command.do
18
+ command_history_for(file) << command
19
+ end
20
+
21
+ def undo(file)
22
+ return if command_history_for(file).size <= 1
23
+ command_history_for(file).pop.undo
24
+ end
25
+
26
+ def redo(file)
27
+ command_history_for(file).last&.redo
28
+ end
29
+ end
30
+
31
+ attr_accessor :file, :method, :next_command, :previous_file_content, :previous_file_caret_position, :previous_file_selection_count
32
+
33
+ def initialize(file, method = nil)
34
+ @file = file
35
+ @method = method
36
+ end
37
+
38
+ def native?
39
+ @method.nil?
40
+ end
41
+
42
+ def do
43
+ return if native?
44
+ backup
45
+ execute
46
+ end
47
+
48
+ def undo
49
+ return if native?
50
+ restore
51
+ end
52
+
53
+ def redo
54
+ return if next_command.nil?# || next_command.native?
55
+ Command.do(next_command.file, command: next_command)
56
+ end
57
+
58
+ def backup
59
+ @previous_file_dirty_content = @file.dirty_content.clone
60
+ @previous_file_caret_position = @file.caret_position
61
+ @previous_file_selection_count = @file.selection_count
62
+ end
63
+
64
+ def restore
65
+ @file.dirty_content = @previous_file_dirty_content.clone
66
+ @file.caret_position = @previous_file_caret_position
67
+ @file.selection_count = @previous_file_selection_count
68
+ end
69
+
70
+ def execute
71
+ @file.send(@method)
72
+ end
73
+ end
74
+ end
75
+ end
@@ -117,7 +117,7 @@ module Glimmer
117
117
  begin
118
118
  unless new_child.dirty_content.nil?
119
119
  self.selected_child&.stop_filewatcher
120
- selected_child_path_history << self.selected_child.path if self.selected_child
120
+ selected_child_path_history << new_child.path if new_child && !selected_child_path_history.include?(new_child.path)
121
121
  self.selected_child = new_child
122
122
  self.selected_child.start_filewatcher
123
123
  end
@@ -140,6 +140,14 @@ module Glimmer
140
140
  def to_s
141
141
  path
142
142
  end
143
+
144
+ def eql?(other)
145
+ self.path.eql?(other&.path)
146
+ end
147
+
148
+ def hash
149
+ self.path.hash
150
+ end
143
151
  end
144
152
  end
145
153
  end
@@ -5,14 +5,18 @@ module Glimmer
5
5
  class File
6
6
  include Glimmer
7
7
 
8
- attr_accessor :line_numbers_content, :caret_position, :selection_count, :line_number, :find_text, :replace_text, :top_index, :path, :display_path
9
- attr_reader :name, :dirty_content
8
+ attr_accessor :dirty_content, :line_numbers_content, :selection, :selection_count, :line_number, :find_text, :replace_text, :top_index, :path, :display_path, :case_sensitive
9
+ attr_reader :name
10
10
 
11
11
  def initialize(path)
12
12
  raise "Not a file path: #{path}" unless ::File.file?(path)
13
+ @command_history = []
13
14
  @display_path = path
14
15
  @name = ::File.basename(path)
15
16
  @path = ::File.expand_path(path)
17
+ @top_index = 0
18
+ @selection_count = 0
19
+ @selection = Point.new(0, 0 + @selection_count)
16
20
  read_dirty_content = ::File.read(path)
17
21
  begin
18
22
  # test read dirty content
@@ -21,8 +25,9 @@ module Glimmer
21
25
  lines_text_size = lines.size.to_s.size
22
26
  self.line_numbers_content = lines.size.times.map {|n| (' ' * (lines_text_size - (n+1).to_s.size)) + (n+1).to_s }.join("\n")
23
27
  end
28
+ @line_number = 1
24
29
  self.dirty_content = read_dirty_content
25
- observe(self, :caret_position) do
30
+ observe(self, :selection) do
26
31
  self.line_number = line_index_for_caret_position(caret_position) + 1
27
32
  end
28
33
  observe(self, :line_number) do
@@ -36,7 +41,30 @@ module Glimmer
36
41
  # no op in case of a binary file
37
42
  end
38
43
  end
39
-
44
+
45
+ # to use for widget data-binding
46
+ def content=(value)
47
+ Command.do(self) # record a native (OS-widget) operation
48
+ self.dirty_content = value
49
+ end
50
+
51
+ def content
52
+ dirty_content
53
+ end
54
+
55
+ def caret_position=(value)
56
+ self.selection = Point.new(value, value + selection_count.to_i)
57
+ if OS.linux?
58
+ async_exec do
59
+ self.top_index = line_index_for_caret_position(value)
60
+ end
61
+ end
62
+ end
63
+
64
+ def caret_position
65
+ selection.x
66
+ end
67
+
40
68
  def name=(the_name)
41
69
  self.display_path = display_path.sub(/#{Regexp.escape(@name)}$/, the_name)
42
70
  @name = the_name
@@ -47,6 +75,7 @@ module Glimmer
47
75
 
48
76
  def dirty_content=(the_content)
49
77
  @dirty_content = the_content if ::File.exist?(path)
78
+ notify_observers(:content)
50
79
  end
51
80
 
52
81
  def start_filewatcher
@@ -105,6 +134,13 @@ module Glimmer
105
134
  FileUtils.rm(path)
106
135
  end
107
136
 
137
+ def prefix_new_line!
138
+ the_lines = lines
139
+ the_lines[line_number-1...line_number-1] = [current_line_indentation]
140
+ self.dirty_content = the_lines.join("\n")
141
+ self.caret_position = caret_position_for_line_index(line_number-1) + current_line_indentation.size
142
+ end
143
+
108
144
  def insert_new_line!
109
145
  the_lines = lines
110
146
  the_lines[line_number...line_number] = [current_line_indentation]
@@ -125,6 +161,7 @@ module Glimmer
125
161
  line_indices_for_selection(caret_position, selection_count).reverse.each do | the_line_index |
126
162
  delta = 0
127
163
  the_line = old_lines[the_line_index]
164
+ return if the_line.nil?
128
165
  if the_line.strip.start_with?('# ')
129
166
  new_lines[the_line_index] = the_line.sub(/# /, '')
130
167
  delta -= 2
@@ -183,7 +220,7 @@ module Glimmer
183
220
  delta = 0
184
221
  line_indices_for_selection(caret_position, selection_count).each do |the_line_index|
185
222
  the_line = old_lines[the_line_index]
186
- if the_line.start_with?(' ')
223
+ if the_line.to_s.start_with?(' ')
187
224
  new_lines[the_line_index] = the_line.sub(/ /, '')
188
225
  delta = -2
189
226
  elsif the_line.start_with?(' ')
@@ -240,7 +277,7 @@ module Glimmer
240
277
  end
241
278
 
242
279
  def find_next
243
- return if find_text.to_s.empty?
280
+ return if find_text.to_s.empty?
244
281
  all_lines = lines
245
282
  the_line_index = line_index_for_caret_position(caret_position)
246
283
  line_position = line_position_for_caret_position(caret_position)
@@ -251,8 +288,8 @@ module Glimmer
251
288
  the_index = (the_index + rotation)%all_lines.size
252
289
  start_position = 0
253
290
  start_position = line_position + find_text.to_s.size if i == 0 && the_index == the_line_index && found_text?(caret_position)
254
- text_to_find_in = the_line.downcase[start_position..-1]
255
- occurrence_index = text_to_find_in.index(find_text.to_s.downcase)
291
+ text_to_find_in = the_line[start_position..-1]
292
+ occurrence_index = case_sensitive ? text_to_find_in&.index(find_text.to_s) : text_to_find_in&.downcase&.index(find_text.to_s.downcase)
256
293
  if occurrence_index
257
294
  self.caret_position = caret_position_for_line_index(the_index) + start_position + occurrence_index
258
295
  self.selection_count = find_text.to_s.size
@@ -306,18 +343,22 @@ module Glimmer
306
343
  end
307
344
 
308
345
  def page_up
346
+ self.selection_count = 0
309
347
  self.line_number = [(self.line_number - 15), 1].max
310
348
  end
311
349
 
312
350
  def page_down
351
+ self.selection_count = 0
313
352
  self.line_number = [(self.line_number + 15), lines.size].min
314
353
  end
315
354
 
316
355
  def home
356
+ self.selection_count = 0
317
357
  self.line_number = 1
318
358
  end
319
359
 
320
360
  def end
361
+ self.selection_count = 0
321
362
  self.line_number = lines.size
322
363
  end
323
364
 
@@ -421,6 +462,14 @@ module Glimmer
421
462
  def to_s
422
463
  path
423
464
  end
465
+
466
+ def eql?(other)
467
+ self.path.eql?(other&.path)
468
+ end
469
+
470
+ def hash
471
+ self.path.hash
472
+ end
424
473
  end
425
474
  end
426
475
  end
@@ -4,9 +4,11 @@ rescue LoadError
4
4
  # no op
5
5
  end
6
6
  require 'fileutils'
7
+ require 'os'
7
8
 
8
9
  require 'models/glimmer/gladiator/dir'
9
10
  require 'models/glimmer/gladiator/file'
11
+ require 'models/glimmer/gladiator/command'
10
12
 
11
13
  require 'views/glimmer/gladiator/text_editor'
12
14
 
@@ -19,6 +21,8 @@ module Glimmer
19
21
  # Gladiator (Glimmer Editor)
20
22
  class Gladiator
21
23
  include Glimmer::UI::CustomShell
24
+
25
+ COMMAND_KEY = OS.mac? ? :command : :ctrl
22
26
 
23
27
  ## Add options like the following to configure CustomShell by outside consumers
24
28
  #
@@ -33,70 +37,90 @@ module Glimmer
33
37
  Display.setAppName('Gladiator')
34
38
  @display = display {
35
39
  on_event_keydown { |key_event|
36
- if Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'f'
37
- if @text_editor.text_widget.getSelectionText && @text_editor.text_widget.getSelectionText.size > 0
40
+ if key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == 'f'
41
+ if @text_editor&.text_widget&.getSelectionText && @text_editor&.text_widget&.getSelectionText&.size.to_i > 0
38
42
  @find_text.swt_widget.setText @text_editor.text_widget.getSelectionText
39
43
  end
40
44
  @find_text.swt_widget.selectAll
41
45
  @find_text.swt_widget.setFocus
42
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == 'c'
46
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == 'c'
43
47
  Clipboard.copy(Gladiator::Dir.local_dir.selected_child.path)
44
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == 'g'
48
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == 'g'
45
49
  Gladiator::Dir.local_dir.selected_child.find_previous
46
- # elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == 'w'
47
- # @tab_folder.swt_widget.getItems.each(&:dispose)
48
- # elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :alt) && key_event.character.chr.downcase == 'w'
49
- # @tab_folder.swt_widget.getItems.each do |ti|
50
- # ti.dispose unless ti == @tab_folder.swt_widget.getSelection()
51
- # end
52
- # elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'w'
53
- # @tab_folder.swt_widget.getSelection.each(&:dispose)
54
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == ']'
55
- @tab_folder.swt_widget.setSelection([@tab_folder.swt_widget.getSelectionIndex() + 1, @tab_folder.swt_widget.getItemCount - 1].min) if @tab_folder.swt_widget.getItemCount > 0
50
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == 'w'
51
+ @tab_folder.swt_widget.getItems.each do |tab_item|
52
+ Dir.local_dir.selected_child_path_history.delete(tab_item.getData('file_path'))
53
+ tab_item.getData('proxy').dispose
54
+ end
55
+ @tab_item = @text_editor = Dir.local_dir.selected_child = nil
56
+ @filter_text.swt_widget.selectAll
57
+ @filter_text.swt_widget.setFocus
58
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :alt) && extract_char(key_event) == 'w'
59
+ other_tab_items.each do |tab_item|
60
+ Dir.local_dir.selected_child_path_history.delete(tab_item.getData('file_path'))
61
+ tab_item.getData('proxy').dispose
62
+ end
63
+ elsif key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == 'w'
64
+ if selected_tab_item
65
+ Dir.local_dir.selected_child_path_history.delete(Dir.local_dir.selected_child.path)
66
+ selected_tab_item.getData('proxy').dispose
67
+ if selected_tab_item.nil?
68
+ @tab_item = @text_editor = Dir.local_dir.selected_child = nil
69
+ @filter_text.swt_widget.selectAll
70
+ @filter_text.swt_widget.setFocus
71
+ else
72
+ @text_editor.text_widget.setFocus
73
+ end
74
+ end
75
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == ']'
76
+ @tab_folder.swt_widget.setSelection((@tab_folder.swt_widget.getSelectionIndex() + 1) % @tab_folder.swt_widget.getItemCount) if @tab_folder.swt_widget.getItemCount > 0
56
77
  @text_editor.text_widget.setFocus
57
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == '['
58
- @tab_folder.swt_widget.setSelection([@tab_folder.swt_widget.getSelectionIndex() - 1, 0].max) if @tab_folder.swt_widget.getItemCount > 0
78
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == '['
79
+ @tab_folder.swt_widget.setSelection((@tab_folder.swt_widget.getSelectionIndex() - 1) % @tab_folder.swt_widget.getItemCount) if @tab_folder.swt_widget.getItemCount > 0
59
80
  @text_editor.text_widget.setFocus
60
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '1'
81
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '1'
61
82
  @tab_folder.swt_widget.setSelection(0) if @tab_folder.swt_widget.getItemCount >= 1
62
83
  @text_editor.text_widget.setFocus
63
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '2'
84
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '2'
64
85
  @tab_folder.swt_widget.setSelection(1) if @tab_folder.swt_widget.getItemCount >= 2
65
86
  @text_editor.text_widget.setFocus
66
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '3'
87
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '3'
67
88
  @tab_folder.swt_widget.setSelection(2) if @tab_folder.swt_widget.getItemCount >= 3
68
89
  @text_editor.text_widget.setFocus
69
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '4'
70
90
  @tab_folder.swt_widget.setSelection(3) if @tab_folder.swt_widget.getItemCount >= 4
71
91
  @text_editor.text_widget.setFocus
72
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '5'
92
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '5'
73
93
  @tab_folder.swt_widget.setSelection(4) if @tab_folder.swt_widget.getItemCount >= 5
74
94
  @text_editor.text_widget.setFocus
75
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '6'
95
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '4'
96
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '6'
76
97
  @tab_folder.swt_widget.setSelection(5) if @tab_folder.swt_widget.getItemCount >= 6
77
98
  @text_editor.text_widget.setFocus
78
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '7'
99
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '7'
79
100
  @tab_folder.swt_widget.setSelection(6) if @tab_folder.swt_widget.getItemCount >= 7
80
101
  @text_editor.text_widget.setFocus
81
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '8'
102
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '8'
82
103
  @tab_folder.swt_widget.setSelection(7) if @tab_folder.swt_widget.getItemCount >= 8
83
104
  @text_editor.text_widget.setFocus
84
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '9'
105
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '9'
85
106
  @tab_folder.swt_widget.setSelection(@tab_folder.swt_widget.getItemCount - 1) if @tab_folder.swt_widget.getItemCount > 0
86
107
  @text_editor.text_widget.setFocus
87
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'g'
108
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == 'g'
88
109
  Gladiator::Dir.local_dir.selected_child.find_next
89
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'l'
110
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == 'l'
90
111
  @line_number_text.swt_widget.selectAll
91
112
  @line_number_text.swt_widget.setFocus
92
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'r'
113
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == 'r'
93
114
  @filter_text.swt_widget.selectAll
94
115
  @filter_text.swt_widget.setFocus
95
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 't'
116
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == 't'
117
+ select_tree_item unless @rename_in_progress
96
118
  @tree.swt_widget.setFocus
97
119
  elsif key_event.keyCode == swt(:esc)
98
- Dir.local_dir.selected_child_path = @text_editor.file.path
99
- @text_editor.text_widget.setFocus
120
+ if @text_editor
121
+ Dir.local_dir.selected_child_path = @text_editor.file.path
122
+ @text_editor.text_widget.setFocus
123
+ end
100
124
  end
101
125
  }
102
126
  }
@@ -116,12 +140,12 @@ module Glimmer
116
140
  observe(Gladiator::Dir.local_dir, 'selected_child') do
117
141
  select_tree_item unless @rename_in_progress
118
142
  selected_file = Gladiator::Dir.local_dir.selected_child
119
- found_tab_item = @tab_folder.swt_widget.getItems.detect {|ti| ti.getData('file_path') == selected_file.path}
143
+ found_tab_item = selected_tab_item
120
144
  if found_tab_item
121
145
  @tab_folder.swt_widget.setSelection(found_tab_item)
122
146
  @tab_item = found_tab_item.getData('tab_item')
123
147
  @text_editor = found_tab_item.getData('text_editor')
124
- else
148
+ elsif selected_file
125
149
  @tab_folder.content {
126
150
  @tab_item = tab_item { |the_tab_item|
127
151
  text selected_file.name
@@ -136,6 +160,7 @@ module Glimmer
136
160
  @tab_item.swt_tab_item.setData('file_path', selected_file.path)
137
161
  @tab_item.swt_tab_item.setData('tab_item', @tab_item)
138
162
  @tab_item.swt_tab_item.setData('text_editor', @text_editor)
163
+ @tab_item.swt_tab_item.setData('proxy', @tab_item)
139
164
  }
140
165
  @tab_folder.swt_widget.setSelection(@tab_item.swt_tab_item)
141
166
  body_root.pack_same_size
@@ -173,6 +198,9 @@ module Glimmer
173
198
  }
174
199
  on_control_moved {
175
200
  save_config
201
+ }
202
+ on_shell_deactivated {
203
+ @text_editor&.file&.write_dirty_content
176
204
  }
177
205
  composite {
178
206
  grid_layout 1, false
@@ -193,12 +221,11 @@ module Glimmer
193
221
  }
194
222
  }
195
223
  composite {
224
+ fill_layout(:vertical) {
225
+ spacing 5
226
+ }
196
227
  layout_data(:fill, :fill, true, true)
197
228
  @list = list(:border, :h_scroll, :v_scroll) {
198
- layout_data(:fill, :fill, true, true) {
199
- #exclude bind(Gladiator::Dir.local_dir, :filter) {|f| !f}
200
- minimum_height 400
201
- }
202
229
  #visible bind(Gladiator::Dir, 'local_dir.filter') {|f| !!f}
203
230
  selection bind(Gladiator::Dir.local_dir, :filtered_path)
204
231
  on_mouse_up {
@@ -207,14 +234,11 @@ module Glimmer
207
234
  on_key_pressed { |key_event|
208
235
  if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr)
209
236
  Gladiator::Dir.local_dir.selected_child_path = @list.swt_widget.getSelection.first
210
- @text_editor.text_widget.setFocus
237
+ @text_editor&.text_widget&.setFocus
211
238
  end
212
239
  }
213
240
  }
214
241
  @tree = tree(:virtual, :border, :h_scroll, :v_scroll) {
215
- layout_data(:fill, :fill, true, true) {
216
- #exclude bind(Gladiator::Dir.local_dir, :filter) {|f| !!f}
217
- }
218
242
  #visible bind(Gladiator::Dir, 'local_dir.filter') {|f| !f}
219
243
  items bind(Gladiator::Dir, :local_dir), tree_properties(children: :children, text: :name)
220
244
  menu {
@@ -262,12 +286,13 @@ module Glimmer
262
286
  @open_menu_item.swt_widget.setEnabled(!::Dir.exist?(path)) if path
263
287
  }
264
288
  on_mouse_up {
265
- Gladiator::Dir.local_dir.selected_child_path = extract_tree_item_path(@tree.swt_widget.getSelection.first)
289
+ Gladiator::Dir.local_dir.selected_child_path = extract_tree_item_path(@tree.swt_widget.getSelection&.first)
290
+ @text_editor&.text_widget&.setFocus
266
291
  }
267
292
  on_key_pressed { |key_event|
268
293
  if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr)
269
294
  Gladiator::Dir.local_dir.selected_child_path = extract_tree_item_path(@tree.swt_widget.getSelection&.first)
270
- @text_editor.text_widget.setFocus
295
+ @text_editor&.text_widget&.setFocus
271
296
  end
272
297
  }
273
298
  on_paint_control {
@@ -289,10 +314,13 @@ module Glimmer
289
314
  grid_layout 1, false
290
315
  layout_data :fill, :fill, true, true
291
316
  composite {
292
- grid_layout 2, false
317
+ grid_layout 3, false
318
+
319
+ # row 1
320
+
293
321
  @file_path_label = styled_text(:none) {
294
322
  layout_data(:fill, :fill, true, false) {
295
- horizontal_span 2
323
+ horizontal_span 3
296
324
  }
297
325
  background color(:widget_background)
298
326
  editable false
@@ -305,6 +333,9 @@ module Glimmer
305
333
  @file_path_label.swt_widget.setSelection(0, 0)
306
334
  }
307
335
  }
336
+
337
+ # row 2
338
+
308
339
  label {
309
340
  text 'Line:'
310
341
  }
@@ -315,10 +346,17 @@ module Glimmer
315
346
  text bind(Gladiator::Dir.local_dir, 'selected_child.line_number', on_read: :to_s, on_write: :to_i)
316
347
  on_key_pressed { |key_event|
317
348
  if key_event.keyCode == swt(:cr)
318
- @text_editor.text_widget.setFocus
349
+ @text_editor&.text_widget&.setFocus
319
350
  end
320
351
  }
352
+ on_verify_text { |event|
353
+ event.doit = !event.text.match(/^\d*$/).to_a.empty?
354
+ }
321
355
  }
356
+ label
357
+
358
+ # row 3
359
+
322
360
  label {
323
361
  text 'Find:'
324
362
  }
@@ -328,11 +366,32 @@ module Glimmer
328
366
  }
329
367
  text bind(Gladiator::Dir.local_dir, 'selected_child.find_text')
330
368
  on_key_pressed { |key_event|
369
+ if key_event.stateMask == swt(COMMAND_KEY) && key_event.keyCode == swt(:cr)
370
+ Dir.local_dir.selected_child.case_sensitive = !Dir.local_dir.selected_child.case_sensitive
371
+ Gladiator::Dir.local_dir.selected_child&.find_next
372
+ end
331
373
  if key_event.keyCode == swt(:cr)
332
- Gladiator::Dir.local_dir.selected_child.find_next
374
+ Gladiator::Dir.local_dir.selected_child&.find_next
333
375
  end
334
376
  }
335
377
  }
378
+ composite {
379
+ row_layout
380
+ button(:check) {
381
+ selection bind(Dir.local_dir, 'selected_child.case_sensitive')
382
+ on_key_pressed { |key_event|
383
+ if key_event.keyCode == swt(:cr)
384
+ Gladiator::Dir.local_dir.selected_child&.find_next
385
+ end
386
+ }
387
+ }
388
+ label {
389
+ text 'Case-sensitive'
390
+ }
391
+ }
392
+
393
+ # row 4
394
+
336
395
  label {
337
396
  text 'Replace:'
338
397
  }
@@ -342,14 +401,17 @@ module Glimmer
342
401
  }
343
402
  text bind(Gladiator::Dir.local_dir, 'selected_child.replace_text')
344
403
  on_focus_gained {
345
- Gladiator::Dir.local_dir.selected_child.ensure_find_next
404
+ Gladiator::Dir.local_dir.selected_child&.ensure_find_next
346
405
  }
347
406
  on_key_pressed { |key_event|
348
407
  if key_event.keyCode == swt(:cr)
349
- Gladiator::Dir.local_dir.selected_child.replace_next!
408
+ if Gladiator::Dir.local_dir.selected_child
409
+ Command.do(Gladiator::Dir.local_dir.selected_child, :replace_next!)
410
+ end
350
411
  end
351
412
  }
352
413
  }
414
+ label
353
415
  }
354
416
  @tab_folder = tab_folder {
355
417
  layout_data(:fill, :fill, true, true)
@@ -363,6 +425,9 @@ module Glimmer
363
425
  config_yaml = ::File.read(@config_file_path)
364
426
  return if config_yaml.to_s.strip.empty?
365
427
  @config = YAML.load(config_yaml)
428
+ @config[:open_file_paths].to_a.each do |file_path|
429
+ Gladiator::Dir.local_dir.selected_child_path = file_path
430
+ end
366
431
  Gladiator::Dir.local_dir.selected_child_path = @config[:selected_child_path] if @config[:selected_child_path]
367
432
  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].to_i) if @config[:caret_position]
368
433
  Gladiator::Dir.local_dir.selected_child&.top_index = @config[:top_index].to_i if @config[:top_index]
@@ -371,6 +436,8 @@ module Glimmer
371
436
  swt_widget.setLocation(@config[:shell_x], @config[:shell_y]) if @config[:shell_x] && @config[:shell_y]
372
437
  @loaded_config = true
373
438
  }
439
+ else
440
+ @loaded_config = true
374
441
  end
375
442
  end
376
443
 
@@ -386,19 +453,28 @@ module Glimmer
386
453
  shell_height: swt_widget&.getBounds&.height,
387
454
  shell_x: swt_widget&.getBounds&.x,
388
455
  shell_y: swt_widget&.getBounds&.y,
456
+ open_file_paths: Dir.local_dir.selected_child_path_history,
389
457
  }
390
458
  config_yaml = YAML.dump(@config)
391
459
  ::File.write(@config_file_path, config_yaml) unless config_yaml.to_s.empty?
392
460
  rescue => e
393
461
  puts e.full_message
394
462
  end
463
+
464
+ def selected_tab_item
465
+ @tab_folder.swt_widget.getItems.detect { |ti| ti.getData('file_path') == Gladiator::Dir.local_dir.selected_child&.path }
466
+ end
467
+
468
+ def other_tab_items
469
+ @tab_folder.swt_widget.getItems.reject { |ti| ti.getData('file_path') == Gladiator::Dir.local_dir.selected_child&.path }
470
+ end
395
471
 
396
472
  def extract_tree_item_path(tree_item)
397
473
  return if tree_item.nil?
398
474
  if tree_item.getParentItem
399
475
  ::File.join(extract_tree_item_path(tree_item.getParentItem), tree_item.getText)
400
476
  else
401
- '.'
477
+ Dir.local_dir.path
402
478
  end
403
479
  end
404
480
 
@@ -409,9 +485,10 @@ module Glimmer
409
485
  end
410
486
 
411
487
  def delete_tree_item(tree_item)
488
+ return if tree_item.nil?
412
489
  file = tree_item.getData
413
490
  parent_path = ::File.dirname(file.path)
414
- file.delete!
491
+ file.delete! # TODO consider supporting command undo/redo
415
492
  Dir.local_dir.refresh(async: false)
416
493
  parent_tree_item = @tree.depth_first_search {|ti| ti.getData.path == parent_path}.first
417
494
  @tree.swt_widget.showItem(parent_tree_item)
@@ -432,6 +509,7 @@ module Glimmer
432
509
  Dir.local_dir.pause_refresh
433
510
  tree_item = @tree.swt_widget.getSelection.first
434
511
  directory_path = extract_tree_item_path(tree_item)
512
+ return if directory_path.nil?
435
513
  if !::Dir.exist?(directory_path)
436
514
  tree_item = tree_item.getParentItem
437
515
  directory_path = ::File.dirname(directory_path)
@@ -461,42 +539,25 @@ module Glimmer
461
539
  end
462
540
 
463
541
  def rename_tree_item(tree_item, open_afterwards = false)
464
- @tree.content {
465
- @tree_text = text {
466
- focus true
467
- text tree_item.getText
468
- @action_taken = false
469
- action = lambda { |event|
470
- if !@action_taken && !@rename_in_progress
471
- @action_taken = true
472
- @rename_in_progress = true
473
- new_text = @tree_text.swt_widget.getText
474
- tree_item.setText(new_text)
475
- file = tree_item.getData
476
- file.name = new_text
477
- file_path = file.path
478
- tree_item = @tree.depth_first_search { |ti| ti.getData.path == file_path }
479
- @tree.swt_widget.showItem(tree_item.first)
480
- @tree_text.swt_widget.dispose
481
- Dir.local_dir.selected_child_path = file_path if open_afterwards
482
- Dir.local_dir.resume_refresh
483
- @rename_in_progress = false
484
- end
485
- }
486
- on_focus_lost(&action)
487
- on_key_pressed { |key_event|
488
- if key_event.keyCode == swt(:cr)
489
- action.call(key_event)
490
- elsif key_event.keyCode == swt(:esc)
491
- @tree_text.swt_widget.dispose
492
- Dir.local_dir.resume_refresh
493
- @rename_in_progress = false
494
- end
495
- }
542
+ @tree.edit_tree_item(
543
+ tree_item,
544
+ after_write: -> (edited_tree_item) {
545
+ file = edited_tree_item.getData
546
+ file_path = file.path
547
+ # TODO rename file in tab title
548
+ Dir.local_dir.selected_child_path = file_path if open_afterwards
549
+ Dir.local_dir.resume_refresh
550
+ },
551
+ after_cancel: -> {
552
+ Dir.local_dir.resume_refresh
496
553
  }
497
- @tree_text.swt_widget.selectAll
498
- }
499
- @tree_editor.setEditor(@tree_text.swt_widget, tree_item);
554
+ )
555
+ end
556
+
557
+ def extract_char(event)
558
+ event.keyCode.chr
559
+ rescue => e
560
+ nil
500
561
  end
501
562
  end
502
- end
563
+ end
@@ -17,7 +17,7 @@ module Glimmer
17
17
  grid_layout 2, false
18
18
  @line_numbers_text = text(:multi) {
19
19
  layout_data(:right, :fill, false, true)
20
- font name: 'Consolas', height: 15
20
+ font name: 'Consolas', height: OS.mac? ? 15 : 12
21
21
  background color(:widget_background)
22
22
  foreground rgb(75, 75, 75)
23
23
  text bind(file, 'line_numbers_content')
@@ -34,29 +34,42 @@ module Glimmer
34
34
  }
35
35
  @text = text(:multi, :border, :h_scroll, :v_scroll) {
36
36
  layout_data :fill, :fill, true, true
37
- font name: 'Consolas', height: 15
37
+ font name: 'Consolas', height: OS.mac? ? 15 : 12
38
38
  foreground rgb(75, 75, 75)
39
- text bind(file, 'dirty_content')
39
+ text bind(file, :content)
40
40
  focus true
41
- caret_position bind(file, 'caret_position')
41
+ selection bind(file, 'selection')
42
42
  selection_count bind(file, 'selection_count')
43
43
  top_index bind(file, 'top_index')
44
44
  on_focus_lost {
45
45
  file&.write_dirty_content
46
46
  }
47
47
  on_key_pressed { |key_event|
48
- if key_event.stateMask == swt(:command) && key_event.character.chr.downcase == '/'
49
- file.comment_line!
50
- elsif key_event.stateMask == swt(:command) && key_event.character.chr.downcase == 'k'
51
- file.kill_line!
52
- elsif key_event.stateMask == swt(:command) && key_event.character.chr.downcase == 'd'
53
- file.duplicate_line!
54
- elsif key_event.stateMask == swt(:command) && key_event.character.chr.downcase == '['
55
- file.outdent!
56
- elsif key_event.stateMask == swt(:command) && key_event.character.chr.downcase == ']'
57
- file.indent!
58
- elsif key_event.stateMask == swt(:command) && key_event.keyCode == swt('cr')
59
- file.insert_new_line!
48
+ if (Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && extract_char(key_event) == 'z') || (key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == 'y')
49
+ key_event.doit = !Command.redo(file)
50
+ elsif key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == 'z'
51
+ key_event.doit = !Command.undo(file)
52
+ elsif key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == '/'
53
+ Command.do(file, :comment_line!)
54
+ key_event.doit = false
55
+ elsif key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == 'k'
56
+ Command.do(file, :kill_line!)
57
+ key_event.doit = false
58
+ elsif key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == 'd'
59
+ Command.do(file, :duplicate_line!)
60
+ key_event.doit = false
61
+ elsif key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == '['
62
+ Command.do(file, :outdent!)
63
+ key_event.doit = false
64
+ elsif key_event.stateMask == swt(COMMAND_KEY) && extract_char(key_event) == ']'
65
+ Command.do(file, :indent!)
66
+ key_event.doit = false
67
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY, :shift) && key_event.keyCode == swt(:cr)
68
+ Command.do(file, :prefix_new_line!)
69
+ key_event.doit = false
70
+ elsif key_event.stateMask == swt(COMMAND_KEY) && key_event.keyCode == swt(:cr)
71
+ Command.do(file, :insert_new_line!)
72
+ key_event.doit = false
60
73
  elsif key_event.keyCode == swt(:page_up)
61
74
  file.page_up
62
75
  key_event.doit = false
@@ -69,11 +82,11 @@ module Glimmer
69
82
  elsif key_event.keyCode == swt(:end)
70
83
  file.end
71
84
  key_event.doit = false
72
- elsif key_event.stateMask == swt(:command) && key_event.keyCode == swt(:arrow_up)
73
- file.move_up!
85
+ elsif key_event.stateMask == swt(COMMAND_KEY) && key_event.keyCode == swt(:arrow_up)
86
+ Command.do(file, :move_up!)
74
87
  key_event.doit = false
75
- elsif key_event.stateMask == swt(:command) && key_event.keyCode == swt(:arrow_down)
76
- file.move_down!
88
+ elsif key_event.stateMask == swt(COMMAND_KEY) && key_event.keyCode == swt(:arrow_down)
89
+ Command.do(file, :move_down!)
77
90
  key_event.doit = false
78
91
  end
79
92
  }
@@ -86,7 +99,7 @@ module Glimmer
86
99
  end
87
100
  when swt(:tab)
88
101
  if file.selection_count.to_i > 0
89
- file.indent!
102
+ Command.do(file, :indent!)
90
103
  verify_event.doit = false
91
104
  else
92
105
  verify_event.text = ' '
@@ -96,6 +109,15 @@ module Glimmer
96
109
  }
97
110
  }
98
111
  }
112
+
113
+
114
+ def extract_char(event)
115
+ event.keyCode.chr
116
+ rescue => e
117
+ nil
118
+ end
119
+
99
120
  end
100
121
  end
101
122
  end
123
+
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: glimmer-cs-gladiator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Maleh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-19 00:00:00.000000000 Z
11
+ date: 2020-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: 0.1.0
19
+ - - "<"
17
20
  - !ruby/object:Gem::Version
18
- version: 0.7.4
19
- name: glimmer
21
+ version: 2.0.0
22
+ name: glimmer-dsl-swt
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.1.0
30
+ - - "<"
25
31
  - !ruby/object:Gem::Version
26
- version: 0.7.4
32
+ version: 2.0.0
27
33
  - !ruby/object:Gem::Dependency
28
34
  requirement: !ruby/object:Gem::Requirement
29
35
  requirements:
@@ -124,9 +130,11 @@ extra_rdoc_files:
124
130
  files:
125
131
  - LICENSE.txt
126
132
  - README.md
133
+ - VERSION
127
134
  - bin/gladiator
128
135
  - bin/gladiator_runner.rb
129
136
  - lib/glimmer-cs-gladiator.rb
137
+ - lib/models/glimmer/gladiator/command.rb
130
138
  - lib/models/glimmer/gladiator/dir.rb
131
139
  - lib/models/glimmer/gladiator/file.rb
132
140
  - lib/views/glimmer/gladiator.rb