Skip to content

Instantly share code, notes, and snippets.

@symmetriq
Last active February 27, 2018 04:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save symmetriq/a3b1965405d413878516782c3aac8983 to your computer and use it in GitHub Desktop.
Save symmetriq/a3b1965405d413878516782c3aac8983 to your computer and use it in GitHub Desktop.
BBEdit: Tidy Values
#!/usr/bin/env ruby
#-------------------------------------------------------------------------------
# Tidy Values
#-------------------------------------------------------------------------------
# Jason Sims <jason@symmetriq.com>
#-------------------------------------------------------------------------------
#
# Aligns a series of `key: value` or `var = value` lines
#
# - Language agnostic
# - Supports quoted keys (' or ") if lines are key: value pairs
# - Supports `||=`
# - Supports mixed `||=` and `=`; the `=` will be aligned
# - Supports leading commas
# - Preserves indentation
# - Unlike many BBEdit filters, this doesn't strip the trailing newline, so you
# can quickly select entire lines by clicking and dragging in the line number
# column on the left.
#
#-------------------------------------------------------------------------------
#
# Usage:
# Select multiple lines of text that contain `key: value` or `var = value`, then
# apply this via keyboard shortcut or Text → Apply Text Filter → Tidy Values.
#
# CAUTION:
# This removes lines that don't contain either of the above expressions.
#
#-------------------------------------------------------------------------------
#
# Installation in BBEdit:
#
# 1. Place this file in your "Text Filters" directory:
# ~/Library/Application Support/BBEdit/Text Filters/
# or
# ~/Dropbox/Application Support/BBEdit/Text Filters/
#
# 2. Optionally assign a keyboard shortcut to "Tidy Values" in:
# BBEdit → Preferences → Menus & Shortcuts → Text → Apply Text Filter
#
#-------------------------------------------------------------------------------
# More scripts & snippets here:
# https://gist.github.com/symmetriq
#-------------------------------------------------------------------------------
input = ARGF.set_encoding('UTF-8').read
# here's an example of what this script does:
indent = ''
leading_comma = ''
operators = {}
longest_operator = 0
keys = []
values = []
input.split("\n").each_with_index do |line, i|
matches = /^( *)(, *)?(?:('[^']+'|"[^"]+"|[^ :]+) *(:)|([^ =]+) *((?:\|\|)?=)) *(.*)$/.match line
next if matches.nil?
# capture indent for each line in case the selection uses leading commas and
# the first line has no comma (this could be more efficient by only capturing
# the indent of the last line, but then we'd also need to make sure the last
# line isn't empty)
indent = matches[1] if matches[1]
leading_comma = matches[2] if matches[2] && leading_comma.empty?
key = matches[3] || matches[5]
keys.push key
operator = matches[4] || matches[6]
operators[key] = operator
longest_operator = [operator.length, longest_operator].max
values.push matches[7]
end
longest_key = keys.max_by(&:length).length
output = []
keys.zip(values).each do |key, value|
operator = operators[key]
prefix = output.length == 0 ? ' ' * leading_comma.length : leading_comma
output.push "#{indent}#{prefix}#{key.ljust(longest_key)} #{operator.rjust(longest_operator)} #{value}"
end
print output.join("\n")
print "\n" if input[-1] == "\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment