glimmer-cs-gladiator 0.1.4 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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