glimmer-cs-gladiator 0.1.3 → 0.1.8

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: f660a554a1e716632a2eec69dc0204d014b93b8f2e10f35f0c6b3b5a29563a47
4
- data.tar.gz: cb7758e6669b03bfbdc8925e2c6639885db5406e424edc0860bb7e713c20181c
3
+ metadata.gz: d1fedd5416ae759bea0cbfa6d14572cedd58f74d14c544a187efb9310c5954c3
4
+ data.tar.gz: fd0d141721cb77e391c6a07aea9bbb637d326c22374ffc5e2f157487116f59a2
5
5
  SHA512:
6
- metadata.gz: 6a3f4d16e7b301079ccf0af079b53304b07d392ecb12f9f9512366fd95e13ed7b658e5dfeb4f8510aa50b2d49fd4b4ed96c14cdcb0bf7049b06a594500445009
7
- data.tar.gz: 184c54cea2a6411bd5a82b078939c637b27cdb37a238e37301447655dc7e7bb646776e3ce247e57d59c088ccd5efbb407870c753b8f3511ad8dbf1604993c7ff
6
+ metadata.gz: 19c5ae152d5bbe45f434c06da679b1779b844ad180cca79a945f4368d05bb50a2342ca5d085a1ad7c8b06b6aa5a97548c98d4487ee66f0b0be3f4a16089c7d74
7
+ data.tar.gz: 3acdffb642c32c894af12b9f4fa27f51a4b04eba7c13dbedc6a5c89e6dc97da7dd1cd79c3c93a75c2c0e7318866d3de33b58ad269ffee29b221632ff21b02348
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Gladiator (Glimmer Editor) 0.1.3 - Glimmer Custom Shell
1
+ # Gladiator (Glimmer Editor) 0.1.8 - 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,25 +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
13
- - File lookup by name
14
- - Find & Replace
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
+ - Watch open file for external changes to automatically refresh in editor
15
+ - Watch project subdirectories for changes to automatically refresh in file explorer/file lookup
16
+ - Find & Replace (CMD+F)
15
17
  - Show Line Numbers
16
- - Jump to Line
17
- - Multiple tab support
18
- - Remember last opened file, caret position, top line, window size, and window location
19
- - Autosave on focus out/quit/open new file
20
- - Watch open file for external changes to reflect in editor
21
- - Watch subdirectories for changes to reflect in file explorer/file lookup
22
- - Duplicate Line(s)
23
- - Kill Line(s)
24
- - Move up one line
25
- - Move down one line
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.
26
35
 
27
36
  ## Pre-requisites
28
37
 
