Skip to content

Instantly share code, notes, and snippets.

@mixio
Last active October 16, 2022 18:30
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 mixio/2a31288be50061f3350a119c24a88b49 to your computer and use it in GitHub Desktop.
Save mixio/2a31288be50061f3350a119c24a88b49 to your computer and use it in GitHub Desktop.
BBEdit script to sort indented hierarchical lists
(*
README
Considering that list indentation is a form of compression, this BBEdit script
decompresses the list, sorts it with the shell `sort` command, and compresses it back again.
In doing so, the indented list will be sorted, sub lists will be merged and
duplicates will be eliminated.
For sorting options (case insensitive, etc.) see the `sort` man page in terminal and
adapt the do shell script according to your needs.
This script work on the selection of the front document or on the whole document if
nothing is selected. Selected lines should cover whole sub-lists appropriately to make sense.
By default the script accepts TAB or 4 SPACES indented lists but outputs TAB indented lists.
If you'd prefer a final 4 SPACES indented list, change the `vIndentation` variable.
INSTALL
Copy this script to ~/Library/Library/Application\ Support/BBEdit/Scripts/sort_and_merge_indented_list.applescript
Call it from BBEdit's AppleScript menu.
TEST SAMPLE
--
ambition
{ambitious}
ancient
train
ancient civilization
apex
{#1}
{number 1}
appetizing
apprehend
approach
{approaching}
approachable
approval
{approve}
{approving}elegant
email
embryonic
emotion
{emotional}
{emotions}
affection
devotion
fondness
love
passion
sympathy
tenderness
warmth
agitated
{agitation}
flustered
frantic
amusement
{amused}
{amusing}
ego
elegance
embarrassment
emergence
empathy
emphasis
enchantment
encouragement
ending
endurance
energy
enhancement
enjoyment
ennui
emotion
{sad}
funny
hilarious
enthusiasm
envy
equality
--
*)
--
use AppleScript version "2.8"
use scripting additions
use framework "Foundation"
--
set v4Spaces to " "
set vIndentation to tab -- Use TAB indentation. Change to v4Spaces if you prefer 4 SPACES indentation.
--
on split(aText, aDelimiters)
set {vOldDelim, AppleScript's text item delimiters} to {AppleScript's text item delimiters, aDelimiters}
set vItems to every text item of aText
set AppleScript's text item delimiters to vOldDelim
return vItems
end split
--
on join(aList, aDelimiter)
set {vOldDelim, AppleScript's text item delimiters} to {AppleScript's text item delimiters, aDelimiter}
set vText to aList as string
set AppleScript's text item delimiters to vOldDelim
return vText
end join
--
on decompress(aPreviousList, aCurrentList)
copy aPreviousList to vPreviousList
copy aCurrentList to vCurrentList
set vPreviousCount to count (vPreviousList)
set vCurrentCount to count (vCurrentList)
if vCurrentCount > 1 then
if vCurrentCount = vPreviousCount then
repeat with vIndex from 1 to (vPreviousCount - 1)
set item vIndex of vCurrentList to item vIndex of vPreviousList
end repeat
else
repeat with vIndex from 1 to vCurrentCount
if (item vIndex of vCurrentList) as string = "" then
set item vIndex of vCurrentList to item vIndex of vPreviousList
else
exit repeat
end if
end repeat
end if
end if
return vCurrentList
end decompress
--
on compress(aPreviousList, aCurrentList)
copy aPreviousList to vPreviousList
copy aCurrentList to vCurrentList
set vPreviousCount to count (vPreviousList)
set vCurrentCount to count (vCurrentList)
repeat with vIndex from 1 to (vCurrentCount - 1)
try
if (item vIndex of vPreviousList) as string = (item vIndex of vCurrentList) as string then
set item vIndex of vCurrentList to ""
end if
end try
end repeat
return vCurrentList
end compress
--
try
tell application "BBEdit"
tell first document of first window
set vSelection to selection of its window
if class of vSelection is insertion point then
set vStartLine to 1
set vEndLine to (startLine of its last line) as integer
else if class of vSelection is list then
set vStartLine to (startLine of first item of vSelection) as integer
set vEndLine to (endLine of last item of vSelection) as integer
else
set vStartLine to (startLine of vSelection) as integer
set vEndLine to (endLine of vSelection) as integer
end if
if vEndLine - vStartLine < 1 then
error "Error: You Need to select more than 2 lines."
end if
select its lines vStartLine thru vEndLine
set vLines to my split((its lines vStartLine thru vEndLine) as string, {return, linefeed})
set vSplittedLines to {}
repeat with vLine in vLines
if length of vLine > 0 then
set vSplittedLine to my split(vLine as string, {tab, v4Spaces})
set end of vSplittedLines to vSplittedLine
end if
end repeat
set vCount to length of vSplittedLines
set vDecompressedLine to item 1 of vSplittedLines
set vDecompressedLines to {vDecompressedLine}
repeat with i from 2 to vCount
set vCurrentLine to item i of vSplittedLines
set vDecompressedLine to my decompress(vDecompressedLine, vCurrentLine)
set end of vDecompressedLines to my join(vDecompressedLine, vIndentation)
end repeat
set vText to my join(vDecompressedLines, linefeed)
tell AppleScript
set vSortedText to do shell script ("echo" & space & (the quoted form of vText) & "| /usr/bin/sort --unique")
end tell
set vSortedLines to my split(vSortedText, {return, linefeed})
set vSortedSplittedLines to {}
repeat with vSortedLine in vSortedLines
set vSplittedLine to my split(vSortedLine, vIndentation)
set end of vSortedSplittedLines to vSplittedLine
end repeat
set vCount to length of vSortedSplittedLines
set vCompressedLine to item 1 of vSortedSplittedLines
set vCompressedLines to {vCompressedLine}
repeat with i from 2 to vCount
set vPreviousLine to item (i - 1) of vSortedSplittedLines
set vCurrentLine to item i of vSortedSplittedLines
set vCompressedLine to my compress(vPreviousLine, vCurrentLine)
set end of vCompressedLines to my join(vCompressedLine, vIndentation)
end repeat
set vText to my join(vCompressedLines, linefeed)
copy vText & linefeed to selection of its window
end tell
end tell
on error aMessage number aErrorNumber
if aErrorNumber ≠ -128 then -- Error number -128 (User Cancelled).
display dialog aMessage
end if
end try
--
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment