Last active
October 16, 2022 18:30
-
-
Save mixio/2a31288be50061f3350a119c24a88b49 to your computer and use it in GitHub Desktop.
BBEdit script to sort indented hierarchical lists
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* | |
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 | |
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