Skip to content

Instantly share code, notes, and snippets.

@ttscoff ttscoff/ezsnippets.rb
Last active Sep 14, 2016

Embed
What would you like to do?
ezsnippets v1, define expansions as you write (based on work by Stephen Margheim: http://www.alfredforum.com/topic/4680-snippets-on-the-fly-text-expansion/))
#!/usr/bin/ruby
=begin
# ezsnippets
Brett Terpstra 2014, MIT License
Based on a great idea by Stephen Margheim <http://twitter.com/s_margheim>
- http://www.alfredforum.com/topic/4680-snippets-on-the-fly-text-expansion/
- https://github.com/smargh/alfred_snippets
## Summary
Create snippets on the fly as you write, then have them expanded in the
final document
## Details
This version of the idea lets you write snippets definitions right in your
text. The first time you type a long phrase you know you're going to want
again, just surround it in curly brackets and end it with a colon and a
shortcut. The shortcut can be anything you want, but it's probably best to use
something you're not likely to type again. Start it with a double comma or
other punctuation if you want to be safe.
The shortcut can have no spaces, before, inside, or after it. Other than that,
it's up to you. You can use *, ?, ,, :, \, ~, etc. If you're using a colon as
a prefix, make sure there are three in a row (2 to split, 1 for the
definition).
For accuracy, the script will only match the snippet if it's preceded by a
word boundary or a space. That allows some matching safety and precision while
still allowing to you pluralize the snippet in the text. Snippets will be
replaced in order from longest to shortest, so ",,ru" won't overwrite
",,rumble".
Snippet abbreviations can _only_ be defined once. If you define the same
snippet abbreviation two or more times, the script will gracefully fail and no
replacements will be made. It's assumed that this was a mistake on your part,
and that there will be multiple abbreviations in the document that are
intended to mean different things.
The original script is designed for Alfred, this one is probably going
to be used in Services and PopClip.
## Example:
Lorem ipsum dolor sit amet {on-the-fly text expansion::,otf},
consectetur adipisicing elit ,otf, sed do eiusmod tempor incididunt
,otf.
becomes:
Lorem ipsum dolor sit amet on-the-fly text expansion,
consectetur adipisicing elit on-the-fly text expansion, sed do eiusmod
tempor incididunt on-the-fly text expansion.
## Usage:
Just pipe text containing snippet definitions and instances to it.
cat "mywriting.md" | ezsnippets
=end
silent = true
def usage(err=false)
puts "cat <filename> | ezsnippets"
if err
Process.exit 1
else
Process.exit 0
end
end
args = ARGV.join(" ")
if args =~ /(d(ebug)?|t(est)?)/
silent = false
input = STDIN.stat.size > 0 ? STDIN.read.force_encoding('utf-8') : DATA.read
else
if STDIN.stat.size > 0
if RUBY_VERSION.to_f > 1.9
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8
input = STDIN.read.force_encoding('utf-8')
else
input = STDIN.read
end
if input.length == 0
$stderr.puts "Input must be received on STDIN"
Process.exit 1
end
else
usage(true)
end
end
message = []
abbrs = {}
total_replaced = {}
found = 0
input.gsub! (/\{(.*?)::(\S+)\}/m) do |match|
found += 1
unless abbrs.has_key? $2
abbrs[$2] = $1
else
# $stderr.puts "Abbreviation #{$2} defined multiple times."
# $stderr.puts "Edit text with an alternate snippet for additional instances of \"#{$1}\"."
# raise MultipleDefinitionException
message.push("Abbreviation #{$2} defined multiple times.\nEdit text with an alternate snippet for additional instances of \"#{$1}\".")
found = -1
break
end
$1
end
if found < 1
$stdout.puts input
message.push("No snippet definitions found in text") if found == 0
$stderr.puts %Q{\n---\n#{message.join("\n")}} unless message.empty? || silent
Process.exit
else
message.push("Found #{abbrs.length} snippet definitions")
end
abbrs.sort_by {|k,v| k.length }.reverse.each {|short, long|
$stderr.printf("%s: %s\n", short, long) unless silent
total_replaced[short] = 0
input.gsub!(/(?<=[\b\s])#{Regexp.escape(short)}/) do |m|
total_replaced[short] += 1
long
end
}
total = abbrs.length
total_replaced.each {|abbr,count|
message.push("#{abbr}:\t\t#{count}")
total += count.to_i
}
message.push("#{total} replacements made in file")
$stdout.print input
unless silent
$stderr.puts message.join("\n")
end
__END__
Lorem ipsum {a test string::,tst} dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut {a longer phrase that will repeat. Not sure why you'd do this but
it can break lines and paragraphs, too::,ns} enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. {The
Ministry of Silly Walks::,sw}. Duis aute irure dolor in reprehenderit in
voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit
anim id est laborum.
Sed ut perspiciatis unde omnis ,tst iste natus error sit voluptatem accusantium
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
veritatis et quasi architecto beatae vitae dicta sunt explicabo. Nemo enim
ipsam voluptatem ,ns quia voluptas sit aspernatur aut odit aut fugit, sed quia
consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque
porro quisquam est, qui ,sw dolorem ipsum quia dolor sit amet, consectetur,
adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et
dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam, quis
nostrum exercitationem ullam corporis suscipit laboriosam, nisi ut aliquid ex
ea commodi consequatur? Quis autem vel eum iure reprehenderit qui in ea
voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem
eum fugiat quo voluptas nulla pariatur?
,sw
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.