elisp2any 0.0.4 → 0.0.6

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +12 -0
  3. data/LICENSE.txt +674 -202
  4. data/README.md +15 -5
  5. data/Rakefile +1 -46
  6. data/exe/elisp2any +4 -5
  7. data/lib/elisp/comment.rb +93 -0
  8. data/lib/elisp/parser.rb +188 -0
  9. data/lib/elisp.rb +142 -0
  10. data/lib/elisp2any/aside.rb +23 -0
  11. data/lib/elisp2any/blanklines.rb +7 -4
  12. data/lib/elisp2any/code.rb +26 -12
  13. data/lib/elisp2any/codeblock.rb +56 -0
  14. data/lib/elisp2any/comment.rb +3 -1
  15. data/lib/elisp2any/commentary.rb +10 -7
  16. data/lib/elisp2any/expression.rb +81 -5
  17. data/lib/elisp2any/footer_line.rb +28 -0
  18. data/lib/elisp2any/header_line.rb +40 -7
  19. data/lib/elisp2any/heading.rb +21 -4
  20. data/lib/elisp2any/html_renderer/index.html.erb +16 -16
  21. data/lib/elisp2any/html_renderer.erb +22 -0
  22. data/lib/elisp2any/html_renderer.rb +98 -12
  23. data/lib/elisp2any/inline_code.rb +1 -0
  24. data/lib/elisp2any/line.rb +5 -3
  25. data/lib/elisp2any/paragraph.rb +3 -4
  26. data/lib/elisp2any/section.rb +32 -8
  27. data/lib/elisp2any/text.rb +33 -0
  28. data/lib/elisp2any/version.rb +2 -1
  29. data/lib/elisp2any.rb +19 -1
  30. metadata +14 -80
  31. data/.document +0 -4
  32. data/.envrc +0 -3
  33. data/.rdoc_options +0 -2
  34. data/.rubocop.yml +0 -11
  35. data/lib/elisp2any/asciidoc_renderer/index.adoc.erb +0 -15
  36. data/lib/elisp2any/asciidoc_renderer.rb +0 -57
  37. data/lib/elisp2any/code_block.rb +0 -16
  38. data/lib/elisp2any/file.rb +0 -47
  39. data/lib/elisp2any/filename.rb +0 -14
  40. data/lib/elisp2any/header_line_variable_assignment.rb +0 -27
  41. data/lib/elisp2any/header_line_variables.rb +0 -33
  42. data/lib/elisp2any/node.rb +0 -66
  43. data/lib/elisp2any/top_heading.rb +0 -21
  44. data/lib/elisp2any/tree_sitter_parser.rb +0 -36
  45. data/lib/elisp2any/variable.rb +0 -14
  46. data/manifest.scm +0 -87
  47. data/sig/elisp2any.gen.rbs +0 -112
  48. data/sig/elisp2any.rbs +0 -4
metadata CHANGED
@@ -1,43 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elisp2any
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - gemmaro
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-02-08 00:00:00.000000000 Z
11
+ date: 2025-06-22 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: ruby_tree_sitter
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 0.20.8.1
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 0.20.8.1
27
- - !ruby/object:Gem::Dependency
28
- name: asciidoctor
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
13
  - !ruby/object:Gem::Dependency
42
14
  name: rake
43
15
  requirement: !ruby/object:Gem::Requirement
@@ -52,20 +24,6 @@ dependencies:
52
24
  - - "~>"
53
25
  - !ruby/object:Gem::Version
54
26
  version: '13.0'
55
- - !ruby/object:Gem::Dependency
56
- name: rubocop
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.21'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.21'
69
27
  - !ruby/object:Gem::Dependency
70
28
  name: test-unit
71
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,22 +38,8 @@ dependencies:
80
38
  - - "~>"
81
39
  - !ruby/object:Gem::Version
82
40
  version: '3.0'
