diff --git a/README.md b/README.md
index 870e92b..a423f56 100644
--- a/README.md
+++ b/README.md
@@ -250,7 +250,21 @@ If you want to do specialized formatting within a given string, Squib has lots o
* Apostraphes are converted to curly as well.
* LaTeX-style quotes are explicitly converted (``like this'')
* Em-dash and en-dash are converted with triple and double-dashes respectively (-- is an en-dash, and --- becomes an em-dash.)
-* Ellipses can be specified with .... Note that this is entirely different from the `ellipsize` option (which determines what to do with overflowing text).
+* Ellipses can be specified with .... Note that this is entirely different from the `ellipsize` option, which is determining what to do with overflowing text.
+
+The above replacements assume you are using the UTF-8 character set. If you wish to change the characters, set the following configuration options in your `config.yml`
+
+```yaml
+ lsquote: "\u2018" #note that Yaml wants double quotes here to use escape chars
+ rsquote: "\u2019"
+ ldquote: "\u201C"
+ rdquote: "\u201D"
+ em_dash: "\u2014"
+ en_dash: "\u2013"
+ ellipsis: "\u2026"
+```
+
+You can also disable the auto-quoting mechanism by setting `smart_quotes: false` in your config. Explicit replacements will still be performed.
### Text Samples
@@ -258,10 +272,18 @@ Examples of all of the above are crammed into the `text_options.rb` sample [foun
{include:file:samples/text_options.rb}
-Also, the `embed_text.rb` sample has more examples of embedding text, which can be [found here](https://github.com/andymeneely/squib/tree/master/samples/embed_text.rb).
+The `embed_text.rb` sample has more examples of embedding text, which can be [found here](https://github.com/andymeneely/squib/tree/master/samples/embed_text.rb).
{include:file:samples/embed_text.rb}
+The `config_text_markup.rb` sample demonstrates how quoting can be configured, [found here](https://github.com/andymeneely/squib/tree/master/samples/config_text_markup.rb)
+
+{include:file:samples/config_text_markup.rb}
+
+{include:file:samples/config_text_markup.yml}
+
+
+
## Custom Layouts
Working with x-y coordinates all the time can be tiresome, and ideally everything in a game prototype should be data-driven and easily changed. For this, many Squib methods allow for a `layout` to be set. In essence, layouts are a way of setting default values for any argument given to the command.
diff --git a/lib/squib/args/typographer.rb b/lib/squib/args/typographer.rb
index 1ab62ab..ab753c8 100644
--- a/lib/squib/args/typographer.rb
+++ b/lib/squib/args/typographer.rb
@@ -8,17 +8,27 @@ module Squib
end
def process(str)
- [
- :left_curly,
- :right_curly,
- :apostraphize,
+ str = explicit_replacements(str)
+ str = smart_quotes(str) if @config['smart_quotes']
+ str
+ end
+
+ def explicit_replacements(str)
+ [ :left_curly, :right_curly, :apostraphize,
+ :ellipsificate, :em_dash, :en_dash ].each do |sym|
+ str = each_non_tag(str) do |token|
+ self.method(sym).call(token)
+ end
+ end
+ str
+ end
+
+ def smart_quotes(str)
+ [ :single_inside_double_quote,
:right_double_quote,
:left_double_quote,
:right_single_quote,
- :left_single_quote,
- :ellipsificate,
- :em_dash,
- :en_dash ].each do |sym|
+ :left_single_quote].each do |sym|
str = each_non_tag(str) do |token|
self.method(sym).call(token)
end
@@ -43,52 +53,58 @@ module Squib
# Straightforward replace
def left_curly(str)
- str.gsub('``', "\u201C")
+ str.gsub('``', @config['ldquote'])
end
# Straightforward replace
def right_curly(str)
- str.gsub(%{''}, "\u201D")
+ str.gsub(%{''}, @config['rdquote'])
end
# A quote between two letters is an apostraphe
def apostraphize(str)
- str.gsub(/(\w)(\')(\w)/, '\1' + "\u2019" + '\3')
+ str.gsub(/(\w)(\')(\w)/, '\1' + @config['rsquote'] + '\3')
end
- # Quote next to non-whitespace curls
- def right_double_quote(str)
- str.gsub(/(\S)(\")/, '\1' + "\u201D")
+ # Straightforward replace
+ def ellipsificate(str)
+ str.gsub('...', @config['ellipsis'])
end
- # Quote next to non-whitespace curls
- def left_double_quote(str)
- str.gsub(/(\")(\S)/, "\u201C" + '\2')
+ # Straightforward replace
+ def en_dash(str)
+ str.gsub('--', @config['en_dash'])
+ end
+
+ # Straightforward replace
+ def em_dash(str)
+ str.gsub('---', @config['em_dash'])
end
# Quote next to non-whitespace curls
- def right_single_quote(str)
- str.gsub(/(\S)(\')/, '\1' + "\u2019")
+ def right_double_quote(str)
+ str.gsub(/(\S)(\")/, '\1' + @config['rdquote'])
end
# Quote next to non-whitespace curls
- def left_single_quote(str)
- str.gsub(/(\')(\S)/, "\u2018" + '\2')
+ def left_double_quote(str)
+ str.gsub(/(\")(\S)/, @config['ldquote'] + '\2')
end
- # Straightforward replace
- def ellipsificate(str)
- str.gsub('...', "\u2026")
+ # Handle the cases where a double quote is next to a single quote
+ def single_inside_double_quote(str)
+ str.gsub(/(\")(\')(\S)/, @config['ldquote'] + @config['lsquote'] + '\3')
+ .gsub(/(\")(\')(\S)/, '\1' + @config['rsquote'] + @config['rdquote'])
end
- # Straightforward replace
- def en_dash(str)
- str.gsub('--', "\u2013")
+ # Quote next to non-whitespace curls
+ def right_single_quote(str)
+ str.gsub(/(\S)(\')/, '\1' + @config['rsquote'])
end
- # Straightforward replace
- def em_dash(str)
- str.gsub('---', "\u2014")
+ # Quote next to non-whitespace curls
+ def left_single_quote(str)
+ str.gsub(/(\')(\S)/, @config['lsquote'] + '\2')
end
end
diff --git a/lib/squib/constants.rb b/lib/squib/constants.rb
index 7864d5a..9ed0dc4 100644
--- a/lib/squib/constants.rb
+++ b/lib/squib/constants.rb
@@ -80,6 +80,14 @@ module Squib
'hint' => :none,
'img_dir' => '.',
'progress_bar' => false,
+ 'ldquote' => "\u201C", # UTF8 chars
+ 'rdquote' => "\u201D",
+ 'lsquote' => "\u2018",
+ 'rsquote' => "\u2019",
+ 'em_dash' => "\u2014",
+ 'en_dash' => "\u2013",
+ 'ellipsis' => "\u2026",
+ 'smart_quotes' => true,
}
#Translate the hints to the methods.
diff --git a/lib/squib/deck.rb b/lib/squib/deck.rb
index f047d15..c63d2a2 100644
--- a/lib/squib/deck.rb
+++ b/lib/squib/deck.rb
@@ -34,7 +34,7 @@ module Squib
# :nodoc:
# @api private
- attr_reader :layout, :config
+ attr_reader :layout, :config, :quote_chars
attr_reader :dir, :prefix, :count_format
@@ -70,6 +70,7 @@ module Squib
@dir = SYSTEM_DEFAULTS[:dir]
@prefix = SYSTEM_DEFAULTS[:prefix]
@count_format = SYSTEM_DEFAULTS[:count_format]
+ @quote_chars = CONFIG_DEFAULTS.select {|k,v| %w(lsquote rsquote ldquote rdquote smart_quotes).include?(k) }
show_info(config, layout)
load_config(config)
@width = Args::UnitConversion.parse width, dpi
@@ -111,6 +112,10 @@ module Squib
@prefix = config['prefix']
@count_format = config['count_format']
@antialias = config['antialias']
+ @quote_chars ||= {}
+ %w(lsquote rsquote ldquote rdquote smart_quotes em_dash en_dash ellipsis).each do |key|
+ @quote_chars[key] = config[key]
+ end
end
end
diff --git a/lib/squib/graphics/text.rb b/lib/squib/graphics/text.rb
index 61951c6..89338af 100644
--- a/lib/squib/graphics/text.rb
+++ b/lib/squib/graphics/text.rb
@@ -156,7 +156,7 @@ module Squib
layout.font_description = font_desc
layout.text = str
if markup
- str = Args::Typographer.new(@deck.config).process(layout.text)
+ str = Args::Typographer.new(@deck.quote_chars).process(layout.text)
layout.markup = str
end
diff --git a/lib/squib/project_template/config.yml b/lib/squib/project_template/config.yml
index 6ffa218..4984020 100644
--- a/lib/squib/project_template/config.yml
+++ b/lib/squib/project_template/config.yml
@@ -25,3 +25,16 @@
# Use a SVG cairo back end, instead of an in-memory buffer
# backend: :memory # default
# backend: :svg # can create scalable pdfs, but rendering done at the printer level is not as good as Cairo.
+
+# Configure what text markup uses replace characters
+# Below are the defaults
+# lsquote: "\u2018" #note that Yaml wants double quotes here to use escape chars
+# rsquote: "\u2019"
+# ldquote: "\u201C"
+# rdquote: "\u201D"
+# em_dash: "\u2014"
+# en_dash: "\u2013"
+# ellipsis: "\u2026"
+
+# We can also disallow smart quotes and only allow explicit replacements with ``LaTeX-style'' quotes.
+# smart_quotes: false
\ No newline at end of file
diff --git a/samples/config_disable_quotes.yml b/samples/config_disable_quotes.yml
new file mode 100644
index 0000000..a916fff
--- /dev/null
+++ b/samples/config_disable_quotes.yml
@@ -0,0 +1,3 @@
+# If we want to disable smart quoting and only allow explicit quoting within markup,
+# use this option
+smart_quotes: false
diff --git a/samples/config_text_markup.rb b/samples/config_text_markup.rb
new file mode 100644
index 0000000..2ea6068
--- /dev/null
+++ b/samples/config_text_markup.rb
@@ -0,0 +1,15 @@
+require 'squib'
+
+Squib::Deck.new(config: 'config_text_markup.yml') do
+ text str: %{"'Yaml ain't markup', he says"},
+ x: 10, y: 10, width: 300, height: 200, font: 'Serif 20',
+ markup: true, hint: :cyan
+ save_png prefix: 'config_text_'
+end
+
+Squib::Deck.new(config: 'config_disable_quotes.yml') do
+ text str: %{This has typographic sugar --- and ``explicit'' quotes --- but the quotes are "dumb"},
+ x: 10, y: 10, width: 300, height: 200, font: 'Serif 20',
+ markup: true, hint: :cyan
+ save_png prefix: 'config_disable_text_'
+end
\ No newline at end of file
diff --git a/samples/config_text_markup.yml b/samples/config_text_markup.yml
new file mode 100644
index 0000000..58d3b7f
--- /dev/null
+++ b/samples/config_text_markup.yml
@@ -0,0 +1,8 @@
+# We can configure what characters actually get replaced by quoting them with unicode code points.
+lsquote: "\u2018" #note that Yaml wants double quotes here to use escape chars
+rsquote: "\u2019"
+ldquote: "\u201C"
+rdquote: "\u201D"
+em_dash: "\u2014"
+en_dash: "\u2013"
+ellipsis: "\u2026"
diff --git a/spec/args/typographer_spec.rb b/spec/args/typographer_spec.rb
index c9243d0..cf0b268 100644
--- a/spec/args/typographer_spec.rb
+++ b/spec/args/typographer_spec.rb
@@ -44,8 +44,8 @@ describe Squib::Args::Typographer do
expect(t.process(%{can't})).to eq(%{can\u2019t})
end
- it "single quotes inside double quotes" do
- expect(t.process(%{"'I can't do that', he said"})).to eq(%{\u201C\u2019I can\u2019t do that\u2019, he said\u201D})
+it "single quotes inside double quotes" do
+ expect(t.process(%{"'I can't do that', he said"})).to eq(%{\u201C\u2018I can\u2019t do that\u2019, he said\u201D})
end
it "replaces the straightforward ones" do
diff --git a/spec/data/samples/config_text_markup.rb.txt b/spec/data/samples/config_text_markup.rb.txt
new file mode 100644
index 0000000..916fdf5
--- /dev/null
+++ b/spec/data/samples/config_text_markup.rb.txt
@@ -0,0 +1,52 @@
+cairo: antialias=(["subpixel"])
+cairo: save([])
+cairo: set_source_color([:black])
+cairo: translate([10, 10])
+cairo: rotate([0])
+cairo: move_to([0, 0])
+pango: font_description=([MockDouble])
+pango: text=(["\"'Yaml ain't markup', he says\""])
+pango: markup=(["foo"])
+pango: width=([307200])
+pango: height=([204800])
+pango: wrap=([#])
+pango: ellipsize=([#])
+pango: alignment=([#])
+pango: justify=([false])
+pango: spacing=([0])
+cairo: update_pango_layout([MockDouble])
+cairo: move_to([0, 0])
+cairo: update_pango_layout([MockDouble])
+cairo: show_pango_layout([MockDouble])
+cairo: rounded_rectangle([0, 0, 0, 0, 0, 0])
+cairo: set_source_color([:cyan])
+cairo: set_line_width([2.0])
+cairo: stroke([])
+cairo: restore([])
+surface: write_to_png(["_output/config_text_00.png"])
+cairo: antialias=(["subpixel"])
+cairo: save([])
+cairo: set_source_color([:black])
+cairo: translate([10, 10])
+cairo: rotate([0])
+cairo: move_to([0, 0])
+pango: font_description=([MockDouble])
+pango: text=(["This has typographic sugar --- and ``explicit'' quotes --- but the quotes are \"dumb\""])
+pango: markup=(["foo"])
+pango: width=([307200])
+pango: height=([204800])
+pango: wrap=([#])
+pango: ellipsize=([#])
+pango: alignment=([#])
+pango: justify=([false])
+pango: spacing=([0])
+cairo: update_pango_layout([MockDouble])
+cairo: move_to([0, 0])
+cairo: update_pango_layout([MockDouble])
+cairo: show_pango_layout([MockDouble])
+cairo: rounded_rectangle([0, 0, 0, 0, 0, 0])
+cairo: set_source_color([:cyan])
+cairo: set_line_width([2.0])
+cairo: stroke([])
+cairo: restore([])
+surface: write_to_png(["_output/config_disable_text_00.png"])
diff --git a/spec/samples/samples_regression_spec.rb b/spec/samples/samples_regression_spec.rb
index 39ac0fc..0d04e1b 100644
--- a/spec/samples/samples_regression_spec.rb
+++ b/spec/samples/samples_regression_spec.rb
@@ -51,6 +51,7 @@ describe "Squib samples" do
basic.rb
cairo_access.rb
csv_import.rb
+ config_text_markup.rb
custom_config.rb
draw_shapes.rb
embed_text.rb
diff --git a/squib.sublime-project b/squib.sublime-project
index 857278a..c6b3d03 100644
--- a/squib.sublime-project
+++ b/squib.sublime-project
@@ -24,6 +24,10 @@
"name": "rake run[draw_shapes]",
"shell_cmd": "rake run[draw_shapes]",
},
+ {
+ "name": "rake run[config_text_markup]",
+ "shell_cmd": "rake run[config_text_markup]",
+ },
{
"name": "rspec spec/samples/samples_regression_spec.rb",
"shell_cmd": "rspec spec/samples/samples_regression_spec.rb",
@@ -39,6 +43,7 @@
"shell_cmd": "rspec spec/graphics/graphics_text_spec.rb",
"working_dir": "${project_path:${folder}}"
},
+
],
}