Browse Source

Complete overhaul of smart quotes to "typographer"

See README for details

Contributes to #50
dev
Andy Meneely 11 years ago
parent
commit
a5d1cb60f2
  1. 11
      README.md
  2. 7
      lib/squib/api/text.rb
  3. 29
      lib/squib/args/smart_quotes.rb
  4. 96
      lib/squib/args/typographer.rb
  5. 5
      lib/squib/graphics/text.rb
  6. 4
      samples/text_options.rb
  7. 46
      spec/args/smart_quotes_spec.rb
  8. 71
      spec/args/typographer_spec.rb
  9. 64
      spec/data/samples/embed_text.rb.txt
  10. 16
      spec/data/samples/text_options.rb.txt
  11. 5
      squib.sublime-project

11
README.md

@ -241,6 +241,17 @@ text(str: 'Gain 1 :health:') do |embed|
end end
``` ```
###Markup
If you want to do specialized formatting within a given string, Squib has lots of options. By setting `markup: true`, you enable tons of text processing. This includes:
* Pango Markup. This is an HTML-like formatting language that specifies formatting inside your string. Pango Markup essentially supports any formatting option, but on a letter-by-letter basis. Such as: font options, letter spacing, gravity, color, etc. See the [Pango docs](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html) for details.
* Quotes are converted to their curly counterparts where appropriate (i.e. “smart quotes” instead of "straight quotes").
* Apostraphes are converted to curly as well.
* LaTeX-style quotes are explicitly converted (<tt>``like this''</tt>)
* Em-dash and en-dash are converted with triple and double-dashes respectively (<tt>--</tt> is an en-dash, and <tt>---</tt> becomes an em-dash.)
* Ellipses can be specified with <tt>...</tt>. Note that this is entirely different from the `ellipsize` option (which determines what to do with overflowing text).
### Text Samples ### Text Samples
Examples of all of the above are crammed into the `text_options.rb` sample [found here](https://github.com/andymeneely/squib/tree/master/samples/text_options.rb). Examples of all of the above are crammed into the `text_options.rb` sample [found here](https://github.com/andymeneely/squib/tree/master/samples/text_options.rb).

7
lib/squib/api/text.rb

@ -1,5 +1,4 @@
require 'squib/api/text_embed' require 'squib/api/text_embed'
require 'squib/args/smart_quotes'
module Squib module Squib
class Deck class Deck
@ -26,7 +25,7 @@ module Squib
# @option opts x [Integer] (0) the x-coordinate to place. Supports Unit Conversion, see {file:README.md#Units Units}. # @option opts x [Integer] (0) the x-coordinate to place. Supports Unit Conversion, see {file:README.md#Units Units}.
# @option opts y [Integer] (0) the y-coordinate to place. Supports Unit Conversion, see {file:README.md#Units Units}. # @option opts y [Integer] (0) the y-coordinate to place. Supports Unit Conversion, see {file:README.md#Units Units}.
# @option opts color [String] (:black) the color the font will render to. Gradients supported. See {file:README.md#Specifying_Colors___Gradients Specifying Colors} # @option opts color [String] (:black) the color the font will render to. Gradients supported. See {file:README.md#Specifying_Colors___Gradients Specifying Colors}
# @option opts markup: [Boolean] (false) Enable markup parsing of `str` using the HTML-like Pango Markup syntax, defined [here](http://ruby-gnome2.sourceforge.jp/hiki.cgi?pango-markup) and [here](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html). # @option opts markup: [Boolean] (false) Enable markup parsing of `str` using the HTML-like Pango Markup syntax, defined [here](http://ruby-gnome2.sourceforge.jp/hiki.cgi?pango-markup) and [here](https://developer.gnome.org/pango/stable/PangoMarkupFormat.html). Also does other replacements, such as smart quotes, curly apostraphes, en- and em-dashes, and explict ellipses (not to be confused with ellipsize option). See README for full explanation.
# @option opts width [Integer, :native] (:native) the width of the box the string will be placed in. Stretches to the content by default.. Supports Unit Conversion, see {file:README.md#Units Units}. # @option opts width [Integer, :native] (:native) the width of the box the string will be placed in. Stretches to the content by default.. Supports Unit Conversion, see {file:README.md#Units Units}.
# @option opts height [Integer, :native] the height of the box the string will be placed in. Stretches to the content by default. Supports Unit Conversion, see {file:README.md#Units Units}. # @option opts height [Integer, :native] the height of the box the string will be placed in. Stretches to the content by default. Supports Unit Conversion, see {file:README.md#Units Units}.
# @option opts layout [String, Symbol] (nil) entry in the layout to use as defaults for this command. See {file:README.md#Custom_Layouts Custom Layouts} # @option opts layout [String, Symbol] (nil) entry in the layout to use as defaults for this command. See {file:README.md#Custom_Layouts Custom Layouts}
@ -39,7 +38,6 @@ module Squib
# @option opts ellipsize [:none, :start, :middle, :end, true, false] (:end) When width and height are set, determines the behavior of overflowing text. Also: `true` maps to `:end` and `false` maps to `:none`. Default `:end` # @option opts ellipsize [:none, :start, :middle, :end, true, false] (:end) When width and height are set, determines the behavior of overflowing text. Also: `true` maps to `:end` and `false` maps to `:none`. Default `:end`
# @option opts angle [FixNum] (0) Rotation of the text in radians. Note that this rotates around the upper-left corner of the text box, making the placement of x-y coordinates slightly tricky. # @option opts angle [FixNum] (0) Rotation of the text in radians. Note that this rotates around the upper-left corner of the text box, making the placement of x-y coordinates slightly tricky.
# @option opts hint [String] (:nil) draw a rectangle around the text with the given color. Overrides global hints (see {Deck#hint}). # @option opts hint [String] (:nil) draw a rectangle around the text with the given color. Overrides global hints (see {Deck#hint}).
# @options ops quotes [:smart, :dumb, or Array]. Convert straight ("dumb") quotes to curly ("smart") quotes. The 'smart' option assumes UTF-8 characters. If you supply a two-element array of characters, those will be used (first is left, second is right). Smart quoting looks for a quote next to a letter, word, number, or underscore character. Default is to show straight quotes.
# @return [Array] Returns an Array of hashes keyed by :width and :height that mark the ink extents of the text rendered. # @return [Array] Returns an Array of hashes keyed by :width and :height that mark the ink extents of the text rendered.
# @api public # @api public
def text(opts = {}) def text(opts = {})
@ -50,8 +48,7 @@ module Squib
yield(embed) if block_given? #store the opts for later use yield(embed) if block_given? #store the opts for later use
extents = Array.new(@cards.size) extents = Array.new(@cards.size)
opts[:range].each do |i| opts[:range].each do |i|
str = Args::SmartQuotes.new.process(opts[:str][i], opts[:quotes][i]) extents[i] = @cards[i].text(embed, opts[:str][i],
extents[i] = @cards[i].text(embed, str,
opts[:font][i], opts[:font_size][i], opts[:color][i], opts[:font][i], opts[:font_size][i], opts[:color][i],
opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i], opts[:x][i], opts[:y][i], opts[:width][i], opts[:height][i],
opts[:markup][i], opts[:justify][i], opts[:wrap][i], opts[:markup][i], opts[:justify][i], opts[:wrap][i],

29
lib/squib/args/smart_quotes.rb

@ -1,29 +0,0 @@
module Squib
module Args
class SmartQuotes
def process(str, opt)
clean_opt = opt.to_s.downcase.strip
return str if clean_opt.eql? 'dumb'
if clean_opt.eql? 'smart'
quotify(str) # default to UTF-8
else
quotify(str, opt) # supplied quotes
end
end
# Convert regular quotes to smart quotes by looking for
# a boundary between a word character (letters, numbers, underscore)
# and a quote. Replaces with the UTF-8 equivalent.
# :nodoc:
# @api private
def quotify(str, quote_chars = ["\u201C", "\u201D"])
left_regex = /(\")(\w)/
right_regex = /(\w)(\")/
str.gsub(left_regex, quote_chars[0] + '\2')
.gsub(right_regex, '\1' + quote_chars[1])
end
end
end
end

96
lib/squib/args/typographer.rb

@ -0,0 +1,96 @@
require 'squib/constants'
module Squib
module Args
class Typographer
def initialize(config = CONFIG_DEFAULTS)
@config = config
end
def process(str)
[
:left_curly,
:right_curly,
:apostraphize,
:right_double_quote,
:left_double_quote,
:right_single_quote,
:left_single_quote,
:ellipsificate,
:em_dash,
:en_dash ].each do |sym|
str = each_non_tag(str) do |token|
self.method(sym).call(token)
end
end
str
end
# Iterate over each non-tag for processing
# Allows us to ignore anything inside < and >
def each_non_tag(str)
full_str = ''
tag_delimit = /(<(?:(?!<).)*>)/ # use non-capturing group w/ negative lookahead
str.split(tag_delimit).each do |token|
if token.start_with? '<'
full_str << token # don't process tags
else
full_str << yield(token)
end
end
return full_str
end
# Straightforward replace
def left_curly(str)
str.gsub('``', "\u201C")
end
# Straightforward replace
def right_curly(str)
str.gsub(%{''}, "\u201D")
end
# A quote between two letters is an apostraphe
def apostraphize(str)
str.gsub(/(\w)(\')(\w)/, '\1' + "\u2019" + '\3')
end
# Quote next to non-whitespace curls
def right_double_quote(str)
str.gsub(/(\S)(\")/, '\1' + "\u201D")
end
# Quote next to non-whitespace curls
def left_double_quote(str)
str.gsub(/(\")(\S)/, "\u201C" + '\2')
end
# Quote next to non-whitespace curls
def right_single_quote(str)
str.gsub(/(\S)(\')/, '\1' + "\u2019")
end
# Quote next to non-whitespace curls
def left_single_quote(str)
str.gsub(/(\')(\S)/, "\u2018" + '\2')
end
# Straightforward replace
def ellipsificate(str)
str.gsub('...', "\u2026")
end
# Straightforward replace
def en_dash(str)
str.gsub('--', "\u2013")
end
# Straightforward replace
def em_dash(str)
str.gsub('---', "\u2014")
end
end
end
end

5
lib/squib/graphics/text.rb

@ -1,4 +1,5 @@
require 'pango' require 'pango'
require 'squib/args/typographer'
module Squib module Squib
class Card class Card
@ -153,7 +154,9 @@ module Squib
layout = cc.create_pango_layout layout = cc.create_pango_layout
layout.font_description = font_desc layout.font_description = font_desc
layout.text = str layout.text = str
layout.markup = str if markup if markup
layout.markup = Args::Typographer.new(@deck.config).process(layout.text)
end
set_wh!(layout, width, height) set_wh!(layout, width, height)
set_wrap!(layout, wrap) set_wrap!(layout, wrap)

4
samples/text_options.rb

@ -78,12 +78,12 @@ Squib::Deck.new(width: 825, height: 1125, cards: 3) do
embed.svg key: ':health:', width: 28, height: 28, file: 'glass-heart.svg' embed.svg key: ':health:', width: 28, height: 28, file: 'glass-heart.svg'
end end
text str: '<b>Markup</b> is also <i>quite</i> <s>easy</s> awesome', text str: "<b>Markup</b> is <i>quite</i> <s>'easy'</s> <span fgcolor=\"\#ff0000\">awesome</span>. Can't beat those \"smart\" 'quotes', now with 10--20% more en-dashes --- and em-dashes --- with explicit ellipses too...",
markup: true, markup: true,
x: 50, y: 1000, x: 50, y: 1000,
width: 750, height: 100, width: 750, height: 100,
valign: :bottom, valign: :bottom,
font: 'Arial 32', hint: :cyan font: 'Serif 18', hint: :cyan
save prefix: 'text_', format: :png save prefix: 'text_', format: :png

46
spec/args/smart_quotes_spec.rb

@ -1,46 +0,0 @@
require 'spec_helper'
require 'squib/args/smart_quotes'
describe Squib::Args::SmartQuotes do
it 'does nothing on a non-quoted string' do
expect(subject.quotify('nothing')).to eq('nothing')
end
it 'left quotes at the beginning' do
expect(subject.quotify('"foo')).to eq("\u201Cfoo")
end
it 'left quotes in the middle of the string' do
expect(subject.quotify('hello "foo')).to eq("hello \u201Cfoo")
end
it 'right quotes at the end of a string' do
expect(subject.quotify('foo"')).to eq("foo\u201D")
end
it 'handles the entire string quoted' do
expect(subject.quotify('"foo"')).to eq("\u201Cfoo\u201D")
end
it "quotes in the middle of the string" do
expect(subject.quotify('hello "foo" world')).to eq("hello \u201Cfoo\u201D world")
end
it "allows custom quotes for different character sets" do
expect(subject.quotify('hello "foo" world', %w({ }))).to eq("hello {foo} world")
end
it "processes dumb quotes" do
expect(subject.process('hello "foo" world', :dumb)).to eq("hello \"foo\" world")
end
it "processes smart quotes" do
expect(subject.process('hello "foo" world', :smart)).to eq("hello \u201Cfoo\u201D world")
end
it "processes custom quotes" do
expect(subject.process('hello "foo" world', %w({ }))).to eq("hello {foo} world")
end
end

71
spec/args/typographer_spec.rb

@ -0,0 +1,71 @@
require 'spec_helper'
require 'squib/args/typographer'
describe Squib::Args::Typographer do
subject(:t) { Squib::Args::Typographer.new }
it 'does nothing on a non-quoted string' do
expect(t.process(%{nothing})).to eq(%{nothing})
end
it 'left quotes at the beginning' do
expect(t.process(%{"foo})).to eq(%{\u201Cfoo})
end
it 'left quotes in the middle of the string' do
expect(t.process(%{hello "foo})).to eq(%{hello \u201Cfoo})
end
it 'right quotes at the end' do
expect(t.process(%{foo"})).to eq(%{foo\u201D})
end
it 'handles the entire string quoted' do
expect(t.process(%{"foo"})).to eq(%{\u201Cfoo\u201D})
end
it "quotes in the middle of the string" do
expect(t.process(%{hello "foo" world})).to eq(%{hello \u201Cfoo\u201D world})
end
it "single left quotes at the beginning" do
expect(t.process(%{'foo})).to eq(%{\u2018foo})
end
it "single right quotes at the end" do
expect(t.process(%{foo'})).to eq(%{foo\u2019})
end
it "single quotes in the middle" do
expect(t.process(%{a 'foo' bar})).to eq(%{a \u2018foo\u2019 bar})
end
it "handles apostraphes" 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})
end
it "replaces the straightforward ones" do
expect(t.process(%{``hi...'' -- ---})).to eq(%{\u201Chi\u2026\u201D \u2013 \u2014})
end
it "does nothing on lone quotes" do
expect(t.process(%{"})).to eq(%{"})
expect(t.process(%{'})).to eq(%{'})
end
it "ignores stuff in <tags>" do
expect(t.process(%{<span weight="bold">"can't"</span>})).to eq(%{<span weight="bold">\u201Ccan\u2019t\u201D</span>})
end
context 'configured' do
#TODO
end
end

64
spec/data/samples/embed_text.rb.txt

@ -12,13 +12,67 @@ cairo: rounded_rectangle([0, 0, 825, 1125, 0, 0])
cairo: set_source_color(["#0000"]) cairo: set_source_color(["#0000"])
cairo: fill([]) cairo: fill([])
cairo: restore([]) cairo: restore([])
cairo: antialias=(["subpixel"])
cairo: antialias=(["subpixel"])
cairo: antialias=(["subpixel"])
cairo: save([])
cairo: set_source_color([:black])
cairo: translate([0, 0])
cairo: rotate([0])
cairo: move_to([0, 0])
pango font: size=([18432])
pango: font_description=([MockDouble])
pango: text=(["Take 1 :tool: and gain 2 :health:."])
pango: width=([184320])
pango: height=([307200])
pango: wrap=([#<Pango::Layout::WrapMode word-char>])
pango: ellipsize=([#<Pango::Layout::EllipsizeMode none>])
pango: alignment=([#<Pango::Layout::Alignment left>])
pango: justify=([false])
pango: spacing=([0])
cairo: update_pango_layout([MockDouble])
pango: markup=(["Take 1 :tool: and gain 2 :health:."])
cairo: move_to([0, 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([])
cairo: save([])
cairo: set_source_color([:black])
cairo: translate([0, 0])
cairo: rotate([0])
cairo: move_to([0, 0])
pango font: size=([32768])
pango: font_description=([MockDouble])
pango: text=(["Take 1 :tool: and gain 2 :health:."])
pango: width=([184320])
pango: height=([307200])
pango: wrap=([#<Pango::Layout::WrapMode word-char>])
pango: ellipsize=([#<Pango::Layout::EllipsizeMode none>])
pango: alignment=([#<Pango::Layout::Alignment left>])
pango: justify=([false])
pango: spacing=([0])
cairo: update_pango_layout([MockDouble])
pango: markup=(["Take 1 :tool: and gain 2 :health:."])
cairo: move_to([0, 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([])
cairo: save([]) cairo: save([])
cairo: set_source_color([:black]) cairo: set_source_color([:black])
cairo: translate([200, 0]) cairo: translate([0, 0])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango font: size=([46080])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["Middle align: Take 1 :tool: and gain 2 :health:. Take 2 :tool: and gain 3 :purse:"]) pango: text=(["Take 1 :tool: and gain 2 :health:."])
pango: width=([184320]) pango: width=([184320])
pango: height=([307200]) pango: height=([307200])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])
@ -27,7 +81,7 @@ pango: alignment=([#<Pango::Layout::Alignment left>])
pango: justify=([false]) pango: justify=([false])
pango: spacing=([0]) pango: spacing=([0])
cairo: update_pango_layout([MockDouble]) cairo: update_pango_layout([MockDouble])
pango: markup=(["Middle align: Take 1 :tool: and gain 2 :health:. Take 2 :tool: and gain 3 :purse:"]) pango: markup=(["Take 1 :tool: and gain 2 :health:."])
cairo: move_to([0, 0.0]) cairo: move_to([0, 0.0])
cairo: update_pango_layout([MockDouble]) cairo: update_pango_layout([MockDouble])
cairo: show_pango_layout([MockDouble]) cairo: show_pango_layout([MockDouble])
@ -36,4 +90,6 @@ cairo: set_source_color([:cyan])
cairo: set_line_width([2.0]) cairo: set_line_width([2.0])
cairo: stroke([]) cairo: stroke([])
cairo: restore([]) cairo: restore([])
surface: write_to_png(["_output/embed_00.png"]) surface: write_to_png(["_output/embed_multi_00.png"])
surface: write_to_png(["_output/embed_multi_01.png"])
surface: write_to_png(["_output/embed_multi_02.png"])

16
spec/data/samples/text_options.rb.txt

@ -331,7 +331,7 @@ cairo: translate([65, 400])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, has a red hint, and \u201Csmart quotes\u201D"]) pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, has a red hint, and \"smart quotes\""])
pango: width=([307200]) pango: width=([307200])
pango: height=([128000]) pango: height=([128000])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])
@ -354,7 +354,7 @@ cairo: translate([65, 400])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, has a red hint, and \u201Csmart quotes\u201D"]) pango: text=(["This text has fixed width, fixed height, center-aligned, middle-valigned, has a red hint, and \"smart quotes\""])
pango: width=([307200]) pango: width=([307200])
pango: height=([128000]) pango: height=([128000])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])
@ -829,8 +829,8 @@ cairo: translate([50, 1000])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["<b>Markup</b> is also <i>quite</i> <s>easy</s> awesome"]) pango: text=(["<b>Markup</b> is <i>quite</i> <s>'easy'</s> <span fgcolor=\"#ff0000\">awesome</span>. Can't beat those \"smart\" 'quotes', now with 10--20% more en-dashes --- and em-dashes --- with explicit ellipses too..."])
pango: markup=(["<b>Markup</b> is also <i>quite</i> <s>easy</s> awesome"]) pango: markup=(["foo"])
pango: width=([768000]) pango: width=([768000])
pango: height=([102400]) pango: height=([102400])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])
@ -853,8 +853,8 @@ cairo: translate([50, 1000])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["<b>Markup</b> is also <i>quite</i> <s>easy</s> awesome"]) pango: text=(["<b>Markup</b> is <i>quite</i> <s>'easy'</s> <span fgcolor=\"#ff0000\">awesome</span>. Can't beat those \"smart\" 'quotes', now with 10--20% more en-dashes --- and em-dashes --- with explicit ellipses too..."])
pango: markup=(["<b>Markup</b> is also <i>quite</i> <s>easy</s> awesome"]) pango: markup=(["foo"])
pango: width=([768000]) pango: width=([768000])
pango: height=([102400]) pango: height=([102400])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])
@ -877,8 +877,8 @@ cairo: translate([50, 1000])
cairo: rotate([0]) cairo: rotate([0])
cairo: move_to([0, 0]) cairo: move_to([0, 0])
pango: font_description=([MockDouble]) pango: font_description=([MockDouble])
pango: text=(["<b>Markup</b> is also <i>quite</i> <s>easy</s> awesome"]) pango: text=(["<b>Markup</b> is <i>quite</i> <s>'easy'</s> <span fgcolor=\"#ff0000\">awesome</span>. Can't beat those \"smart\" 'quotes', now with 10--20% more en-dashes --- and em-dashes --- with explicit ellipses too..."])
pango: markup=(["<b>Markup</b> is also <i>quite</i> <s>easy</s> awesome"]) pango: markup=(["foo"])
pango: width=([768000]) pango: width=([768000])
pango: height=([102400]) pango: height=([102400])
pango: wrap=([#<Pango::Layout::WrapMode word-char>]) pango: wrap=([#<Pango::Layout::WrapMode word-char>])

5
squib.sublime-project vendored

@ -29,6 +29,11 @@
"shell_cmd": "rspec spec/samples/samples_regression_spec.rb", "shell_cmd": "rspec spec/samples/samples_regression_spec.rb",
"working_dir": "${project_path:${folder}}" "working_dir": "${project_path:${folder}}"
}, },
{
"name": "rspec spec/args/typographer_spec.rb",
"shell_cmd": "rspec spec/args/typographer_spec.rb",
"working_dir": "${project_path:${folder}}"
},
{ {
"name": "rspec spec/graphics/graphics_text_spec.rb", "name": "rspec spec/graphics/graphics_text_spec.rb",
"shell_cmd": "rspec spec/graphics/graphics_text_spec.rb", "shell_cmd": "rspec spec/graphics/graphics_text_spec.rb",

Loading…
Cancel
Save