I do most of my automation and string manipulation scripting using Ruby. I know it’s not the most popular language these days, but it’s the one I know the best (thanks to my days of hacking on TextMate bundles) and it’s usually the fastest way for me to solve a problem. I have reams of snippets saved (and easily accessible with Snibbets) and thought I’d share a few that are useful for everyday scripting on macOS.
Scrub
Scrub uses the encode function to switch a string to UTF-16 discarding invalid characters (gremlins), then back to UTF-8. Applied as a String method, you can then use input.scrub to get clean text with all gremlins removed.
This can be modified or turned into a case statement to determine operating system. I often only need it to check if I can run Mac-only tools like pbcopy or not.
`uname`.strip=="Darwin"
Get macOS version
Just in case your script needs to behave differently across OS versions:
defmacos_versionbegin`sw_vers`.strip.each_linedo|line|ifline.strip=~/ProductVersion:\s+([\d.]+)$/returnRegexp.last_match(1).to_fendendreturn0rescuewarn'Failed to retrieve macOS version'Process.exit1endend
Rounding numbers
class::Numeric# Round to nearest 5defround5((self*0.2).round/0.2)end# Round to nearest 10defround10((self*0.1).round/0.1)endend
Human-readable file size
The #to_human method will convert 293592035 to “280MB”.
I used to use the CGI library for url encoding, but it doesn’t properly percent-encode spaces as %20, but rather as +, which breaks a lot of applications. The solution (as opposed to doing a manual search and replace) is to use the ERB library instead:
require'erb'ERB::Util.url_encode('string to encode')
Get a single keypress
For dialogs where you want to act as soon as a key is pressed without requiring pressing Return:
defget_keypresssystem"stty raw -echo"STDIN.getcensuresystem"stty -raw echo"endkey=get_keypress.chr
Get the longest string in an array of strings
Of limited utility but I use it all the time when doing search algorithms:
class::Arraydeflongest_elementgroup_by(&:size).max.last[0]# Leave off the [0] to get an array containing all of the longest elements when there's a tieendendp['short','longest','longer'].longest_element#=> "longest"
Symbolize hash keys
If you’re creating nested hash objects that end up with a mix of string and symbol keys, the easiest thing to do is symbolize all keys. #to_sym won’t do anything if the key is already a symbol.
class::Hash# Turn all keys into symbols, including nested hashesdefsymbolize_keyseach_with_object({}){|(k,v),hsh|hsh[k.to_sym]=v.is_a?(Hash)?v.symbolize_keys:v}endend# >> h = {'one' => 2, 'two' => { 'three' => 4 } }# >> h.symbolize_keys# {# :one => 2,# :two => {# :three => 4# }# }
I hope that’s useful for aspiring Ruby scripters. If there’s interest, I can post (tons) more, but I also hope to get better about creating Gists that could be more easily searchable as a reference. The next step for Snibbets?
Bonus tip: Clipboard Preview
There’s a shell function I use frequently, easily replicable in any shell. It just shows you the contents of your clipboard (assuming text) without requiring a paste:
pbpaste | cat
In Fish that looks like:
# Defined in /Users/ttscoff/.config/fish/functions/cbp.fish @ line 1
function cbp --description 'ClipBoard Preview'
pbpaste | cat
end
Like I said, useful in any shell as a way to ensure what you think is on your clipboard actually is. Just type cbp and get a preview before pasting anywhere.