foxtail-tools 0.5.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 +7 -0
- data/CHANGELOG.md +19 -0
- data/LICENSE.txt +21 -0
- data/README.md +66 -0
- data/exe/foxtail +12 -0
- data/lib/foxtail/cli/commands/check.rb +60 -0
- data/lib/foxtail/cli/commands/dump.rb +43 -0
- data/lib/foxtail/cli/commands/ids.rb +73 -0
- data/lib/foxtail/cli/commands/tidy.rb +107 -0
- data/lib/foxtail/cli.rb +59 -0
- data/lib/foxtail/syntax/error.rb +8 -0
- data/lib/foxtail/syntax/parser/ast/annotation.rb +23 -0
- data/lib/foxtail/syntax/parser/ast/attribute.rb +23 -0
- data/lib/foxtail/syntax/parser/ast/base_comment.rb +19 -0
- data/lib/foxtail/syntax/parser/ast/base_literal.rb +24 -0
- data/lib/foxtail/syntax/parser/ast/base_node.rb +89 -0
- data/lib/foxtail/syntax/parser/ast/call_arguments.rb +23 -0
- data/lib/foxtail/syntax/parser/ast/comment.rb +13 -0
- data/lib/foxtail/syntax/parser/ast/function_reference.rb +23 -0
- data/lib/foxtail/syntax/parser/ast/group_comment.rb +13 -0
- data/lib/foxtail/syntax/parser/ast/identifier.rb +19 -0
- data/lib/foxtail/syntax/parser/ast/junk.rb +23 -0
- data/lib/foxtail/syntax/parser/ast/message.rb +28 -0
- data/lib/foxtail/syntax/parser/ast/message_reference.rb +23 -0
- data/lib/foxtail/syntax/parser/ast/named_argument.rb +23 -0
- data/lib/foxtail/syntax/parser/ast/number_literal.rb +24 -0
- data/lib/foxtail/syntax/parser/ast/pattern.rb +22 -0
- data/lib/foxtail/syntax/parser/ast/placeable.rb +21 -0
- data/lib/foxtail/syntax/parser/ast/resource.rb +55 -0
- data/lib/foxtail/syntax/parser/ast/resource_comment.rb +13 -0
- data/lib/foxtail/syntax/parser/ast/select_expression.rb +23 -0
- data/lib/foxtail/syntax/parser/ast/span.rb +22 -0
- data/lib/foxtail/syntax/parser/ast/string_literal.rb +45 -0
- data/lib/foxtail/syntax/parser/ast/syntax_node.rb +22 -0
- data/lib/foxtail/syntax/parser/ast/term.rb +28 -0
- data/lib/foxtail/syntax/parser/ast/term_reference.rb +25 -0
- data/lib/foxtail/syntax/parser/ast/text_element.rb +19 -0
- data/lib/foxtail/syntax/parser/ast/variable_reference.rb +21 -0
- data/lib/foxtail/syntax/parser/ast/variant.rb +25 -0
- data/lib/foxtail/syntax/parser/ast.rb +12 -0
- data/lib/foxtail/syntax/parser/parse_error.rb +94 -0
- data/lib/foxtail/syntax/parser/stream.rb +338 -0
- data/lib/foxtail/syntax/parser.rb +797 -0
- data/lib/foxtail/syntax/serializer.rb +242 -0
- data/lib/foxtail/syntax/visitor.rb +61 -0
- data/lib/foxtail/syntax.rb +12 -0
- data/lib/foxtail/tools/error.rb +8 -0
- data/lib/foxtail/tools/version.rb +9 -0
- data/lib/foxtail-tools.rb +22 -0
- metadata +141 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Foxtail
|
|
4
|
+
module Syntax
|
|
5
|
+
# Serializes AST nodes back to FTL format
|
|
6
|
+
class Serializer
|
|
7
|
+
# Create a new Serializer instance
|
|
8
|
+
# @param with_junk [Boolean] Whether to include junk entries in output (default: false)
|
|
9
|
+
def initialize(with_junk: false)
|
|
10
|
+
@with_junk = with_junk
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# @return [Boolean] Whether to include junk entries in output
|
|
14
|
+
def with_junk? = @with_junk
|
|
15
|
+
|
|
16
|
+
# Serialize a Resource AST to FTL string
|
|
17
|
+
# @param resource [Parser::AST::Resource] Resource to serialize
|
|
18
|
+
# @return [String] FTL formatted source text
|
|
19
|
+
def serialize(resource)
|
|
20
|
+
has_entries = false
|
|
21
|
+
parts = []
|
|
22
|
+
|
|
23
|
+
resource.body.each do |entry|
|
|
24
|
+
next if entry.is_a?(Parser::AST::Junk) && !with_junk?
|
|
25
|
+
|
|
26
|
+
parts << serialize_entry(entry, has_entries:)
|
|
27
|
+
has_entries = true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
parts.join
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Serialize a single entry (Message, Term, Comment, or Junk)
|
|
34
|
+
# @param entry [Parser::AST::Message, Parser::AST::Term, Parser::AST::BaseComment, Parser::AST::Junk] Entry to serialize
|
|
35
|
+
# @param has_entries [Boolean] Whether previous entries exist (for spacing)
|
|
36
|
+
# @return [String] FTL formatted entry text
|
|
37
|
+
def serialize_entry(entry, has_entries: false)
|
|
38
|
+
case entry
|
|
39
|
+
when Parser::AST::Message
|
|
40
|
+
serialize_message(entry)
|
|
41
|
+
when Parser::AST::Term
|
|
42
|
+
serialize_term(entry)
|
|
43
|
+
when Parser::AST::Comment
|
|
44
|
+
serialize_standalone_comment(entry, "#", has_entries)
|
|
45
|
+
when Parser::AST::GroupComment
|
|
46
|
+
serialize_standalone_comment(entry, "##", has_entries)
|
|
47
|
+
when Parser::AST::ResourceComment
|
|
48
|
+
serialize_standalone_comment(entry, "###", has_entries)
|
|
49
|
+
when Parser::AST::Junk
|
|
50
|
+
serialize_junk(entry)
|
|
51
|
+
else
|
|
52
|
+
raise ArgumentError, "Unknown entry type: #{entry.class}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
private def serialize_standalone_comment(comment, prefix, has_entries)
|
|
57
|
+
result = serialize_comment(comment, prefix)
|
|
58
|
+
if has_entries
|
|
59
|
+
"\n#{result}\n"
|
|
60
|
+
else
|
|
61
|
+
"#{result}\n"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private def serialize_comment(comment, prefix="#")
|
|
66
|
+
prefixed = comment.content.split("\n").map {|line|
|
|
67
|
+
line.empty? ? prefix : "#{prefix} #{line}"
|
|
68
|
+
}.join("\n")
|
|
69
|
+
"#{prefixed}\n"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private def serialize_junk(junk) = junk.content
|
|
73
|
+
|
|
74
|
+
private def serialize_message(message)
|
|
75
|
+
parts = []
|
|
76
|
+
parts << serialize_comment(message.comment) if message.comment
|
|
77
|
+
parts << "#{message.id.name} ="
|
|
78
|
+
parts << serialize_pattern(message.value) if message.value
|
|
79
|
+
message.attributes.each {|attr| parts << serialize_attribute(attr) }
|
|
80
|
+
parts << "\n"
|
|
81
|
+
parts.join
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private def serialize_term(term)
|
|
85
|
+
parts = []
|
|
86
|
+
parts << serialize_comment(term.comment) if term.comment
|
|
87
|
+
parts << "-#{term.id.name} ="
|
|
88
|
+
parts << serialize_pattern(term.value)
|
|
89
|
+
term.attributes.each {|attr| parts << serialize_attribute(attr) }
|
|
90
|
+
parts << "\n"
|
|
91
|
+
parts.join
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private def serialize_attribute(attribute)
|
|
95
|
+
value = indent_except_first_line(serialize_pattern(attribute.value))
|
|
96
|
+
"\n .#{attribute.id.name} =#{value}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private def serialize_pattern(pattern)
|
|
100
|
+
content = pattern.elements.map {|elem| serialize_element(elem) }.join
|
|
101
|
+
|
|
102
|
+
if should_start_on_new_line?(pattern)
|
|
103
|
+
"\n #{indent_except_first_line(content)}"
|
|
104
|
+
else
|
|
105
|
+
" #{indent_except_first_line(content)}"
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
private def serialize_element(element)
|
|
110
|
+
case element
|
|
111
|
+
when Parser::AST::TextElement
|
|
112
|
+
element.value
|
|
113
|
+
when Parser::AST::Placeable
|
|
114
|
+
serialize_placeable(element)
|
|
115
|
+
else
|
|
116
|
+
raise ArgumentError, "Unknown element type: #{element.class}"
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
private def serialize_placeable(placeable)
|
|
121
|
+
expr = placeable.expression
|
|
122
|
+
case expr
|
|
123
|
+
when Parser::AST::Placeable
|
|
124
|
+
"{#{serialize_placeable(expr)}}"
|
|
125
|
+
when Parser::AST::SelectExpression
|
|
126
|
+
"{ #{serialize_expression(expr)}}"
|
|
127
|
+
else
|
|
128
|
+
"{ #{serialize_expression(expr)} }"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
private def serialize_expression(expr)
|
|
133
|
+
case expr
|
|
134
|
+
when Parser::AST::StringLiteral
|
|
135
|
+
"\"#{expr.value}\""
|
|
136
|
+
when Parser::AST::NumberLiteral
|
|
137
|
+
expr.value
|
|
138
|
+
when Parser::AST::VariableReference
|
|
139
|
+
"$#{expr.id.name}"
|
|
140
|
+
when Parser::AST::TermReference
|
|
141
|
+
serialize_term_reference(expr)
|
|
142
|
+
when Parser::AST::MessageReference
|
|
143
|
+
serialize_message_reference(expr)
|
|
144
|
+
when Parser::AST::FunctionReference
|
|
145
|
+
"#{expr.id.name}#{serialize_call_arguments(expr.arguments)}"
|
|
146
|
+
when Parser::AST::SelectExpression
|
|
147
|
+
serialize_select_expression(expr)
|
|
148
|
+
when Parser::AST::Placeable
|
|
149
|
+
serialize_placeable(expr)
|
|
150
|
+
else
|
|
151
|
+
raise ArgumentError, "Unknown expression type: #{expr.class}"
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
private def serialize_term_reference(ref)
|
|
156
|
+
out = "-#{ref.id.name}"
|
|
157
|
+
out += ".#{ref.attribute.name}" if ref.attribute
|
|
158
|
+
out += serialize_call_arguments(ref.arguments) if ref.arguments
|
|
159
|
+
out
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
private def serialize_message_reference(ref)
|
|
163
|
+
out = ref.id.name
|
|
164
|
+
out += ".#{ref.attribute.name}" if ref.attribute
|
|
165
|
+
out
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
private def serialize_select_expression(expr)
|
|
169
|
+
out = "#{serialize_expression(expr.selector)} ->"
|
|
170
|
+
expr.variants.each {|variant| out += serialize_variant(variant) }
|
|
171
|
+
"#{out}\n"
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
private def serialize_variant(variant)
|
|
175
|
+
key = serialize_variant_key(variant.key)
|
|
176
|
+
value = indent_except_first_line(serialize_pattern(variant.value))
|
|
177
|
+
|
|
178
|
+
if variant.default
|
|
179
|
+
"\n *[#{key}]#{value}"
|
|
180
|
+
else
|
|
181
|
+
"\n [#{key}]#{value}"
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
private def serialize_variant_key(key)
|
|
186
|
+
case key
|
|
187
|
+
when Parser::AST::Identifier
|
|
188
|
+
key.name
|
|
189
|
+
when Parser::AST::NumberLiteral
|
|
190
|
+
key.value
|
|
191
|
+
else
|
|
192
|
+
raise ArgumentError, "Unknown variant key type: #{key.class}"
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
private def serialize_call_arguments(args)
|
|
197
|
+
return "()" if args.nil?
|
|
198
|
+
|
|
199
|
+
positional = args.positional.map {|arg| serialize_expression(arg) }.join(", ")
|
|
200
|
+
named = args.named.map {|arg| serialize_named_argument(arg) }.join(", ")
|
|
201
|
+
|
|
202
|
+
if !positional.empty? && !named.empty?
|
|
203
|
+
"(#{positional}, #{named})"
|
|
204
|
+
else
|
|
205
|
+
"(#{positional}#{named})"
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
private def serialize_named_argument(arg)
|
|
210
|
+
value = serialize_expression(arg.value)
|
|
211
|
+
"#{arg.name.name}: #{value}"
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
private def indent_except_first_line(content)
|
|
215
|
+
content.split("\n").join("\n ")
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
private def should_start_on_new_line?(pattern)
|
|
219
|
+
is_multiline = pattern.elements.any? {|elem|
|
|
220
|
+
select_expr?(elem) || includes_newline?(elem)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return false unless is_multiline
|
|
224
|
+
|
|
225
|
+
first_element = pattern.elements.first
|
|
226
|
+
return true unless first_element.is_a?(Parser::AST::TextElement)
|
|
227
|
+
|
|
228
|
+
first_char = first_element.value[0]
|
|
229
|
+
# These characters may not appear as the first character on a new line
|
|
230
|
+
!["[", ".", "*"].include?(first_char)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
private def select_expr?(elem)
|
|
234
|
+
elem.is_a?(Parser::AST::Placeable) && elem.expression.is_a?(Parser::AST::SelectExpression)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
private def includes_newline?(elem)
|
|
238
|
+
elem.is_a?(Parser::AST::TextElement) && elem.value.include?("\n")
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Foxtail
|
|
4
|
+
module Syntax
|
|
5
|
+
# Visitor module for traversing AST nodes
|
|
6
|
+
#
|
|
7
|
+
# Include this module and override the visit_* methods you need.
|
|
8
|
+
# By default, all visit_* methods traverse children automatically.
|
|
9
|
+
# Override a method and omit `super` to stop traversal at that node.
|
|
10
|
+
#
|
|
11
|
+
# @example Collecting message IDs
|
|
12
|
+
# class MessageIdCollector
|
|
13
|
+
# include Foxtail::Syntax::Visitor
|
|
14
|
+
#
|
|
15
|
+
# def initialize
|
|
16
|
+
# @ids = []
|
|
17
|
+
# end
|
|
18
|
+
#
|
|
19
|
+
# attr_reader :ids
|
|
20
|
+
#
|
|
21
|
+
# def visit_message(node)
|
|
22
|
+
# @ids << node.id.name
|
|
23
|
+
# super # continue traversal
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
#
|
|
27
|
+
# collector = MessageIdCollector.new
|
|
28
|
+
# resource.accept(collector)
|
|
29
|
+
# collector.ids # => ["hello", "goodbye", ...]
|
|
30
|
+
module Visitor
|
|
31
|
+
def visit_resource(node) = visit_children(node)
|
|
32
|
+
def visit_message(node) = visit_children(node)
|
|
33
|
+
def visit_term(node) = visit_children(node)
|
|
34
|
+
def visit_attribute(node) = visit_children(node)
|
|
35
|
+
def visit_pattern(node) = visit_children(node)
|
|
36
|
+
def visit_placeable(node) = visit_children(node)
|
|
37
|
+
def visit_select_expression(node) = visit_children(node)
|
|
38
|
+
def visit_variant(node) = visit_children(node)
|
|
39
|
+
def visit_call_arguments(node) = visit_children(node)
|
|
40
|
+
def visit_named_argument(node) = visit_children(node)
|
|
41
|
+
def visit_message_reference(node) = visit_children(node)
|
|
42
|
+
def visit_term_reference(node) = visit_children(node)
|
|
43
|
+
def visit_function_reference(node) = visit_children(node)
|
|
44
|
+
def visit_variable_reference(node) = visit_children(node)
|
|
45
|
+
def visit_string_literal(node) = visit_children(node)
|
|
46
|
+
def visit_number_literal(node) = visit_children(node)
|
|
47
|
+
def visit_text_element(node) = visit_children(node)
|
|
48
|
+
def visit_identifier(node) = visit_children(node)
|
|
49
|
+
def visit_comment(node) = visit_children(node)
|
|
50
|
+
def visit_group_comment(node) = visit_children(node)
|
|
51
|
+
def visit_resource_comment(node) = visit_children(node)
|
|
52
|
+
def visit_junk(node) = visit_children(node)
|
|
53
|
+
def visit_annotation(node) = visit_children(node)
|
|
54
|
+
def visit_span(node) = visit_children(node)
|
|
55
|
+
|
|
56
|
+
def visit_children(node)
|
|
57
|
+
node.children.each {|child| child&.accept(self) }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Foxtail
|
|
4
|
+
# Syntax module provides full FTL parsing with complete AST representation.
|
|
5
|
+
# This is the fluent-syntax equivalent, suitable for tools like linters,
|
|
6
|
+
# formatters, and editors that need position information and comments.
|
|
7
|
+
#
|
|
8
|
+
# For runtime message formatting, use {Foxtail::Bundle} instead which uses
|
|
9
|
+
# a lightweight parser optimized for execution.
|
|
10
|
+
module Syntax
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "zeitwerk"
|
|
4
|
+
require_relative "foxtail/tools/version"
|
|
5
|
+
|
|
6
|
+
# Tooling entrypoint for Foxtail (syntax + CLI)
|
|
7
|
+
module Foxtail
|
|
8
|
+
loader = Zeitwerk::Loader.new
|
|
9
|
+
loader.push_dir(__dir__ + "/foxtail", namespace: Foxtail)
|
|
10
|
+
|
|
11
|
+
# Ignore version.rb since it's required by gemspec before Zeitwerk loads
|
|
12
|
+
loader.ignore(__dir__ + "/foxtail/tools/version.rb")
|
|
13
|
+
# Ignore gem entrypoint file (no constant defined)
|
|
14
|
+
loader.ignore(__dir__ + "/foxtail-tools.rb")
|
|
15
|
+
|
|
16
|
+
loader.inflector.inflect(
|
|
17
|
+
"ast" => "AST",
|
|
18
|
+
"cli" => "CLI"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
loader.setup
|
|
22
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: foxtail-tools
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.5.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- OZAWA Sakuro
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: exe
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-08 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: dry-cli
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.4'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.4'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: dry-inflector
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.0'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: zeitwerk
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '2.7'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '2.7'
|
|
55
|
+
description: 'Tooling components for Foxtail: fluent syntax parser/serializer and
|
|
56
|
+
CLI utilities.
|
|
57
|
+
|
|
58
|
+
'
|
|
59
|
+
email:
|
|
60
|
+
- 10973+sakuro@users.noreply.github.com
|
|
61
|
+
executables:
|
|
62
|
+
- foxtail
|
|
63
|
+
extensions: []
|
|
64
|
+
extra_rdoc_files: []
|
|
65
|
+
files:
|
|
66
|
+
- CHANGELOG.md
|
|
67
|
+
- LICENSE.txt
|
|
68
|
+
- README.md
|
|
69
|
+
- exe/foxtail
|
|
70
|
+
- lib/foxtail-tools.rb
|
|
71
|
+
- lib/foxtail/cli.rb
|
|
72
|
+
- lib/foxtail/cli/commands/check.rb
|
|
73
|
+
- lib/foxtail/cli/commands/dump.rb
|
|
74
|
+
- lib/foxtail/cli/commands/ids.rb
|
|
75
|
+
- lib/foxtail/cli/commands/tidy.rb
|
|
76
|
+
- lib/foxtail/syntax.rb
|
|
77
|
+
- lib/foxtail/syntax/error.rb
|
|
78
|
+
- lib/foxtail/syntax/parser.rb
|
|
79
|
+
- lib/foxtail/syntax/parser/ast.rb
|
|
80
|
+
- lib/foxtail/syntax/parser/ast/annotation.rb
|
|
81
|
+
- lib/foxtail/syntax/parser/ast/attribute.rb
|
|
82
|
+
- lib/foxtail/syntax/parser/ast/base_comment.rb
|
|
83
|
+
- lib/foxtail/syntax/parser/ast/base_literal.rb
|
|
84
|
+
- lib/foxtail/syntax/parser/ast/base_node.rb
|
|
85
|
+
- lib/foxtail/syntax/parser/ast/call_arguments.rb
|
|
86
|
+
- lib/foxtail/syntax/parser/ast/comment.rb
|
|
87
|
+
- lib/foxtail/syntax/parser/ast/function_reference.rb
|
|
88
|
+
- lib/foxtail/syntax/parser/ast/group_comment.rb
|
|
89
|
+
- lib/foxtail/syntax/parser/ast/identifier.rb
|
|
90
|
+
- lib/foxtail/syntax/parser/ast/junk.rb
|
|
91
|
+
- lib/foxtail/syntax/parser/ast/message.rb
|
|
92
|
+
- lib/foxtail/syntax/parser/ast/message_reference.rb
|
|
93
|
+
- lib/foxtail/syntax/parser/ast/named_argument.rb
|
|
94
|
+
- lib/foxtail/syntax/parser/ast/number_literal.rb
|
|
95
|
+
- lib/foxtail/syntax/parser/ast/pattern.rb
|
|
96
|
+
- lib/foxtail/syntax/parser/ast/placeable.rb
|
|
97
|
+
- lib/foxtail/syntax/parser/ast/resource.rb
|
|
98
|
+
- lib/foxtail/syntax/parser/ast/resource_comment.rb
|
|
99
|
+
- lib/foxtail/syntax/parser/ast/select_expression.rb
|
|
100
|
+
- lib/foxtail/syntax/parser/ast/span.rb
|
|
101
|
+
- lib/foxtail/syntax/parser/ast/string_literal.rb
|
|
102
|
+
- lib/foxtail/syntax/parser/ast/syntax_node.rb
|
|
103
|
+
- lib/foxtail/syntax/parser/ast/term.rb
|
|
104
|
+
- lib/foxtail/syntax/parser/ast/term_reference.rb
|
|
105
|
+
- lib/foxtail/syntax/parser/ast/text_element.rb
|
|
106
|
+
- lib/foxtail/syntax/parser/ast/variable_reference.rb
|
|
107
|
+
- lib/foxtail/syntax/parser/ast/variant.rb
|
|
108
|
+
- lib/foxtail/syntax/parser/parse_error.rb
|
|
109
|
+
- lib/foxtail/syntax/parser/stream.rb
|
|
110
|
+
- lib/foxtail/syntax/serializer.rb
|
|
111
|
+
- lib/foxtail/syntax/visitor.rb
|
|
112
|
+
- lib/foxtail/tools/error.rb
|
|
113
|
+
- lib/foxtail/tools/version.rb
|
|
114
|
+
homepage: https://github.com/sakuro/foxtail
|
|
115
|
+
licenses:
|
|
116
|
+
- MIT
|
|
117
|
+
metadata:
|
|
118
|
+
homepage_uri: https://github.com/sakuro/foxtail
|
|
119
|
+
source_code_uri: https://github.com/sakuro/foxtail.git
|
|
120
|
+
changelog_uri: https://github.com/sakuro/foxtail/blob/main/foxtail-tools/CHANGELOG.md
|
|
121
|
+
rubygems_mfa_required: 'true'
|
|
122
|
+
post_install_message:
|
|
123
|
+
rdoc_options: []
|
|
124
|
+
require_paths:
|
|
125
|
+
- lib
|
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - ">="
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '3.3'
|
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
132
|
+
requirements:
|
|
133
|
+
- - ">="
|
|
134
|
+
- !ruby/object:Gem::Version
|
|
135
|
+
version: '0'
|
|
136
|
+
requirements: []
|
|
137
|
+
rubygems_version: 3.5.22
|
|
138
|
+
signing_key:
|
|
139
|
+
specification_version: 4
|
|
140
|
+
summary: Foxtail CLI and syntax tooling for Project Fluent
|
|
141
|
+
test_files: []
|