namespacer-rb 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f9e088f3da0c2cad086dfb7db0d1f87a0085c7a6ec05cc6c86d27803aae2f369
4
+ data.tar.gz: 18dedbee30ad393da78a51b023969c70ba15ef1f0014442f180830164ae5786e
5
+ SHA512:
6
+ metadata.gz: 109892aa660e213db391314c4d751e9cfec65c0ac10eb2f35e66a7d6baef074438e0e86c609be626f01790107c9cb2a2875776d3698bacd321ff2911fe0c960c
7
+ data.tar.gz: f71e3f361d1ce1ad9d552b1d4fbcefbdd44609b9bedba272d6ba9befbd6bb749c31fe0ccdeaef01c8e5bed28cb394e2e402e0bb469da6edd85ce059bc7bc47da
data/.rubocop.yml ADDED
@@ -0,0 +1,18 @@
1
+ ---
2
+ require:
3
+ - rubocop-minitest
4
+ - rubocop-rake
5
+ - rubocop-performance
6
+
7
+ AllCops:
8
+ TargetRubyVersion: 3.3
9
+ NewCops: enable
10
+
11
+ Style/StringLiterals:
12
+ Enabled: true
13
+
14
+ Style/StringLiteralsInInterpolation:
15
+ Enabled: true
16
+
17
+ Layout/LineLength:
18
+ Max: 120
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2024-04-10
4
+
5
+ - Initial release
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Namespacer
2
+
3
+ TODO: Delete this and the text below, and describe your gem
4
+
5
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/namespacer`. To experiment with that code, run `bin/console` for an interactive prompt.
6
+
7
+ ## Installation
8
+
9
+ TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
10
+
11
+ Install the gem and add to the application's Gemfile by executing:
12
+
13
+ $ bundle add UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
14
+
15
+ If bundler is not being used to manage dependencies, install the gem by executing:
16
+
17
+ $ gem install UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Development
24
+
25
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
26
+
27
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
28
+
29
+ ## Contributing
30
+
31
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/namespacer.
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'minitest/test_task'
5
+
6
+ Minitest::TestTask.create
7
+
8
+ require 'rubocop/rake_task'
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[test rubocop]
data/exe/namespacer ADDED
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'namespacer'
5
+ require 'optparse'
6
+ require 'pathname'
7
+ require 'tty-command'
8
+ module Rubyists
9
+ # Namespace for the namespacer CLI
10
+ module Namespacer
11
+ CliOptions = Struct.new(:recursive, :verbose, :in_place)
12
+ def self.cli_options
13
+ @cli_options ||= CliOptions.new(verbose: false, recursive: false, in_place: false)
14
+ end
15
+
16
+ def self.cmd
17
+ @cmd = TTY::Command.new
18
+ end
19
+ end
20
+ end
21
+
22
+ options = Rubyists::Namespacer.cli_options
23
+
24
+ parser = OptionParser.new do |opts|
25
+ opts.banner = 'Usage: namespacer [options] NAMESPACE PATHS'
26
+
27
+ opts.on('-r', '--recursive', 'Recursively namespace all files in PATH') { |_| options.recursive = true }
28
+
29
+ opts.on('-i', '--in-place', 'Modify files in-place') { |_| options.in_place = true }
30
+
31
+ opts.on('-v', '--verbose', 'Verbose output') do
32
+ options.verbose = true
33
+ end
34
+ end
35
+ parser.parse!
36
+
37
+ namespace, paths = ARGV
38
+
39
+ if namespace.nil?
40
+ warn 'No namespace supplied'
41
+ warn parser
42
+ exit 1
43
+ end
44
+
45
+ if paths.nil?
46
+ warn 'No paths supplied'
47
+ warn parser
48
+ exit 2
49
+ end
50
+ paths = Array(paths) unless paths.is_a?(Array)
51
+
52
+ paths.map! do |path|
53
+ p = Pathname(path)
54
+ unless p.exist?
55
+ warn "Path #{p} does not exist"
56
+ exit 3
57
+ end
58
+ unless options.recursive || p.file?
59
+ warn "Path #{p} is not a file (use -r to recursively namespace files)"
60
+ exit 4
61
+ end
62
+ p
63
+ end
64
+
65
+ def new_path(path)
66
+ dir = path.dirname
67
+ ext = path.extname
68
+ base = path.basename(ext.to_s)
69
+ dir.join("#{base}.namespaced#{ext}")
70
+ end
71
+
72
+ def namespace_file(namespace, path) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
73
+ namespaced = Rubyists::Namespacer.namespace!(path.read, namespace)
74
+ write_path = Rubyists::Namespacer.cli_options.in_place ? path : new_path(path)
75
+ if Rubyists::Namespacer.cli_options.verbose
76
+ msg = "Namespacing #{write_path} with #{namespace}"
77
+ msg << ' (in-place)' if Rubyists::Namespacer.cli_options.in_place
78
+ warn msg
79
+ end
80
+ cmd = Rubyists::Namespacer.cmd.run(:rubocop,
81
+ '-A',
82
+ '--stdin',
83
+ write_path.basename.to_s,
84
+ '--stderr',
85
+ input: namespaced,
86
+ only_output_on_error: true)
87
+ write_path.write(cmd.out)
88
+ end
89
+
90
+ paths.each do |path|
91
+ case path
92
+ when ->(p) { p.directory? }
93
+ if options.recursive
94
+ path.find do |f|
95
+ next if f.directory?
96
+ next if f.basename.to_s.start_with?('.')
97
+ next if f.basename.to_s.end_with?('.namespaced')
98
+ next if f.basename.to_s.end_with?('.namespaced.rb')
99
+
100
+ namespace_file(namespace, f)
101
+ end
102
+ else
103
+ warn "Path #{path} is a directory, use -r to recursively namespace files"
104
+ exit 5
105
+ end
106
+ when ->(p) { p.file? }
107
+ namespace_file(namespace, path)
108
+ else
109
+ raise 'Invalid path'
110
+ end
111
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rubyists
4
+ module Namespacer
5
+ VERSION = '0.1.2'
6
+ end
7
+ end
data/lib/namespacer.rb ADDED
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'namespacer/version'
4
+ require 'parser/current'
5
+ require 'unparser'
6
+ require 'pry'
7
+
8
+ # Top-level namespace to keep Rubyists namespaces in isolation
9
+ module Rubyists
10
+ # Wrap some namespace around top-level AST nodes of 'module' or 'class' type
11
+ module Namespacer
12
+ # Do the rewriting with the rewriter class
13
+ class Rewriter < Parser::TreeRewriter
14
+ attr_accessor(:namespaces)
15
+
16
+ def initialize(namespaces)
17
+ super()
18
+ @namespaces = namespaces
19
+ end
20
+
21
+ def on_module(node)
22
+ _on_module(node)
23
+ end
24
+
25
+ def on_class(node)
26
+ _on_module(node)
27
+ end
28
+
29
+ private
30
+
31
+ def wrap(ast)
32
+ # Recursively wrap the AST in the namespace modules
33
+ namespaces.split('::').reverse.inject(ast) do |current_ast, ns|
34
+ # Create a module node with the current namespace part and the current AST
35
+ Parser::AST::Node.new(:module, [Parser::AST::Node.new(:const, [nil, ns.to_sym]), current_ast])
36
+ end
37
+ end
38
+
39
+ def _on_module(node)
40
+ return unless node.location.column.zero?
41
+
42
+ (ast, comments) = Unparser.parse_with_comments(node.location.expression.source)
43
+ replace(node.location.expression, Unparser.unparse(wrap(ast), comments))
44
+ end
45
+ end
46
+
47
+ def self.namespace!(string_or_io, namespaces)
48
+ buffer = Parser::Source::Buffer.new("(#{namespaces})")
49
+ buffer.source = string_or_io.is_a?(IO) ? string_or_io.read : string_or_io
50
+ parser = Parser::CurrentRuby.new
51
+ rewriter = Rubyists::Namespacer::Rewriter.new namespaces
52
+ rewriter.rewrite(buffer, parser.parse(buffer))
53
+ end
54
+ end
55
+ end
56
+
57
+ if $PROGRAM_NAME == __FILE__
58
+ warn 'Wrapping myself'
59
+ puts Rubyists::Namespacer.namespace!(File.read(__FILE__), 'Rubyists::Namespacer')
60
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/namespacer/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'namespacer-rb'
7
+ spec.version = Rubyists::Namespacer::VERSION
8
+ spec.authors = ['Tj (bougyman) Vanderpoel']
9
+ spec.email = ['tj@rubyists.com']
10
+
11
+ spec.summary = 'Namespace classes and modules in existing ruby source code.'
12
+ spec.description = 'For those times you realize you should have namespaced your class(es) or module(s).'
13
+ spec.homepage = 'https://github.com/rubyists/namespacer'
14
+ spec.required_ruby_version = '~> 3.3'
15
+
16
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
17
+
18
+ spec.metadata['homepage_uri'] = spec.homepage
19
+ spec.metadata['source_code_uri'] = spec.homepage
20
+ spec.metadata['changelog_uri'] = File.join(spec.homepage, '/blob/main/CHANGELOG.md')
21
+
22
+ # Specify which files should be added to the gem when it is released.
23
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
24
+ spec.files = Dir.chdir(__dir__) do
25
+ `git ls-files -z`.split("\x0").reject do |f|
26
+ (File.expand_path(f) == __FILE__) ||
27
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .github appveyor Gemfile])
28
+ end
29
+ end
30
+ spec.bindir = 'exe'
31
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
32
+ spec.require_paths = ['lib']
33
+
34
+ # Uncomment to register a new dependency of your gem
35
+ spec.add_dependency 'parser', '~> 3'
36
+ spec.add_dependency 'tty-command', '~> 0.10'
37
+ spec.add_dependency 'unparser', '~> 0.6'
38
+ spec.metadata['rubygems_mfa_required'] = 'true'
39
+ end
@@ -0,0 +1,4 @@
1
+ module Namespacer
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: namespacer-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Tj (bougyman) Vanderpoel
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2024-04-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parser
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: tty-command
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.10'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: unparser
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.6'
55
+ description: For those times you realize you should have namespaced your class(es)
56
+ or module(s).
57
+ email:
58
+ - tj@rubyists.com
59
+ executables:
60
+ - namespacer
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".rubocop.yml"
65
+ - CHANGELOG.md
66
+ - README.md
67
+ - Rakefile
68
+ - exe/namespacer
69
+ - lib/namespacer.rb
70
+ - lib/namespacer/version.rb
71
+ - namespacer.gemspec
72
+ - sig/namespacer.rbs
73
+ homepage: https://github.com/rubyists/namespacer
74
+ licenses: []
75
+ metadata:
76
+ allowed_push_host: https://rubygems.org
77
+ homepage_uri: https://github.com/rubyists/namespacer
78
+ source_code_uri: https://github.com/rubyists/namespacer
79
+ changelog_uri: https://github.com/rubyists/namespacer/blob/main/CHANGELOG.md
80
+ rubygems_mfa_required: 'true'
81
+ post_install_message:
82
+ rdoc_options: []
83
+ require_paths:
84
+ - lib
85
+ required_ruby_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.3'
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ requirements: []
96
+ rubygems_version: 3.5.3
97
+ signing_key:
98
+ specification_version: 4
99
+ summary: Namespace classes and modules in existing ruby source code.
100
+ test_files: []