glimmer-dsl-libui 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,231 @@
1
+ # Copyright (c) 2007-2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ if ARGV.include?('--bundler') && File.exist?(File.expand_path('./Gemfile'))
23
+ require 'bundler'
24
+ Bundler.setup(:default)
25
+ end
26
+ require 'fileutils'
27
+ require 'os'
28
+
29
+ module Glimmer
30
+ # Launcher of glimmer applications and main entry point for the `glimmer` command.
31
+ class Launcher
32
+ # TODO update the verbiage below for Glimmer DSL for LibUI
33
+ TEXT_USAGE = <<~MULTI_LINE_STRING
34
+ Glimmer DSL for LibUI (Prerequisite-Free Ruby Desktop Development Cross-Platform Native GUI Library) - Ruby Gem: glimmer-dsl-libui v#{File.read(File.expand_path('../../../VERSION', __FILE__))}
35
+ Usage: glimmer [--bundler] [--pd] [--quiet] [--debug] [--log-level=VALUE] [[ENV_VAR=VALUE]...] [[-ruby-option]...] (application.rb or task[task_args])
36
+
37
+ Runs Glimmer applications and tasks.
38
+
39
+ When applications are specified, they are run using Ruby,
40
+ automatically preloading the glimmer-dsl-libui Ruby gem.
41
+
42
+ Optionally, extra Glimmer options, Ruby options, and/or environment variables may be passed in.
43
+
44
+ Glimmer options:
45
+ - "--bundler=GROUP" : Activates gems in Bundler default group in Gemfile
46
+ - "--pd=BOOLEAN" : Requires puts_debuggerer to enable pd method
47
+ - "--quiet=BOOLEAN" : Does not announce file path of Glimmer application being launched
48
+ - "--debug" : Displays extra debugging information and enables debug logging
49
+ - "--log-level=VALUE" : Sets Glimmer's Ruby logger level ("ERROR" / "WARN" / "INFO" / "DEBUG"; default is none)
50
+
51
+ Tasks are run via rake. Some tasks take arguments in square brackets (surround with double-quotes if using Zsh).
52
+
53
+ Available tasks are below (if you do not see any, please add `require 'glimmer/rake_task'` to Rakefile and rerun or run rake -T):
54
+
55
+ MULTI_LINE_STRING
56
+
57
+ GLIMMER_LIB_GEM = 'glimmer-dsl-libui'
58
+ GLIMMER_LIB_LOCAL = File.expand_path(File.join('lib', "#{GLIMMER_LIB_GEM}.rb"))
59
+ GLIMMER_OPTIONS = %w[--log-level --quiet --bundler --pd]
60
+ GLIMMER_OPTION_ENV_VAR_MAPPING = {
61
+ '--log-level' => 'GLIMMER_LOGGER_LEVEL' ,
62
+ '--bundler' => 'GLIMMER_BUNDLER_SETUP' ,
63
+ '--pd' => 'PD' ,
64
+ }
65
+ REGEX_RAKE_TASK_WITH_ARGS = /^([^\[]+)\[?([^\]]*)\]?$/
66
+
67
+ class << self
68
+ def is_arm64?
69
+ host_cpu = OS.host_cpu.downcase
70
+ host_cpu.include?('aarch64') || host_cpu.include?('arm')
71
+ end
72
+
73
+ def glimmer_lib
74
+ unless @glimmer_lib
75
+ @glimmer_lib = GLIMMER_LIB_GEM
76
+ if File.exist?(GLIMMER_LIB_LOCAL)
77
+ @glimmer_lib = GLIMMER_LIB_LOCAL
78
+ puts "[DEVELOPMENT MODE] (detected #{@glimmer_lib})"
79
+ end
80
+ end
81
+ @glimmer_lib
82
+ end
83
+
84
+ def dev_mode?
85
+ glimmer_lib == GLIMMER_LIB_LOCAL
86
+ end
87
+
88
+ def glimmer_option_env_vars(glimmer_options)
89
+ GLIMMER_OPTION_ENV_VAR_MAPPING.reduce({}) do |hash, pair|
90
+ glimmer_options[pair.first] ? hash.merge(GLIMMER_OPTION_ENV_VAR_MAPPING[pair.first] => glimmer_options[pair.first]) : hash
91
+ end
92
+ end
93
+
94
+ def load_env_vars(env_vars)
95
+ env_vars.each do |key, value|
96
+ ENV[key] = value
97
+ end
98
+ end
99
+
100
+ def launch(application, ruby_options: [], env_vars: {}, glimmer_options: {})
101
+ ruby_options_string = ruby_options.join(' ') + ' ' if ruby_options.any?
102
+ env_vars = env_vars.merge(glimmer_option_env_vars(glimmer_options))
103
+ env_vars.each do |k,v|
104
+ ENV[k] = v
105
+ end
106
+ the_glimmer_lib = glimmer_lib
107
+ require 'puts_debuggerer' if the_glimmer_lib == GLIMMER_LIB_LOCAL
108
+ is_rake_task = !application.end_with?('.rb')
109
+ rake_tasks = []
110
+ if is_rake_task
111
+ load File.expand_path('./Rakefile') if File.exist?(File.expand_path('./Rakefile')) && caller.join("\n").include?('/bin/glimmer:')
112
+ require_relative 'rake_task'
113
+ rake_tasks = Rake.application.tasks.map(&:to_s).map {|t| t.sub('glimmer:', '')}
114
+
115
+ potential_rake_task_parts = application.match(REGEX_RAKE_TASK_WITH_ARGS)
116
+ application = potential_rake_task_parts[1]
117
+ rake_task_args = potential_rake_task_parts[2].split(',')
118
+ end
119
+ if rake_tasks.include?(application)
120
+ load_env_vars(glimmer_option_env_vars(glimmer_options))
121
+ rake_task = "glimmer:#{application}"
122
+ puts "Running Glimmer rake task: #{rake_task}" if ruby_options_string.to_s.include?('--debug')
123
+ Rake::Task[rake_task].invoke(*rake_task_args)
124
+ else
125
+ puts "Launching Glimmer Application: #{application}" if ruby_options_string.to_s.include?('--debug') || glimmer_options['--quiet'].to_s.downcase != 'true'
126
+ require the_glimmer_lib
127
+ load File.expand_path(application)
128
+ end
129
+ end
130
+ end
131
+
132
+ attr_reader :application_paths
133
+ attr_reader :env_vars
134
+ attr_reader :glimmer_options
135
+ attr_reader :ruby_options
136
+
137
+ def initialize(raw_options)
138
+ raw_options << '--quiet' if !caller.join("\n").include?('/bin/glimmer:') && !raw_options.join.include?('--quiet=')
139
+ raw_options << '--log-level=DEBUG' if raw_options.join.include?('--debug') && !raw_options.join.include?('--log-level=')
140
+ @application_path = extract_application_path(raw_options)
141
+ @env_vars = extract_env_vars(raw_options)
142
+ @glimmer_options = extract_glimmer_options(raw_options)
143
+ @ruby_options = raw_options
144
+ end
145
+
146
+ def launch
147
+ if @application_path.nil?
148
+ display_usage
149
+ else
150
+ launch_application
151
+ end
152
+ end
153
+
154
+ private
155
+
156
+ def launch_application
157
+ self.class.launch(
158
+ @application_path,
159
+ ruby_options: @ruby_options,
160
+ env_vars: @env_vars,
161
+ glimmer_options: @glimmer_options
162
+ )
163
+ end
164
+
165
+ def display_usage
166
+ puts TEXT_USAGE
167
+ display_tasks
168
+ end
169
+
170
+ def display_tasks
171
+ if OS.windows? || Launcher.is_arm64?
172
+ require 'rake'
173
+ Rake::TaskManager.record_task_metadata = true
174
+ require_relative 'rake_task'
175
+ tasks = Rake.application.tasks
176
+ task_lines = tasks.reject do |task|
177
+ task.comment.nil?
178
+ end.map do |task|
179
+ max_task_size = tasks.map(&:name_with_args).map(&:size).max + 1
180
+ task_name = task.name_with_args.sub('glimmer:', '')
181
+ line = "glimmer #{task_name.ljust(max_task_size)} # #{task.comment}"
182
+ end
183
+ puts task_lines.to_a
184
+ else
185
+ require 'rake-tui'
186
+ require 'tty-screen'
187
+ require_relative 'rake_task'
188
+ Rake::TUI.run(branding_header: nil, prompt_question: 'Select a Glimmer task to run:') do |task, tasks|
189
+ max_task_size = tasks.map(&:name_with_args).map(&:size).max + 1
190
+ task_name = task.name_with_args.sub('glimmer:', '')
191
+ line = "glimmer #{task_name.ljust(max_task_size)} # #{task.comment}"
192
+ bound = TTY::Screen.width - 6
193
+ line.size <= bound ? line : "#{line[0..(bound - 3)]}..."
194
+ end
195
+ end
196
+ end
197
+
198
+ # Extract application path (which can also be a rake task, basically a non-arg)
199
+ def extract_application_path(options)
200
+ application_path = options.detect do |option|
201
+ !option.start_with?('-') && !option.include?('=')
202
+ end.tap do
203
+ options.delete(application_path)
204
+ end
205
+ end
206
+
207
+ def extract_env_vars(options)
208
+ options.select do |option|
209
+ !option.start_with?('-') && option.include?('=')
210
+ end.each do |env_var|
211
+ options.delete(env_var)
212
+ end.reduce({}) do |hash, env_var_string|
213
+ match = env_var_string.match(/^([^=]+)=(.+)$/)
214
+ hash.merge(match[1] => match[2])
215
+ end
216
+ end
217
+
218
+ def extract_glimmer_options(options)
219
+ options.select do |option|
220
+ GLIMMER_OPTIONS.reduce(false) do |result, glimmer_option|
221
+ result || option.include?(glimmer_option)
222
+ end
223
+ end.each do |glimmer_option|
224
+ options.delete(glimmer_option)
225
+ end.reduce({}) do |hash, glimmer_option_string|
226
+ match = glimmer_option_string.match(/^([^=]+)=?(.+)?$/)
227
+ hash.merge(match[1] => (match[2] || 'true'))
228
+ end
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,105 @@
1
+ # Copyright (c) 2007-2023 Andy Maleh
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
22
+ require 'facets'
23
+ require 'text-table'
24
+
25
+ module Glimmer
26
+ module RakeTask
27
+ # Lists Glimmer related gems to use in rake_task.rb
28
+ class List
29
+ class << self
30
+ REGEX_GEM_LINE = /^([^\(]+) \(([^\)]+)\)$/
31
+
32
+ def custom_control_gems(query=nil)
33
+ list_gems('glimmer-cw-', query) do |result|
34
+ puts
35
+ puts " Glimmer Custom Control Gems#{" matching [#{query}]" if query} at rubygems.org:"
36
+ puts result
37
+ end
38
+ end
39
+
40
+ def custom_window_gems(query=nil)
41
+ list_gems('glimmer-cs-', query) do |result|
42
+ puts
43
+ puts " Glimmer Custom Window Gems#{" matching [#{query}]" if query} at rubygems.org:"
44
+ puts result
45
+ end
46
+ end
47
+
48
+ def custom_shape_gems(query=nil)
49
+ list_gems('glimmer-cp-', query) do |result|
50
+ puts
51
+ puts " Glimmer Custom Shape Gems#{" matching [#{query}]" if query} at rubygems.org:"
52
+ puts result
53
+ end
54
+ end
55
+
56
+ def dsl_gems(query=nil)
57
+ list_gems('glimmer-dsl-', query) do |result|
58
+ puts
59
+ puts " Glimmer DSL Gems#{" matching [#{query}]" if query} at rubygems.org:"
60
+ puts result
61
+ end
62
+ end
63
+
64
+ def list_gems(gem_prefix, query=nil, &printer)
65
+ lines = `gem search -d #{gem_prefix}`.split("\n")
66
+ gems = lines.slice_before {|l| l.match(REGEX_GEM_LINE) }.to_a
67
+ gems = gems.map do |gem|
68
+ {
69
+ name: gem[0].match(REGEX_GEM_LINE)[1],
70
+ version: gem[0].match(REGEX_GEM_LINE)[2],
71
+ author: gem[1].strip,
72
+ description: gem[4..-1]&.map(&:strip)&.join(' ').to_s
73
+ }
74
+ end.select do |gem|
75
+ query.nil? || "#{gem[:name]} #{gem[:author]} #{gem[:description]}".downcase.include?(query.to_s.downcase)
76
+ end
77
+ printer.call(tablify(gem_prefix, gems))
78
+ end
79
+
80
+ def tablify(gem_prefix, gems)
81
+ array_of_arrays = gems.map do |gem|
82
+ name, namespace = gem[:name].sub(gem_prefix, '').underscore.titlecase.split
83
+ human_name = name
84
+ human_name += " (#{namespace})" unless namespace.nil?
85
+ [
86
+ human_name,
87
+ gem[:name],
88
+ gem[:version],
89
+ gem[:author].sub('Author: ', ''),
90
+ gem[:description],
91
+ ]
92
+ end
93
+ Text::Table.new(
94
+ :head => %w[Name Gem Version Author Description],
95
+ :rows => array_of_arrays,
96
+ :horizontal_padding => 1,
97
+ :vertical_boundary => ' ',
98
+ :horizontal_boundary => ' ',
99
+ :boundary_intersection => ' '
100
+ )
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end