83
- - !ruby/object:Gem::Dependency
84
- name: webrick
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
41
  description: elisp2any is a command line tool and library for converting Emacs Lisp
98
- source to some document markup, such as HTML or AsciiDoc.
42
+ source to some document markup, such as HTML.
99
43
  email:
100
44
  - gemmaro.dev@gmail.com
101
45
  executables:
@@ -103,10 +47,6 @@ executables:
103
47
  extensions: []
104
48
  extra_rdoc_files: []
105
49
  files:
106
- - ".document"
107
- - ".envrc"
108
- - ".rdoc_options"
109
- - ".rubocop.yml"
110
50
  - CHANGELOG.md
111
51
  - Gemfile
112
52
  - LICENSE.txt
@@ -114,38 +54,32 @@ files:
114
54
  - Rakefile
115
55
  - exe/elisp2any
116
56
  - fixtures/init.el
57
+ - lib/elisp.rb
58
+ - lib/elisp/comment.rb
59
+ - lib/elisp/parser.rb
117
60
  - lib/elisp2any.rb
118
- - lib/elisp2any/asciidoc_renderer.rb
119
- - lib/elisp2any/asciidoc_renderer/index.adoc.erb
61
+ - lib/elisp2any/aside.rb
120
62
  - lib/elisp2any/blanklines.rb
121
63
  - lib/elisp2any/code.rb
122
- - lib/elisp2any/code_block.rb
64
+ - lib/elisp2any/codeblock.rb
123
65
  - lib/elisp2any/comment.rb
124
66
  - lib/elisp2any/commentary.rb
125
67
  - lib/elisp2any/expression.rb
126
- - lib/elisp2any/file.rb
127
- - lib/elisp2any/filename.rb
68
+ - lib/elisp2any/footer_line.rb
128
69
  - lib/elisp2any/header_line.rb
129
- - lib/elisp2any/header_line_variable_assignment.rb
130
- - lib/elisp2any/header_line_variables.rb
131
70
  - lib/elisp2any/heading.rb
71
+ - lib/elisp2any/html_renderer.erb
132
72
  - lib/elisp2any/html_renderer.rb
133
73
  - lib/elisp2any/html_renderer/index.html.erb
134
74
  - lib/elisp2any/inline_code.rb
135
75
  - lib/elisp2any/line.rb
136
- - lib/elisp2any/node.rb
137
76
  - lib/elisp2any/paragraph.rb
138
77
  - lib/elisp2any/section.rb
139
- - lib/elisp2any/top_heading.rb
140
- - lib/elisp2any/tree_sitter_parser.rb
141
- - lib/elisp2any/variable.rb
78
+ - lib/elisp2any/text.rb
142
79
  - lib/elisp2any/version.rb
143
- - manifest.scm
144
- - sig/elisp2any.gen.rbs
145
- - sig/elisp2any.rbs
146
80
  homepage: https://codeberg.org/gemmaro/elisp2any
147
81
  licenses:
148
- - Apache-2.0
82
+ - GPL-3.0-or-later
149
83
  metadata:
150
84
  rubygems_mfa_required: 'true'
151
85
  bug_tracker_uri: https://codeberg.org/gemmaro/elisp2any/issues
@@ -162,14 +96,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
162
96
  requirements:
163
97
  - - ">="
164
98
  - !ruby/object:Gem::Version
165
- version: 2.6.0
99
+ version: '3.1'
166
100
  required_rubygems_version: !ruby/object:Gem::Requirement
167
101
  requirements:
168
102
  - - ">="
169
103
  - !ruby/object:Gem::Version
170
104
  version: '0'
171
105
  requirements: []
172
- rubygems_version: 3.3.26
106
+ rubygems_version: 3.3.27
173
107
  signing_key:
174
108
  specification_version: 4
175
109
  summary: Converter from Emacs Lisp to some document markup