29
- - JRuby 9.2.11.1 (supporting Ruby 2.5.x syntax) (find at https://www.jruby.org/download)
30
- - Java SE Runtime Environment 7 or higher (find at https://www.oracle.com/java/technologies/javase-downloads.html)
38
+ - [Glimmer](https://github.com/AndyObtiva/glimmer) (Ruby Desktop Development GUI Library): '>= 0.8.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)
31
41
 
32
42
  ## Setup Instructions
33
43
 
@@ -51,7 +61,7 @@ To reuse Gladiator as a Glimmer Custom Shell inside another Glimmer application,
51
61
  following to the application's `Gemfile`:
52
62
 
53
63
  ```
54
- gem 'glimmer-cs-gladiator', '0.1.3'
64
+ gem 'glimmer-cs-gladiator', '0.1.8'
55
65
  ```
56
66
 
57
67
  Run:
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.8
@@ -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
@@ -15,41 +15,66 @@ module Glimmer
15
15
  @thread = Thread.new(@filewatcher) do |fw|
16
16
  fw.watch do |filename, event|
17
17
  if @last_update.nil? || (Time.now.to_f - @last_update) > REFRESH_DELAY
18
- dir.refresh if filename != dir.selected_child_path
18
+ dir.refresh if !filename.include?('new_file') && !dir.selected_child_path_history.include?(filename) && filename != dir.selected_child_path
19
19
  end
20
20
  @last_update = Time.now.to_f
21
21
  end
22
22
  end
23
23
  end
24
- end
24
+ end
25
25
  end
26
26
 
27
- attr_accessor :selected_child, :filter, :children, :filtered_path_options, :filtered_path
28
- attr_reader :path, :display_path
27
+ attr_accessor :selected_child, :filter, :children, :filtered_path_options, :filtered_path, :path, :display_path
28
+ attr_reader :name, :parent
29
+ attr_writer :all_children, :children
29
30
 
30
31
  def initialize(path)
31
- @path = @display_path = path
32
+ @display_path = path
33
+ @path = ::File.expand_path(@display_path)
34
+ @name = ::File.basename(::File.expand_path(path))
32
35
  self.filtered_path_options = []
33
36
  end
37
+
38
+ def name=(the_name)
39
+ self.display_path = display_path.sub(/#{Regexp.escape(@name)}$/, the_name)
40
+ @name = the_name
41
+ new_path = ::File.expand_path(display_path)
42
+ FileUtils.mv(path, new_path)
43
+ self.path = display_path
44
+ end
34
45
 
35
46
  def children
36
47
  @children ||= retrieve_children
37
48
  end
38
-
49
+
39
50
  def retrieve_children
40
- ::Dir.glob(::File.join(@path, '*')).map {|p| ::File.file?(p) ? Gladiator::File.new(p) : Gladiator::Dir.new(p)}.sort_by {|c| c.path.to_s.downcase }.sort_by {|c| c.class.name }
51
+ ::Dir.glob(::File.join(@display_path, '*')).map {|p| ::File.file?(p) ? Gladiator::File.new(p) : Gladiator::Dir.new(p)}.sort_by {|c| c.path.to_s.downcase }.sort_by {|c| c.class.name }
41
52
  end
42
53
 
43
- def refresh
54
+ def selected_child_path_history
55
+ @selected_child_path_history ||= []
56
+ end
57
+
58
+ def pause_refresh
59
+ @refresh_paused = true
60
+ end
61
+
62
+ def resume_refresh
63
+ @refresh_paused = false
64
+ end
65
+
66
+ def refresh(async: true, force: false)
67
+ return if @refresh_paused && !force
44
68
  new_all_children = retrieve_all_children
45
- new_children = retrieve_children
46
- async_exec do
47
- @all_children = new_all_children
48
- @children ||= []
49
- @children.clear
50
- new_children.each do |child|
51
- @children << child
52
- end
69
+ new_children = retrieve_children
70
+ refresh_operation = lambda do
71
+ self.all_children = new_all_children
72
+ self.children = new_children
73
+ end
74
+ if async
75
+ async_exec(&refresh_operation)
76
+ else
77
+ sync_exec(&refresh_operation)
53
78
  end
54
79
  end
55
80
 
@@ -66,7 +91,7 @@ module Glimmer
66
91
  return if filter.nil?
67
92
  all_children_files.select do |child|
68
93
  child.path.downcase.include?(filter.downcase) ||
69
- child.path.downcase.gsub(/[_\/]/, '').include?(filter.downcase)
94
+ child.path.downcase.gsub(/[_\/\.]/, '').include?(filter.downcase)
70
95
  end.sort_by {|c| c.path.to_s.downcase}
71
96
  end
72
97
 
@@ -75,7 +100,7 @@ module Glimmer
75
100
  end
76
101
 
77
102
  def retrieve_all_children
78
- ::Dir.glob(::File.join(@path, '**', '*')).map {|p| ::File.file?(p) ? Gladiator::File.new(p) : Gladiator::Dir.new(p)}
103
+ ::Dir.glob(::File.join(@display_path, '**', '*')).map {|p| ::File.file?(p) ? Gladiator::File.new(p) : Gladiator::Dir.new(p)}
79
104
  end
80
105
 
81
106
  def all_children_files
@@ -83,28 +108,46 @@ module Glimmer
83
108
  end
84
109
 
85
110
  def selected_child_path=(selected_path)
86
- if selected_path && ::File.file?(selected_path)
111
+ return if selected_path.nil? ||
112
+ ::Dir.exist?(selected_path) ||
113
+ (selected_child && ::File.expand_path(selected_child.path) == ::File.expand_path(selected_path))
114
+ if ::File.file?(selected_path)
87
115
  @selected_child&.write_dirty_content
88
116
  new_child = Gladiator::File.new(selected_path)
89
117
  begin
90
118
  unless new_child.dirty_content.nil?
91
119
  self.selected_child&.stop_filewatcher
120
+ selected_child_path_history << new_child.path if new_child && !selected_child_path_history.include?(new_child.path)
92
121
  self.selected_child = new_child
93
122
  self.selected_child.start_filewatcher
94
123
  end
95
124
  rescue
96
125
  # no op
97
126
  end
127
+ else
128
+ refresh
98
129
  end
99
130
  end
100
131
 
101
132
  def selected_child_path
102
133
  @selected_child&.path
103
134
  end
135
+
136
+ def delete!
137
+ FileUtils.rm_rf(path)
138
+ end
104
139
 
105
140
  def to_s
106
141
  path
107
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
108
151
  end
109
152
  end
110
153
  end
@@ -5,14 +5,18 @@ module Glimmer
5
5
  class File
6
6
  include Glimmer
7
7
 
8
- attr_accessor :dirty_content, :line_numbers_content, :caret_position, :selection_count, :line_number, :find_text, :replace_text, :top_index
9
- attr_reader :path, :display_path, :name
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,6 +41,42 @@ module Glimmer
36
41
  # no op in case of a binary file
37
42
  end
38
43
  end
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
+
68
+ def name=(the_name)
69
+ self.display_path = display_path.sub(/#{Regexp.escape(@name)}$/, the_name)
70
+ @name = the_name
71
+ new_path = ::File.expand_path(display_path)
72
+ FileUtils.mv(path, new_path)
73
+ self.path = new_path
74
+ end
75
+
76
+ def dirty_content=(the_content)
77
+ @dirty_content = the_content if ::File.exist?(path)
78
+ notify_observers(:content)
79
+ end
39
80
 
40
81
  def start_filewatcher
41
82
  @filewatcher = Filewatcher.new(@path)
@@ -65,6 +106,7 @@ module Glimmer
65
106
  end
66
107
 
67
108
  def write_dirty_content
109
+ return unless ::File.exist?(path)
68
110
  format_dirty_content_for_writing!
69
111
  ::File.write(path, dirty_content) if ::File.exists?(path)
70
112
  rescue => e
@@ -73,12 +115,39 @@ module Glimmer
73
115
  end
74
116
 
75
117
  def write_raw_dirty_content
118
+ return unless ::File.exist?(path)
76
119
  ::File.write(path, dirty_content) if ::File.exists?(path)
77
120
  rescue => e
78
121
  puts "Error in writing raw dirty content for #{path}"
79
122
  puts e.full_message
80
123
  end
81
-
124
+
125
+ def current_line_indentation
126
+ current_line.to_s.match(/^(\s+)/).to_a[1].to_s
127
+ end
128
+
129
+ def current_line
130
+ lines[line_number - 1]
131
+ end
132
+
133
+ def delete!
134
+ FileUtils.rm(path)
135
+ end
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
+
144
+ def insert_new_line!
145
+ the_lines = lines
146
+ the_lines[line_number...line_number] = [current_line_indentation]
147
+ self.dirty_content = the_lines.join("\n")
148
+ self.caret_position = caret_position_for_line_index(line_number) + current_line_indentation.size
149
+ end
150
+
82
151
  def comment_line!
83
152
  old_lines = lines
84
153
  return if old_lines.size < 1
@@ -150,7 +219,7 @@ module Glimmer
150
219
  delta = 0
151
220
  line_indices_for_selection(caret_position, selection_count).each do |the_line_index|
152
221
  the_line = old_lines[the_line_index]
153
- if the_line.start_with?(' ')
222
+ if the_line.to_s.start_with?(' ')
154
223
  new_lines[the_line_index] = the_line.sub(/ /, '')
155
224
  delta = -2
156
225
  elsif the_line.start_with?(' ')
@@ -207,7 +276,7 @@ module Glimmer
207
276
  end
208
277
 
209
278
  def find_next
210
- return if find_text.to_s.empty?
279
+ return if find_text.to_s.empty?
211
280
  all_lines = lines
212
281
  the_line_index = line_index_for_caret_position(caret_position)
213
282
  line_position = line_position_for_caret_position(caret_position)
@@ -218,8 +287,8 @@ module Glimmer
218
287
  the_index = (the_index + rotation)%all_lines.size
219
288
  start_position = 0
220
289
  start_position = line_position + find_text.to_s.size if i == 0 && the_index == the_line_index && found_text?(caret_position)
221
- text_to_find_in = the_line.downcase[start_position..-1]
222
- occurrence_index = text_to_find_in.index(find_text.to_s.downcase)
290
+ text_to_find_in = the_line[start_position..-1]
291
+ occurrence_index = case_sensitive ? text_to_find_in&.index(find_text.to_s) : text_to_find_in&.downcase&.index(find_text.to_s.downcase)
223
292
  if occurrence_index
224
293
  self.caret_position = caret_position_for_line_index(the_index) + start_position + occurrence_index
225
294
  self.selection_count = find_text.to_s.size
@@ -273,18 +342,22 @@ module Glimmer
273
342
  end
274
343
 
275
344
  def page_up
345
+ self.selection_count = 0
276
346
  self.line_number = [(self.line_number - 15), 1].max
277
347
  end
278
348
 
279
349
  def page_down
350
+ self.selection_count = 0
280
351
  self.line_number = [(self.line_number + 15), lines.size].min
281
352
  end
282
353
 
283
354
  def home
355
+ self.selection_count = 0
284
356
  self.line_number = 1
285
357
  end
286
358
 
287
359
  def end
360
+ self.selection_count = 0
288
361
  self.line_number = lines.size
289
362
  end
290
363
 
@@ -388,6 +461,14 @@ module Glimmer
388
461
  def to_s
389
462
  path
390
463
  end
464
+
465
+ def eql?(other)
466
+ self.path.eql?(other&.path)
467
+ end
468
+
469
+ def hash
470
+ self.path.hash
471
+ end
391
472
  end
392
473
  end
393
474
  end
@@ -1,8 +1,19 @@
1
+ begin
2
+ require 'puts_debuggerer' if ENV['puts_debuggerer'].to_s.downcase == 'true'
3
+ rescue LoadError
4
+ # no op
5
+ end
6
+ require 'fileutils'
7
+ require 'os'
8
+
1
9
  require 'models/glimmer/gladiator/dir'
2
10
  require 'models/glimmer/gladiator/file'
11
+ require 'models/glimmer/gladiator/command'
3
12
 
4
13
  require 'views/glimmer/gladiator/text_editor'
5
14
 
15
+ java_import 'org.eclipse.swt.custom.TreeEditor'
16
+
6
17
  Clipboard.implementation = Clipboard::Java
7
18
  Clipboard.copy(Clipboard.paste) # pre-initialize library to avoid slowdown during use
8
19
 
@@ -10,6 +21,8 @@ module Glimmer
10
21
  # Gladiator (Glimmer Editor)
11
22
  class Gladiator
12
23
  include Glimmer::UI::CustomShell
24
+
25
+ COMMAND_KEY = OS.mac? ? :command : :ctrl
13
26
 
14
27
  ## Add options like the following to configure CustomShell by outside consumers
15
28
  #
@@ -22,68 +35,117 @@ module Glimmer
22
35
  #
23
36
  before_body {
24
37
  Display.setAppName('Gladiator')
25
- local_dir = ENV['LOCAL_DIR'] || '.'
26
- @config_file_path = ::File.join(local_dir, '.gladiator')
27
- @config = {}
28
- Gladiator::Dir.local_dir.all_children # pre-caches children
29
38
  @display = display {
30
39
  on_event_keydown { |key_event|
31
- if Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'f'
32
- 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
33
42
  @find_text.swt_widget.setText @text_editor.text_widget.getSelectionText
34
43
  end
35
44
  @find_text.swt_widget.selectAll
36
45
  @find_text.swt_widget.setFocus
37
- 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'
38
47
  Clipboard.copy(Gladiator::Dir.local_dir.selected_child.path)
39
- 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'
40
49
  Gladiator::Dir.local_dir.selected_child.find_previous
41
- # elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == 'w'
42
- # @tab_folder.swt_widget.getItems.each(&:dispose)
43
- # elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :alt) && key_event.character.chr.downcase == 'w'
44
- # @tab_folder.swt_widget.getItems.each do |ti|
45
- # ti.dispose unless ti == @tab_folder.swt_widget.getSelection()
46
- # end
47
- # elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == 'w'
48
- # @tab_folder.swt_widget.getSelection.each(&:dispose)
49
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == ']'
50
- @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
77
+ @text_editor.text_widget.setFocus
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
80
+ @text_editor.text_widget.setFocus
81
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '1'
82
+ @tab_folder.swt_widget.setSelection(0) if @tab_folder.swt_widget.getItemCount >= 1
83
+ @text_editor.text_widget.setFocus
84
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '2'
85
+ @tab_folder.swt_widget.setSelection(1) if @tab_folder.swt_widget.getItemCount >= 2
86
+ @text_editor.text_widget.setFocus
87
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '3'
88
+ @tab_folder.swt_widget.setSelection(2) if @tab_folder.swt_widget.getItemCount >= 3
89
+ @text_editor.text_widget.setFocus
90
+ @tab_folder.swt_widget.setSelection(3) if @tab_folder.swt_widget.getItemCount >= 4
51
91
  @text_editor.text_widget.setFocus
52
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command, :shift) && key_event.character.chr.downcase == '['
53
- @tab_folder.swt_widget.setSelection([@tab_folder.swt_widget.getSelectionIndex() - 1, 0].max) if @tab_folder.swt_widget.getItemCount > 0
92
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '5'
93
+ @tab_folder.swt_widget.setSelection(4) if @tab_folder.swt_widget.getItemCount >= 5
54
94
  @text_editor.text_widget.setFocus
55
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '1'
56
- @tab_folder.swt_widget.setSelection(0) if @tab_folder.swt_widget.getItemCount > 0
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'
97
+ @tab_folder.swt_widget.setSelection(5) if @tab_folder.swt_widget.getItemCount >= 6
57
98
  @text_editor.text_widget.setFocus
58
- elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, :command) && key_event.character.chr.downcase == '9'
99
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '7'
100
+ @tab_folder.swt_widget.setSelection(6) if @tab_folder.swt_widget.getItemCount >= 7
101
+ @text_editor.text_widget.setFocus
102
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '8'
103
+ @tab_folder.swt_widget.setSelection(7) if @tab_folder.swt_widget.getItemCount >= 8
104
+ @text_editor.text_widget.setFocus
105
+ elsif Glimmer::SWT::SWTProxy.include?(key_event.stateMask, COMMAND_KEY) && extract_char(key_event) == '9'
59
106
  @tab_folder.swt_widget.setSelection(@tab_folder.swt_widget.getItemCount - 1) if @tab_folder.swt_widget.getItemCount > 0
60
107
  @text_editor.text_widget.setFocus
61
- 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'
62
109
  Gladiator::Dir.local_dir.selected_child.find_next
63
- 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'
64
111
  @line_number_text.swt_widget.selectAll
65
112
  @line_number_text.swt_widget.setFocus
66
- 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'
67
114
  @filter_text.swt_widget.selectAll
68
115
  @filter_text.swt_widget.setFocus
69
- 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
70
118
  @tree.swt_widget.setFocus
119
+ elsif key_event.keyCode == swt(:esc)
120
+ if @text_editor
121
+ Dir.local_dir.selected_child_path = @text_editor.file.path
122
+ @text_editor.text_widget.setFocus
123
+ end
71
124
  end
72
125
  }
73
126
  }
127
+
128
+ local_dir = ENV['LOCAL_DIR'] || '.'
129
+ @config_file_path = ::File.join(local_dir, '.gladiator')
130
+ @config = {}
131
+ Gladiator::Dir.local_dir.all_children # pre-caches children
74
132
  }
75
133
 
76
134
  ## Uncomment after_body block to setup observers for widgets in body
77
135
  #
78
136
  after_body {
137
+ observe(Gladiator::Dir.local_dir, 'children') do
138
+ select_tree_item unless @rename_in_progress
139
+ end
79
140
  observe(Gladiator::Dir.local_dir, 'selected_child') do
141
+ select_tree_item unless @rename_in_progress
80
142
  selected_file = Gladiator::Dir.local_dir.selected_child
81
- found_tab_item = @tab_folder.swt_widget.getItems.detect {|ti| ti.getData('file_path') == selected_file.path}
143
+ found_tab_item = selected_tab_item
82
144
  if found_tab_item
83
145
  @tab_folder.swt_widget.setSelection(found_tab_item)
84
146
  @tab_item = found_tab_item.getData('tab_item')
85
147
  @text_editor = found_tab_item.getData('text_editor')
86
- else
148
+ elsif selected_file
87
149
  @tab_folder.content {
88
150
  @tab_item = tab_item { |the_tab_item|
89
151
  text selected_file.name
@@ -98,6 +160,7 @@ module Glimmer
98
160
  @tab_item.swt_tab_item.setData('file_path', selected_file.path)
99
161
  @tab_item.swt_tab_item.setData('tab_item', @tab_item)
100
162
  @tab_item.swt_tab_item.setData('text_editor', @text_editor)
163
+ @tab_item.swt_tab_item.setData('proxy', @tab_item)
101
164
  }
102
165
  @tab_folder.swt_widget.setSelection(@tab_item.swt_tab_item)
103
166
  body_root.pack_same_size
@@ -136,6 +199,9 @@ module Glimmer
136
199
  on_control_moved {
137
200
  save_config
138
201
  }
202
+ on_shell_deactivated {
203
+ @text_editor&.file&.write_dirty_content
204
+ }
139
205
  composite {
140
206
  grid_layout 1, false
141
207
  layout_data(:fill, :fill, false, true) {
@@ -144,69 +210,117 @@ module Glimmer
144
210
  @filter_text = text {
145
211
  layout_data :fill, :center, true, false
146
212
  text bind(Gladiator::Dir.local_dir, 'filter')
147
- on_key_pressed { |key_event|
213
+ on_key_pressed { |key_event|
148
214
  if key_event.keyCode == swt(:tab) ||
149
215
  key_event.keyCode == swt(:cr) ||
150
- key_event.keyCode == swt(:lf) ||
151
216
  key_event.keyCode == swt(:arrow_up) ||
152
217
  key_event.keyCode == swt(:arrow_down)
153
218
  @list.swt_widget.select(0) if @list.swt_widget.getSelectionIndex() == -1
154
219
  @list.swt_widget.setFocus
155
- elsif key_event.keyCode == swt(:esc)
156
- @text_editor.text_widget.setFocus
157
220
  end
158
221
  }
159
222
  }
160
223
  composite {
224
+ fill_layout(:vertical) {
225
+ spacing 5
226
+ }
161
227
  layout_data(:fill, :fill, true, true)
162
228
  @list = list(:border, :h_scroll, :v_scroll) {
163
- layout_data(:fill, :fill, true, true) {
164
- #exclude bind(Gladiator::Dir.local_dir, :filter) {|f| !f}
165
- }
166
229
  #visible bind(Gladiator::Dir, 'local_dir.filter') {|f| !!f}
167
230
  selection bind(Gladiator::Dir.local_dir, :filtered_path)
168
231
  on_mouse_up {
169
232
  Gladiator::Dir.local_dir.selected_child_path = @list.swt_widget.getSelection.first
170
233
  }
171
234
  on_key_pressed { |key_event|
172
- if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr) || Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :lf)
235
+ if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr)
173
236
  Gladiator::Dir.local_dir.selected_child_path = @list.swt_widget.getSelection.first
174
- @text_editor.text_widget.setFocus
237
+ @text_editor&.text_widget&.setFocus
175
238
  end
176
239
  }
177
240
  }
178
241
  @tree = tree(:virtual, :border, :h_scroll, :v_scroll) {
179
- layout_data(:fill, :fill, true, true) {
180
- #exclude bind(Gladiator::Dir.local_dir, :filter) {|f| !!f}
181
- }
182
242
  #visible bind(Gladiator::Dir, 'local_dir.filter') {|f| !f}
183
- items bind(Gladiator::Dir, :local_dir), tree_properties(children: :children, text: :display_path)
184
- on_widget_selected {
185
- Gladiator::Dir.local_dir.selected_child_path = @tree.swt_widget.getSelection.first.getText
243
+ items bind(Gladiator::Dir, :local_dir), tree_properties(children: :children, text: :name)
244
+ menu {
245
+ @open_menu_item = menu_item {
246
+ text 'Open'
247
+ on_widget_selected {
248
+ Gladiator::Dir.local_dir.selected_child_path = extract_tree_item_path(@tree.swt_widget.getSelection.first)
249
+ }
250
+ }
251
+ menu_item(:separator)
252
+ menu_item {
253
+ text 'Delete'
254
+ on_widget_selected {
255
+ tree_item = @tree.swt_widget.getSelection.first
256
+ delete_tree_item(tree_item)
257
+ }
258
+ }
259
+ menu_item {
260
+ text 'Refresh'
261
+ on_widget_selected {
262
+ Gladiator::Dir.local_dir.refresh
263
+ }
264
+ }
265
+ menu_item {
266
+ text 'Rename'
267
+ on_widget_selected {
268
+ rename_selected_tree_item
269
+ }
270
+ }
271
+ menu_item {
272
+ text 'New Directory'
273
+ on_widget_selected {
274
+ add_new_directory_to_selected_tree_item
275
+ }
276
+ }
277
+ menu_item {
278
+ text 'New File'
279
+ on_widget_selected {
280
+ add_new_file_to_selected_tree_item
281
+ }
282
+ }
283
+ }
284
+ on_event_menudetect { |event|
285
+ path = extract_tree_item_path(@tree.swt_widget.getSelection.first)
286
+ @open_menu_item.swt_widget.setEnabled(!::Dir.exist?(path)) if path
287
+ }
288
+ on_mouse_up {
289
+ Gladiator::Dir.local_dir.selected_child_path = extract_tree_item_path(@tree.swt_widget.getSelection&.first)
290
+ @text_editor&.text_widget&.setFocus
186
291
  }
187
292
  on_key_pressed { |key_event|
188
- if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr) || Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :lf)
189
- Gladiator::Dir.local_dir.selected_child_path = @tree.swt_widget.getSelection&.first&.getText
190
- @text_editor.text_widget.setFocus
293
+ if Glimmer::SWT::SWTProxy.include?(key_event.keyCode, :cr)
294
+ Gladiator::Dir.local_dir.selected_child_path = extract_tree_item_path(@tree.swt_widget.getSelection&.first)
295
+ @text_editor&.text_widget&.setFocus
191
296
  end
192
297
  }
193
298
  on_paint_control {
194
299
  root_item = @tree.swt_widget.getItems.first
195
300
  if root_item && !root_item.getExpanded
196
- root_item.setExpanded true
301
+ root_item.setExpanded(true)
197
302
  end
198
303
  }
199
304
  }
200
305
  }
306
+
307
+ @tree_editor = TreeEditor.new(@tree.swt_widget);
308
+ @tree_editor.horizontalAlignment = swt(:left);
309
+ @tree_editor.grabHorizontal = true;
310
+ @tree_editor.minimumHeight = 20;
311
+
201
312
  }
202
313
  @editor_container = composite {
203
314
  grid_layout 1, false
204
315
  layout_data :fill, :fill, true, true
205
316
  composite {
206
- grid_layout 2, false
317
+ grid_layout 3, false
318
+
319
+ # row 1
320
+
207
321
  @file_path_label = styled_text(:none) {
208
322
  layout_data(:fill, :fill, true, false) {
209
- horizontal_span 2
323
+ horizontal_span 3
210
324
  }
211
325
  background color(:widget_background)
212
326
  editable false
@@ -219,36 +333,65 @@ module Glimmer
219
333
  @file_path_label.swt_widget.setSelection(0, 0)
220
334
  }
221
335
  }
336
+
337
+ # row 2
338
+
222
339
  label {
223
340
  text 'Line:'
224
341
  }
225
342
  @line_number_text = text {
226
343
  layout_data(:fill, :fill, true, false) {
227
- minimum_width 300
344
+ minimum_width 400
228
345
  }
229
346
  text bind(Gladiator::Dir.local_dir, 'selected_child.line_number', on_read: :to_s, on_write: :to_i)
230
347
  on_key_pressed { |key_event|
231
348
  if key_event.keyCode == swt(:cr)
232
- @text_editor.text_widget.setFocus
349
+ @text_editor&.text_widget&.setFocus
233
350
  end
234
351
  }
352
+ on_verify_text { |event|
353
+ event.doit = !event.text.match(/^\d*$/).to_a.empty?
354
+ }
235
355
  }
356
+ label
357
+
358
+ # row 3
359
+
236
360
  label {
237
361
  text 'Find:'
238
362
  }
239
363
  @find_text = text {
240
364
  layout_data(:fill, :fill, true, false) {
241
- minimum_width 300
365
+ minimum_width 400
242
366
  }
243
367
  text bind(Gladiator::Dir.local_dir, 'selected_child.find_text')
244
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
245
373
  if key_event.keyCode == swt(:cr)
246
- Gladiator::Dir.local_dir.selected_child.find_next
247
- elsif key_event.keyCode == swt(:esc)
248
- @text_editor.text_widget.setFocus
374
+ Gladiator::Dir.local_dir.selected_child&.find_next
249
375
  end
250
376
  }
251
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
+
252
395
  label {
253
396
  text 'Replace:'
254
397
  }
@@ -258,16 +401,17 @@ module Glimmer
258
401
  }
259
402
  text bind(Gladiator::Dir.local_dir, 'selected_child.replace_text')
260
403
  on_focus_gained {
261
- Gladiator::Dir.local_dir.selected_child.ensure_find_next
404
+ Gladiator::Dir.local_dir.selected_child&.ensure_find_next
262
405
  }
263
406
  on_key_pressed { |key_event|
264
407
  if key_event.keyCode == swt(:cr)
265
- Gladiator::Dir.local_dir.selected_child.replace_next!
266
- elsif key_event.keyCode == swt(:esc)
267
- @text_editor.text_widget.setFocus
408
+ if Gladiator::Dir.local_dir.selected_child
409
+ Command.do(Gladiator::Dir.local_dir.selected_child, :replace_next!)
410
+ end
268
411
  end
269
412
  }
270
413
  }
414
+ label
271
415
  }
272
416
  @tab_folder = tab_folder {
273
417
  layout_data(:fill, :fill, true, true)
@@ -281,14 +425,19 @@ module Glimmer
281
425
  config_yaml = ::File.read(@config_file_path)
282
426
  return if config_yaml.to_s.strip.empty?
283
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
284
431
  Gladiator::Dir.local_dir.selected_child_path = @config[:selected_child_path] if @config[:selected_child_path]
285
- Gladiator::Dir.local_dir.selected_child&.caret_position = Gladiator::Dir.local_dir.selected_child&.caret_position_for_caret_position_start_of_line(@config[:caret_position]) if @config[:caret_position]
286
- Gladiator::Dir.local_dir.selected_child&.top_index = @config[:top_index] if @config[:top_index]
287
- body_root.on_event_show do
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]
433
+ Gladiator::Dir.local_dir.selected_child&.top_index = @config[:top_index].to_i if @config[:top_index]
434
+ body_root.on_event_show {
288
435
  swt_widget.setSize(@config[:shell_width], @config[:shell_height]) if @config[:shell_width] && @config[:shell_height]
289
- swt_widget.setLocation(@config[:shell_x], @config[:shell_y]) if @config[:shell_x] && @config[:shell_y]
436
+ swt_widget.setLocation(@config[:shell_x], @config[:shell_y]) if @config[:shell_x] && @config[:shell_y]
290
437
  @loaded_config = true
291
- end
438
+ }
439
+ else
440
+ @loaded_config = true
292
441
  end
293
442
  end
294
443
 
@@ -304,11 +453,109 @@ module Glimmer
304
453
  shell_height: swt_widget&.getBounds&.height,
305
454
  shell_x: swt_widget&.getBounds&.x,
306
455
  shell_y: swt_widget&.getBounds&.y,
456
+ open_file_paths: Dir.local_dir.selected_child_path_history,
307
457
  }
