singer 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +37 -0
- data/lib/singer/configuration.rb +6 -1
- data/lib/singer/option_parsing.rb +27 -6
- data/lib/singer/paths.rb +5 -1
- data/lib/singer/template.rb +4 -1
- data/lib/singer/version.rb +1 -1
- data/templates/sinatra_app/config/config.ru +1 -1
- data/templates/sinatra_app/exe/server.rb +1 -1
- data/templates/sinatra_app/lib/{__SNAKECASE_NAME__ → __PROJECT_NAME_SNAKECASE__}/hello.rb +1 -1
- data/templates/sinatra_app/lib/{__SNAKECASE_NAME__ → __PROJECT_NAME_SNAKECASE__}/server.rb +1 -1
- data/templates/sinatra_app/test/server/test_server.rb +1 -1
- data/templates/sinatra_app/test/server/test_server_error_dumping.rb +1 -1
- data/templates/sinatra_app/test/test_hello.rb +1 -1
- data/templates/sinatra_app/views/layout.haml +1 -1
- data/templates/tdd/lib/{__SNAKECASE_NAME__.rb → __PROJECT_NAME_SNAKECASE__.rb} +2 -2
- data/templates/tdd/test/test___PROJECT_NAME_SNAKECASE__.rb +16 -0
- metadata +6 -6
- data/templates/tdd/test/test___SNAKECASE_NAME__.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd871af4e10b86d0362c5bef72223344e86d5f81cb6a2871e901ec588f2d97b8
|
4
|
+
data.tar.gz: 5bbab829554eee4d7da41e43f07fec57784269906da6a7f866a466a73f1a9e92
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ba2fecb7f5b4a230e5eb26d7e8fef5566e1753fec82952b431779b7720fc3c525beb26a9e9e977c2d328648b11531e1bc4e760c1edbde219f1f025abb0be72d9
|
7
|
+
data.tar.gz: 3f121f9b2383ef48b822e1dac292e5a9f8455ded6cb9816b4fcd79b8139e64d46709c5fd2f9473cb200a1f8fc4808586e16bcfad574d91c86c8892bb67aba96a
|
data/README.md
CHANGED
@@ -17,6 +17,43 @@ Run `singer --list-templates` to see available templates' names, both shipped wi
|
|
17
17
|
|
18
18
|
For `PROJECT_NAME`, using `snake_case` is best, although an attempt will be made to understand `CamelCase`, too.
|
19
19
|
|
20
|
+
## Writing your own templates
|
21
|
+
|
22
|
+
Many features of Singer will become clearer when seeing actual usage - please feel encouraged to examine the templates shipped with the gem (you can find them in `templates_from_gem` shown by the `singer --show-paths`).
|
23
|
+
|
24
|
+
### Template location
|
25
|
+
|
26
|
+
User-provided templates should be placed in the directory named `templates_from_user` in the `singer --show-paths` output.
|
27
|
+
Each template resides in a subdirectory - the subdirectory's name becomes the template's name, and is not included in the generated paths (Singer will only replicate the directory structure _inside_ it).
|
28
|
+
|
29
|
+
### Variables available to templates
|
30
|
+
|
31
|
+
Templates written in ERB or other templating mechanisms that execute Ruby code will have access to Singer::CONFIGURATION object and its accessors. For example, the following code in a `my_template`'s file:
|
32
|
+
```ruby
|
33
|
+
class <%= Singer::CONFIGURATION.project_name_camelcase %>
|
34
|
+
```
|
35
|
+
will, when Singer is called with `singer my_template foo_bar_baz`, result in this written to output file:
|
36
|
+
```ruby
|
37
|
+
class FooBarBaz
|
38
|
+
```
|
39
|
+
|
40
|
+
To see an up-to-date list of available variables, run `singer --list-variables`.
|
41
|
+
|
42
|
+
### Special segments in template paths
|
43
|
+
|
44
|
+
Any of the variables above can be also used in paths/filenames of template files, capitalized and surrounded by double underscores.
|
45
|
+
So, if `my_template` has a file at this path:
|
46
|
+
```
|
47
|
+
docs_for___PROJECT_NAME_SNAKECASE__/__PROJECT_NAME_CAMELCASE__ - humble beginnings.txt
|
48
|
+
```
|
49
|
+
and you run `singer my_template alpha_beta`, a file named like this will be created:
|
50
|
+
```
|
51
|
+
docs_for_alpha_beta/AlphaBeta - humble beginnings.txt
|
52
|
+
```
|
53
|
+
|
54
|
+
Tiny caveat for completeness - while `template_file_name_actual` can be used inside template files, the `__TEMPLATE_FILE_NAME_ACTUAL__` will not be substituted in paths.
|
55
|
+
"Stack level too deep" and all that ;)
|
56
|
+
|
20
57
|
## Development
|
21
58
|
|
22
59
|
```bash
|
data/lib/singer/configuration.rb
CHANGED
@@ -1,4 +1,9 @@
|
|
1
1
|
module Singer
|
2
2
|
# holds settings
|
3
|
-
CONFIGURATION = Struct.new(
|
3
|
+
CONFIGURATION = Struct.new(
|
4
|
+
:template_name,
|
5
|
+
:project_name_original, :project_name_camelcase, :project_name_snakecase,
|
6
|
+
:template_file_name_original, :template_file_name_actual,
|
7
|
+
).new
|
8
|
+
CONFIGURATION_VARIABLES_FORBIDDEN_IN_PATHS = %w[template_file_name_actual].freeze
|
4
9
|
end
|
@@ -3,7 +3,7 @@ module Singer
|
|
3
3
|
class OptionParsing
|
4
4
|
DEFAULT_TEMPLATE_NAME = 'tdd'.freeze
|
5
5
|
|
6
|
-
def self.configure(argvies) # rubocop:disable Metrics/MethodLength
|
6
|
+
def self.configure(argvies) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
7
7
|
options = {}
|
8
8
|
OptionParser.new do |parser|
|
9
9
|
parser.banner = <<~USAGE
|
@@ -17,6 +17,14 @@ module Singer
|
|
17
17
|
list_all_templates
|
18
18
|
Kernel.exit
|
19
19
|
end
|
20
|
+
parser.on('--show-paths', 'show paths used to load files') do
|
21
|
+
show_paths
|
22
|
+
Kernel.exit
|
23
|
+
end
|
24
|
+
parser.on('--list-variables', 'list all variables available to templates') do
|
25
|
+
list_variables
|
26
|
+
Kernel.exit
|
27
|
+
end
|
20
28
|
end.parse!(argvies, into: options)
|
21
29
|
|
22
30
|
raise NameMissingError, 'Missing mandatory argument PROJECT_NAME' if argvies.empty?
|
@@ -26,15 +34,28 @@ module Singer
|
|
26
34
|
end
|
27
35
|
|
28
36
|
def self.list_all_templates
|
29
|
-
|
30
|
-
|
31
|
-
|
37
|
+
columnize_hash(Template.all.transform_values(&:path))
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.show_paths
|
41
|
+
columnize_hash(%w[singer_config_dir templates_from_user templates_from_gem].to_h{ [_1, Paths.send(_1)] })
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.columnize_hash(hash)
|
45
|
+
first_column_width = hash.keys.map(&:length).max
|
46
|
+
hash.each do |k, v|
|
47
|
+
puts "#{k.to_s.ljust(first_column_width)} #{v}"
|
32
48
|
end
|
33
49
|
end
|
34
50
|
|
51
|
+
def self.list_variables
|
52
|
+
puts CONFIGURATION.members
|
53
|
+
end
|
54
|
+
|
35
55
|
def self.encase_name(name)
|
36
|
-
CONFIGURATION.
|
37
|
-
CONFIGURATION.
|
56
|
+
CONFIGURATION.project_name_original = name
|
57
|
+
CONFIGURATION.project_name_snakecase = name.gsub(/(\w)([A-Z])/){ "#{$1}_#{$2}" }.gsub(/_+/, '_').downcase
|
58
|
+
CONFIGURATION.project_name_camelcase = CONFIGURATION.project_name_snakecase.split('_').map(&:capitalize).join
|
38
59
|
end
|
39
60
|
end
|
40
61
|
end
|
data/lib/singer/paths.rb
CHANGED
@@ -21,12 +21,16 @@ module Singer
|
|
21
21
|
File.join(...).gsub(/__([[:alpha:]][[:word:]]+)__/) do |match|
|
22
22
|
potential_config = $1.downcase
|
23
23
|
|
24
|
-
if
|
24
|
+
if variable_name_can_be_substituted?(potential_config)
|
25
25
|
CONFIGURATION.send(potential_config)
|
26
26
|
else
|
27
27
|
match
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
def self.variable_name_can_be_substituted?(name)
|
33
|
+
CONFIGURATION.respond_to?(name) && !CONFIGURATION_VARIABLES_FORBIDDEN_IN_PATHS.include?(name)
|
34
|
+
end
|
31
35
|
end
|
32
36
|
end
|
data/lib/singer/template.rb
CHANGED
@@ -31,9 +31,12 @@ module Singer
|
|
31
31
|
|
32
32
|
def generate(output_path)
|
33
33
|
files.each do |file|
|
34
|
-
|
34
|
+
CONFIGURATION.template_file_name_original = file
|
35
35
|
target_file = Paths.output_path(output_path, file)
|
36
|
+
CONFIGURATION.template_file_name_actual = target_file
|
37
|
+
|
36
38
|
FileUtils.mkdir_p(File.dirname(target_file))
|
39
|
+
source_file = File.join(path, file)
|
37
40
|
TemplatingMethods.send(:erb, source_file, target_file)
|
38
41
|
end
|
39
42
|
end
|
data/lib/singer/version.rb
CHANGED
@@ -3,7 +3,7 @@ require 'haml'
|
|
3
3
|
require 'sassc'
|
4
4
|
require 'colorize'
|
5
5
|
|
6
|
-
module <%= Singer::CONFIGURATION.
|
6
|
+
module <%= Singer::CONFIGURATION.project_name_camelcase %>
|
7
7
|
# Sinatra app with routes
|
8
8
|
class Server < Sinatra::Base
|
9
9
|
set :root, '.' # to make directory structure with views/ work
|
@@ -10,7 +10,7 @@ class TestServerErrorDumping < Minitest::Test
|
|
10
10
|
refute message.lines.any?{ _1.include?('/vendor/') } # now you don't
|
11
11
|
end
|
12
12
|
|
13
|
-
app = <%= Singer::CONFIGURATION.
|
13
|
+
app = <%= Singer::CONFIGURATION.project_name_camelcase %>::Server.new! # .new! returns real instance without Sinatra::Wrapper
|
14
14
|
app.dump_errors!(exc, log)
|
15
15
|
end
|
16
16
|
|
@@ -3,6 +3,6 @@ require 'minitest_helper'
|
|
3
3
|
# TODO: remove
|
4
4
|
class TestHello < Minitest::Test
|
5
5
|
def test_greet_with_a_param_generates_a_greeting_string
|
6
|
-
assert_equal 'Hello, stranger.', <%= Singer::CONFIGURATION.
|
6
|
+
assert_equal 'Hello, stranger.', <%= Singer::CONFIGURATION.project_name_camelcase %>::Hello.greet(:stranger)
|
7
7
|
end
|
8
8
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'colorize'
|
2
2
|
# require 'awesome_print'
|
3
3
|
|
4
|
-
class <%= Singer::CONFIGURATION.
|
4
|
+
class <%= Singer::CONFIGURATION.project_name_camelcase %>
|
5
5
|
def hello(who:)
|
6
6
|
"Hello, #{who}."
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
10
|
if File.expand_path($PROGRAM_NAME) == File.expand_path(__FILE__)
|
11
|
-
ciastka = <%= Singer::CONFIGURATION.
|
11
|
+
ciastka = <%= Singer::CONFIGURATION.project_name_camelcase %>.new
|
12
12
|
puts "Testing testing: #{ciastka.hello(who: :world).green}"
|
13
13
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'minitest/rg'
|
2
|
+
require 'minitest/autorun' if $PROGRAM_NAME == __FILE__
|
3
|
+
|
4
|
+
require_relative '../lib/<%= Singer::CONFIGURATION.project_name_snakecase %>'
|
5
|
+
|
6
|
+
class Test<%= Singer::CONFIGURATION.project_name_camelcase %> < Minitest::Test
|
7
|
+
# TEST_INPUT = File.read('input_mini.txt').lines(chomp: true)
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@<%= Singer::CONFIGURATION.project_name_snakecase %> = <%= Singer::CONFIGURATION.project_name_camelcase %>.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_hello_interpolates_into_string
|
14
|
+
assert_equal 'Hello, world.', @<%= Singer::CONFIGURATION.project_name_snakecase %>.hello(who: :world)
|
15
|
+
end
|
16
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: singer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Emil Chludziński
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-02-09 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: erb
|
@@ -48,8 +48,8 @@ files:
|
|
48
48
|
- templates/sinatra_app/config/config.ru
|
49
49
|
- templates/sinatra_app/config/puma.rb
|
50
50
|
- templates/sinatra_app/exe/server.rb
|
51
|
-
- templates/sinatra_app/lib/
|
52
|
-
- templates/sinatra_app/lib/
|
51
|
+
- templates/sinatra_app/lib/__PROJECT_NAME_SNAKECASE__/hello.rb
|
52
|
+
- templates/sinatra_app/lib/__PROJECT_NAME_SNAKECASE__/server.rb
|
53
53
|
- templates/sinatra_app/lib/zeitwerk_setup.rb
|
54
54
|
- templates/sinatra_app/test/minitest_helper.rb
|
55
55
|
- templates/sinatra_app/test/server/test_server.rb
|
@@ -60,8 +60,8 @@ files:
|
|
60
60
|
- templates/sinatra_app/views/layout.haml
|
61
61
|
- templates/sinatra_app/views/style.sass
|
62
62
|
- templates/tdd/Gemfile
|
63
|
-
- templates/tdd/lib/
|
64
|
-
- templates/tdd/test/
|
63
|
+
- templates/tdd/lib/__PROJECT_NAME_SNAKECASE__.rb
|
64
|
+
- templates/tdd/test/test___PROJECT_NAME_SNAKECASE__.rb
|
65
65
|
homepage: https://gitlab.com/tanstaafl/singer/
|
66
66
|
licenses:
|
67
67
|
- MIT
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'minitest/rg'
|
2
|
-
require 'minitest/autorun' if $PROGRAM_NAME == __FILE__
|
3
|
-
|
4
|
-
require_relative '../lib/<%= Singer::CONFIGURATION.snakecase_name %>'
|
5
|
-
|
6
|
-
class Test<%= Singer::CONFIGURATION.camelcase_name %> < Minitest::Test
|
7
|
-
# TEST_INPUT = File.read('input_mini.txt').lines(chomp: true)
|
8
|
-
|
9
|
-
def setup
|
10
|
-
@<%= Singer::CONFIGURATION.snakecase_name %> = <%= Singer::CONFIGURATION.camelcase_name %>.new
|
11
|
-
end
|
12
|
-
|
13
|
-
def test_hello_interpolates_into_string
|
14
|
-
assert_equal 'Hello, world.', @<%= Singer::CONFIGURATION.snakecase_name %>.hello(who: :world)
|
15
|
-
end
|
16
|
-
end
|