data/.document DELETED
@@ -1,4 +0,0 @@
1
- README.md
2
- lib/**/*.rb
3
- CHANGELOG.md
4
- LICENSE.txt
data/.envrc DELETED
@@ -1,3 +0,0 @@
1
- watch_file manifest.scm
2
- export ELISP2ANY_GUIX_USE_PROFILE_PATH=yes
3
- use guix
data/.rdoc_options DELETED
@@ -1,2 +0,0 @@
1
- main_page: README.md
2
- op_dir: html
data/.rubocop.yml DELETED
@@ -1,11 +0,0 @@
1
- AllCops:
2
- TargetRubyVersion: 2.6
3
- NewCops: enable
4
- DisabledByDefault: true
5
-
6
- Layout/LineLength:
7
- Enabled: false
8
-
9
- Style/FrozenStringLiteralComment:
10
- Enabled: true
11
- EnforcedStyle: never
@@ -1,15 +0,0 @@
1
- = <%= name %>
2
-
3
- <%= synopsis %>
4
-
5
- == Commentary
6
-
7
- <% commentary.each do |paragraph| %>
8
- <%= render_paragraph(paragraph) %>
9
- <% end %>
10
-
11
- == Code
12
-
13
- <% code.each do |block| %>
14
- <%= render_block(block, level: 2) %>
15
- <% end %>
@@ -1,57 +0,0 @@
1
- require 'forwardable'
2
-
3
- module Elisp2any
4
- # This renderer is experimental.
5
- class AsciiDocRenderer
6
- def initialize(file)
7
- @file = file
8
- end
9
-
10
- def render
11
- erb_renderer('index.adoc.erb')
12
- end
13
-
14
- private
15
-
16
- def render_paragraph(paragraph)
17
- adoc = ''
18
- paragraph.each do |line|
19
- line.each do |chunk|
20
- case chunk
21
- when InlineCode
22
- adoc << "``#{chunk.content}``"
23
- when String
24
- adoc << chunk
25
- end
26
- end
27
- end
28
- adoc
29
- end
30
-
31
- def render_block(block, level:)
32
- adoc = ''
33
- case block
34
- when Heading
35
- prefix = '=' * (level + block.level - 1)
36
- adoc << "#{prefix} #{block.content}"
37
- when Paragraph
38
- adoc << render_paragraph(block)
39
- when CodeBlock
40
- adoc << <<~ADOC
41
- ----
42
- #{block.content}
43
- ----
44
- ADOC
45
- end
46
- adoc
47
- end
48
-
49
- def erb_renderer(path)
50
- source = ::File.read(::File.join(__dir__, 'asciidoc_renderer', path))
51
- ERB.new(source).result(binding)
52
- end
53
-
54
- extend Forwardable # :nodoc:
55
- def_delegators :@file, :name, :synopsis, :commentary, :code
56
- end
57
- end
@@ -1,16 +0,0 @@
1
- require 'forwardable'
2
-
3
- module Elisp2any
4
- class CodeBlock # :nodoc:
5
- def initialize(node) # :nodoc:
6
- @node = node
7
- end
8
-
9
- def append(source, end_byte) # :nodoc:
10
- @node.append(source, end_byte)
11
- end
12
-
13
- extend Forwardable # :nodoc:
14
- def_delegators :@node, :content
15
- end
16
- end
@@ -1,47 +0,0 @@
1
- require_relative 'node'
2
- require_relative 'tree_sitter_parser'
3
- require "elisp2any/header_line"
4
- require "elisp2any/blanklines"
5
- require "elisp2any/commentary"
6
- require "elisp2any/code"
7
-
8
- module Elisp2any
9
- class File
10
- attr_reader :name, # TODO: filename
11
- :synopsis, # TODO: header_line, including description
12
- :commentary, :code
13
-
14
- def self.scan(scanner)
15
- scanner = StringScanner.new(scanner) unless scanner.respond_to?(:skip)
16
- line = HeaderLine.scan(scanner) or return
17
- Blanklines.scan(scanner) # optional
18
- commentary = Commentary.scan(scanner)
19
- Blanklines.scan(scanner) # optional
20
- code = Code.scan(scanner)
21
- new(name: line.filename, synopsis: line.description, commentary:, code:)
22
- end
23
-
24
- def self.parse(source)
25
- source = source.respond_to?(:read) ? source.read : source
26
- ts_node = TreeSitterParser.parse(source)
27
- first_heading, second_heading, *nodes, last_heading = Node.from_tree_sitter(source, ts_node)
28
- name, synopsis = first_heading.name_and_synopsis
29
- second_heading.commentary? or raise Error, "no commentary heading: #{second_heading.inspect}"
30
- commentary = []
31
- until nodes.empty?
32
- (node = nodes.shift).code? and break
33
- commentary << node
34
- end
35
- code = nodes
36
- last_heading.final_name == name or raise Error, 'different names'
37
- new(name: name, synopsis: synopsis, commentary: commentary, code: code)
38
- end
39
-
40
- def initialize(name:, synopsis:, commentary:, code:) # :nodoc:
41
- @name = name
42
- @synopsis = synopsis
43
- @commentary = commentary
44
- @code = code
45
- end
46
- end
47
- end
@@ -1,14 +0,0 @@
1
- module Elisp2any
2
- class Filename
3
- attr_reader :content
4
-
5
- def self.scan(scanner)
6
- content = scanner.scan(/[a-z]+[.]el\b/) or return
7
- new(content:)
8
- end
9
-
10
- def initialize(content:)
11
- @content = content
12
- end
13
- end
14
- end
@@ -1,27 +0,0 @@
1
- require "elisp2any/variable"
2
- require "elisp2any/expression"
3
-
4
- module Elisp2any
5
- class HeaderLineVariableAssignment
6
- attr_reader :variable, :expression
7
-
8
- def self.scan(scanner)
9
- pos = scanner.pos
10
- variable = Variable.scan(scanner) or return
11
- unless scanner.skip(/ *: */)
12
- scanner.pos = pos
13
- return
14
- end
15
- unless (expression = Expression.scan(scanner))
16
- scanner.pos = pos
17
- return
18
- end
19
- new(variable: variable.name, expression: expression.content)
20
- end
21
-
22
- def initialize(variable:, expression:)
23
- @variable = variable
24
- @expression = expression
25
- end
26
- end
27
- end
@@ -1,33 +0,0 @@
1
- require "elisp2any/variable"
2
- require "elisp2any/expression"
3
- require "elisp2any/header_line_variable_assignment"
4
-
5
- module Elisp2any
6
- class HeaderLineVariables
7
- attr_reader :variables
8
-
9
- def self.scan(scanner)
10
- scanner = StringScanner.new(scanner) unless scanner.respond_to?(:pos)
11
- pos = scanner.pos
12
- scanner.skip(/ *-[*]- +/) or return
13
- variables = {}
14
- until scanner.skip(/ +-[*]- */)
15
- if scanner.eos?
16
- scanner.pos = pos
17
- return
18
- elsif (assign = HeaderLineVariableAssignment.scan(scanner))
19
- variables[assign.variable] = assign.expression
20
- elsif scanner.skip(";")
21
- break
22
- else
23
- raise scanner.inspect
24
- end
25
- end
26
- new(variables:)
27
- end
28
-
29
- def initialize(variables:)
30
- @variables = variables
31
- end
32
- end
33
- end
@@ -1,66 +0,0 @@
1
- require_relative 'code_block'
2
- require_relative 'line'
3
- require_relative 'heading'
4
- require_relative 'paragraph'
5
- require 'strscan'
6
-
7
- module Elisp2any
8
- class Node
9
- attr_reader :range # :nodoc:
10
- attr_reader :content
11
-
12
- def self.from_tree_sitter(source, ts_node) #:nodoc:
13
- nodes = []
14
- (0 ... ts_node.child_count).map { |index| ts_node[index] }.each do |top_level_node|
15
- range = top_level_node.start_byte .. top_level_node.end_byte
16
- content = source.byteslice(range)
17
- node = Node.new(content, range)
18
- case top_level_node.type
19
- when :comment
20
- scanner = StringScanner.new(content)
21
- scanner.skip(';') or raise Error, 'no semicolon for comment'
22
- scanner.skip(';') or
23
- begin
24
- (last_node = nodes.last) && last_node.is_a?(CodeBlock) or raise Error, 'no prior code for single semicolon comment'
25
- last_node.append(source, range.end)
26
- next
27
- end
28
-
29
- if (level = scanner.skip(/;+/))
30
- scanner.skip(' ') or raise Error, 'no space after heading semicolons'
31
- nodes << Heading.new(node, level, scanner.rest.chomp)
32
- next
33
- elsif scanner.skip("\n")
34
- next
35
- end
36
-
37
- scanner.skip(' ') or raise Error, "no space after semicolons: #{scanner.inspect}"
38
- line = Line.parse(scanner.rest)
39
- if (last_node = nodes.last) && last_node.is_a?(Paragraph) && last_node.end_row + 1 == top_level_node.start_point.row
40
- last_node << line
41
- else
42
- paragraph = Paragraph.new(node, [line], top_level_node.end_point.row)
43
- nodes << paragraph
44
- end
45
- else
46
- if (last_node = nodes.last) && last_node.is_a?(CodeBlock)
47
- last_node.append(source, range.end)
48
- else
49
- nodes << CodeBlock.new(node)
50
- end
51
- end
52
- end
53
- nodes
54
- end
55
-
56
- def append(source, end_byte) # :nodoc:
57
- @range = range = @range.begin .. end_byte
58
- @content = source.byteslice(range)
59
- end
60
-
61
- def initialize(content, range) # :nodoc:
62
- @content = content
63
- @range = range
64
- end
65
- end
66
- end
@@ -1,21 +0,0 @@
1
- require "elisp2any/heading"
2
-
3
- module Elisp2any
4
- class TopHeading
5
- attr_reader :content
6
-
7
- def self.scan(scanner)
8
- pos = scanner.pos
9
- heading = Heading.scan(scanner)
10
- unless heading.level.zero?
11
- scanner.pos = pos
12
- return
13
- end
14
- new(content: heading.content)
15
- end
16
-
17
- def initialize(content:)
18
- @content = content
19
- end
20
- end
21
- end
@@ -1,36 +0,0 @@
1
- require 'tree_sitter'
2
-
3
- module Elisp2any
4
- class TreeSitterParser # :nodoc:
5
- def self.parse(source)
6
- new(source).parse
7
- end
8
-
9
- def parse
10
- @node = parser.parse_string(nil, @source).root_node
11
- end
12
-
13
- private
14
-
15
- def initialize(source)
16
- @source = source
17
- end
18
-
19
- def parser
20
- TreeSitter::Parser.new.tap do |p|
21
- p.language = TreeSitter::Language.load('elisp', elisp_library)
22
- end
23
- end
24
-
25
- def elisp_library
26
- shared_object = 'libtree-sitter-elisp.so'
27
-
28
- # Set this env var for Guix shell environment or shared object file is not found
29
- if ENV['ELISP2ANY_GUIX_USE_PROFILE_PATH']
30
- shared_object = ::File.join(ENV["GUIX_ENVIRONMENT"], "lib/tree-sitter", shared_object)
31
- end
32
-
33
- shared_object
34
- end
35
- end
36
- end
@@ -1,14 +0,0 @@
1
- module Elisp2any
2
- class Variable
3
- attr_reader :name
4
-
5
- def self.scan(scanner)
6
- name = scanner.scan(/[a-z-]+/) or return
7
- new(name:)
8
- end
9
-
10
- def initialize(name:)
11
- @name = name
12
- end
13
- end
14
- end
data/manifest.scm DELETED
@@ -1,87 +0,0 @@
1
- (use-modules (guix packages)
2
- ((guix licenses) #:prefix license:)
3
- (guix git-download)
4
- (guix build-system ruby)
5
- (guix build-system tree-sitter)
6
- (gnu packages tree-sitter)
7
- (gnu packages ruby))
8
-
9
- (define-public ruby-tree-sitter
10
- (let ((commit "2c56b04283f2a8cfed7d6c527ca36b8e1127ee8c")
11
- (revision "0"))
12
- (package
13
- (name "ruby-tree-sitter")
14
- (version (git-version "0.20.8.1" revision commit))
15
- (source
16
- (origin
17
- (method git-fetch)
18
- (uri (git-reference
19
- (url "https://github.com/Faveod/ruby-tree-sitter")
20
- (commit commit)))
21
- (file-name (git-file-name name version))
22
- (sha256
23
- (base32 "144kp0ya4rl03bgwpix17bgq2ak2kqk63pwniy6sfxfjqp5yzr7f"))))
24
- (build-system ruby-build-system)
25
- (arguments
26
- (list
27
- #:phases #~(modify-phases %standard-phases
28
- (add-after 'extract-gemspec 'remove-depends
29
- (lambda _
30
- (substitute* "tree_sitter.gemspec"
31
- ((".*minitest-color.*")
32
- "\n")
33
- ((".*pry.*")
34
- "\n")
35
- ((".*rake.*")
36
- "\n"))
37
- (substitute* "test/test_helper.rb"
38
- ((".*minitest/color.*")
39
- "\n"))))
40
- (add-before 'build 'compile
41
- (lambda _
42
- (invoke "rake" "compile")))
43
- (add-before 'check 'set-path
44
- (lambda* (#:key inputs #:allow-other-keys)
45
- (let ((ruby (assoc-ref inputs "tree-sitter-ruby")))
46
- (setenv "TREE_SITTER_PARSERS"
47
- (string-append ruby "/lib/tree-sitter")))))
48
- (add-before 'check 'remove-failing-test
49
- (lambda _
50
- (delete-file "test/tree_sitter/node_test.rb"))))))
51
- (native-inputs (list ruby-minitest ruby-rake-compiler
52
- ruby-rake-compiler-dock ruby-ruby-memcheck
53
- tree-sitter-ruby))
54
- (inputs (list tree-sitter))
55
- (synopsis "Ruby bindings for Tree-Sitter")
56
- (description "Ruby bindings for Tree-Sitter")
57
- (home-page "https://www.github.com/Faveod/ruby-tree-sitter")
58
- (license license:expat))))
59
-
60
- (define-public tree-sitter-elisp
61
- (let ((commit "e5524fdccf8c22fc726474a910e4ade976dfc7bb")
62
- (revision "0"))
63
- (package
64
- (name "tree-sitter-elisp")
65
- (version (git-version "0.1.4" revision commit))
66
- (source
67
- (origin
68
- (method git-fetch)
69
- (uri (git-reference
70
- (url "https://github.com/Wilfred/tree-sitter-elisp")
71
- (commit commit)))
72
- (file-name (git-file-name name version))
73
- (sha256
74
- (base32 "1wyzfb27zgpvm4110jgv0sl598mxv5dkrg2cwjw3p9g2bq9mav5d"))))
75
- (build-system tree-sitter-build-system)
76
- (home-page "https://github.com/Wilfred/tree-sitter-elisp")
77
- (synopsis "Tree-sitter grammar for Emacs Lisp")
78
- (description "This package provides an Emacs Lisp grammar for the Tree-sitter library.")
79
- (license license:expat))))
80
-
81
- (concatenate-manifests
82
- (list
83
- (packages->manifest (list ruby-tree-sitter tree-sitter-elisp))
84
- (specifications->manifest (list "ruby@3.1"
85
- "ruby-webrick"
86
- "ruby-rubocop"
87
- "ruby-asciidoctor"))))