308
458
  config_yaml = YAML.dump(@config)
309
459
  ::File.write(@config_file_path, config_yaml) unless config_yaml.to_s.empty?
310
460
  rescue => e
311
461
  puts e.full_message
312
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
471
+
472
+ def extract_tree_item_path(tree_item)
473
+ return if tree_item.nil?
474
+ if tree_item.getParentItem
475
+ ::File.join(extract_tree_item_path(tree_item.getParentItem), tree_item.getText)
476
+ else
477
+ Dir.local_dir.path
478
+ end
479
+ end
480
+
481
+ def select_tree_item
482
+ return unless Gladiator::Dir.local_dir.selected_child&.name
483
+ tree_items_to_select = @tree.depth_first_search { |ti| ti.getData.path == Gladiator::Dir.local_dir.selected_child.path }
484
+ @tree.swt_widget.setSelection(tree_items_to_select)
485
+ end
486
+
487
+ def delete_tree_item(tree_item)
488
+ file = tree_item.getData
489
+ parent_path = ::File.dirname(file.path)
490
+ file.delete! # TODO consider supporting command undo/redo
491
+ Dir.local_dir.refresh(async: false)
492
+ parent_tree_item = @tree.depth_first_search {|ti| ti.getData.path == parent_path}.first
493
+ @tree.swt_widget.showItem(parent_tree_item)
494
+ parent_tree_item.setExpanded(true)
495
+ # TODO close text editor tab
496
+ # if file.is_a?(::File)
497
+ # close tab
498
+ # end
499
+ end
500
+
501
+ def rename_selected_tree_item
502
+ Dir.local_dir.pause_refresh
503
+ tree_item = @tree.swt_widget.getSelection.first
504
+ rename_tree_item(tree_item)
505
+ end
506
+
507
+ def add_new_directory_to_selected_tree_item
508
+ Dir.local_dir.pause_refresh
509
+ tree_item = @tree.swt_widget.getSelection.first
510
+ directory_path = extract_tree_item_path(tree_item)
511
+ if !::Dir.exist?(directory_path)
512
+ tree_item = tree_item.getParentItem
513
+ directory_path = ::File.dirname(directory_path)
514
+ end
515
+ new_directory_path = ::File.expand_path(::File.join(directory_path, 'new_directory'))
516
+ FileUtils.mkdir_p(new_directory_path)
517
+ Dir.local_dir.refresh(async: false, force: true)
518
+ new_tree_item = @tree.depth_first_search {|ti| ti.getData.path == new_directory_path}.first
519
+ @tree.swt_widget.showItem(new_tree_item)
520
+ rename_tree_item(new_tree_item, true)
521
+ end
522
+
523
+ def add_new_file_to_selected_tree_item
524
+ Dir.local_dir.pause_refresh
525
+ tree_item = @tree.swt_widget.getSelection.first
526
+ directory_path = extract_tree_item_path(tree_item)
527
+ if !::Dir.exist?(directory_path)
528
+ tree_item = tree_item.getParentItem
529
+ directory_path = ::File.dirname(directory_path)
530
+ end
531
+ new_file_path = ::File.expand_path(::File.join(directory_path, 'new_file'))
532
+ FileUtils.touch(new_file_path)
533
+ Dir.local_dir.refresh(async: false, force: true)
534
+ new_tree_item = @tree.depth_first_search {|ti| ti.getData.path == new_file_path}.first
535
+ @tree.swt_widget.showItem(new_tree_item)
536
+ rename_tree_item(new_tree_item, true)
537
+ end
538
+
539
+ def rename_tree_item(tree_item, open_afterwards = false)
540
+ @tree.edit_tree_item(
541
+ tree_item,
542
+ after_write: -> (edited_tree_item) {
543
+ file = edited_tree_item.getData
544
+ file_path = file.path
545
+ # TODO rename file in tab title
546
+ Dir.local_dir.selected_child_path = file_path if open_afterwards
547
+ Dir.local_dir.resume_refresh
548
+ },
549
+ after_cancel: -> {
550
+ Dir.local_dir.resume_refresh
551
+ }
552
+ )
553
+ end
554
+
555
+ def extract_char(event)
556
+ event.keyCode.chr
557
+ rescue => e
558
+ nil
559
+ end
313
560
  end
314
- end
561
+ end
@@ -17,11 +17,11 @@ 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')
24
- top_index bind(file, 'top_index')
24
+ top_index bind(file, 'top_index', read_only: true)
25
25
  on_focus_gained {
26
26
  @text&.swt_widget.setFocus
27
27
  }
@@ -34,27 +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!
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
58
73
  elsif key_event.keyCode == swt(:page_up)
59
74
  file.page_up
60
75
  key_event.doit = false
@@ -67,20 +82,24 @@ module Glimmer
67
82
  elsif key_event.keyCode == swt(:end)
68
83
  file.end
69
84
  key_event.doit = false
70
- elsif key_event.stateMask == swt(:command) && key_event.keyCode == swt(:arrow_up)
71
- file.move_up!
85
+ elsif key_event.stateMask == swt(COMMAND_KEY) && key_event.keyCode == swt(:arrow_up)
86
+ Command.do(file, :move_up!)
72
87
  key_event.doit = false
73
- elsif key_event.stateMask == swt(:command) && key_event.keyCode == swt(:arrow_down)
74
- file.move_down!
88
+ elsif key_event.stateMask == swt(COMMAND_KEY) && key_event.keyCode == swt(:arrow_down)
89
+ Command.do(file, :move_down!)
75
90
  key_event.doit = false
76
91
  end
77
92
  }
78
93
  on_verify_text { |verify_event|
79
94
  key_code = verify_event.keyCode
80
95
  case key_code
96
+ when swt(:cr)
97
+ if file.selection_count.to_i == 0
98
+ verify_event.text += file.current_line_indentation
99
+ end
81
100
  when swt(:tab)
82
101
  if file.selection_count.to_i > 0
83
- file.indent!
102
+ Command.do(file, :indent!)
84
103
  verify_event.doit = false
85
104
  else
86
105
  verify_event.text = ' '
@@ -90,6 +109,15 @@ module Glimmer
90
109
  }
91
110
  }
92
111
  }
112
+
113
+
114
+ def extract_char(event)
115
+ event.keyCode.chr
116
+ rescue => e
117
+ nil
118
+ end
119
+
93
120
  end
94
121
  end
95
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.3
4
+ version: 0.1.8
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-16 00:00:00.000000000 Z
11
+ date: 2020-06-09 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.8.0
19
+ - - "<"
17
20
  - !ruby/object:Gem::Version
18
- version: 0.7.3
21
+ version: 2.0.0
19
22
  name: glimmer
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.8.0
30
+ - - "<"
25
31
  - !ruby/object:Gem::Version
26
- version: 0.7.3
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