diff --git a/lib/interscript/isc/document_builder.rb b/lib/interscript/isc/document_builder.rb index d6983368..886778b6 100644 --- a/lib/interscript/isc/document_builder.rb +++ b/lib/interscript/isc/document_builder.rb @@ -263,7 +263,9 @@ def extract_stage_items(n) elsif n[:compose] [{kind: :compose}] elsif n[:case] - [{kind: :string_case, op: n[:case].to_s}] + item = {kind: :string_case, op: n[:case].to_s} + item[:kwargs] = extract_kwargs(n[:case_kwargs]) if n[:case_kwargs] + [item] elsif n[:funcall_name] [{kind: :funcall, name: n[:funcall_name].to_s, kwargs: extract_kwargs(n[:funcall_kwargs])}] elsif n[:dep] diff --git a/lib/interscript/isc/generator.rb b/lib/interscript/isc/generator.rb index 1505afce..655abc4e 100644 --- a/lib/interscript/isc/generator.rb +++ b/lib/interscript/isc/generator.rb @@ -96,12 +96,25 @@ def run_target(run) end def funcall(rule, pad) - unless rule.kwargs.empty? - raise UnsupportedConstruct, - "cannot generate #{rule.name}(...) with kwargs as ISC" - end + case rule.name + when :separate + separator = rule.kwargs[:separator] + return "#{pad}separate\n" if separator.nil? + + "#{pad}separate separator #{item(separator)}\n" + when :title_case + word_separator = rule.kwargs[:word_separator] + return "#{pad}title_case\n" if word_separator.nil? - "#{pad}#{rule.name}\n" + "#{pad}title_case word_separator: #{quote(word_separator)}\n" + else + unless rule.kwargs.empty? + raise UnsupportedConstruct, + "cannot generate #{rule.name}(...) with kwargs as ISC" + end + + "#{pad}#{rule.name}\n" + end end # -- items -- diff --git a/lib/interscript/isc/grammar/concerns/stages.rb b/lib/interscript/isc/grammar/concerns/stages.rb index 3cdb4983..5838a386 100644 --- a/lib/interscript/isc/grammar/concerns/stages.rb +++ b/lib/interscript/isc/grammar/concerns/stages.rb @@ -54,8 +54,11 @@ module Stages end # `downcase`, `upcase`, `title_case` — string-case directives. + # title_case takes an optional word_separator kwarg. rule(:string_case_directive) do - (str("downcase") | str("upcase") | str("title_case")).as(:case) + (str("downcase") | str("upcase")).as(:case) | + (str("title_case").as(:case) >> + (whitespace >> kwarg_list.as(:case_kwargs)).maybe) end # `compose` / `decompose` — Unicode normalization directives. diff --git a/lib/interscript/isc/node_adapter.rb b/lib/interscript/isc/node_adapter.rb index df6c0a56..8786c2a1 100644 --- a/lib/interscript/isc/node_adapter.rb +++ b/lib/interscript/isc/node_adapter.rb @@ -111,12 +111,12 @@ def build_stage(stage_def) when :run stage.children << build_run_rule(item) when :separate - stage.children << Interscript::Node::Rule::Sub.new( - Interscript::Node::Item::String.new(" "), - Interscript::Node::Item::String.new(item[:separator]&.value || "-") - ) + kwargs = {} + kwargs[:separator] = item[:separator].value if item[:separator] + stage.children << Interscript::Node::Rule::Funcall.new(:separate, **kwargs) when :string_case - stage.children << Interscript::Node::Rule::Funcall.new(item[:op].to_sym) + stage.children << Interscript::Node::Rule::Funcall.new(item[:op].to_sym, + **(item[:kwargs] || {}).transform_keys(&:to_sym)) when :compose stage.children << Interscript::Node::Rule::Funcall.new(:compose) when :decompose diff --git a/spec/interscript/isc/generator_spec.rb b/spec/interscript/isc/generator_spec.rb index be8e0532..9e820de9 100644 --- a/spec/interscript/isc/generator_spec.rb +++ b/spec/interscript/isc/generator_spec.rb @@ -86,6 +86,29 @@ def round_trip_stage(&block) expect(reparsed.call("ava eve")).to eq(original.call("ava eve")) end + it "round-trips separate and title_case directives" do + original = document { + stage { + title_case + separate + } + } + reparsed = round_trip(original) + expect(reparsed.call("hello world")).to eq(original.call("hello world")) + + kwargs_doc = document { + stage { + title_case word_separator: "" + separate separator: "|" + } + } + kwargs_reparsed = round_trip(kwargs_doc) + expect(kwargs_reparsed.call("hello world hello hello")).to eq( + kwargs_doc.call("hello world hello hello") + ) + expect(kwargs_reparsed.call("こんいちは")).to eq(kwargs_doc.call("こんいちは")) + end + it "round-trips multiple stages with a stage run" do original = document { stage :first do