Last active
August 31, 2018 06:02
-
-
Save fractaledmind/6470371 to your computer and use it in GitHub Desktop.
This script translates simple Markdown outlines into formatted numeral outlines. This script works from the clipboard, so it is totally application agnostic. This newest version allows for Outline Text along with your Markdown outline items and allows you to use any Markdown symbol for your outline ("*", "-", etc.)
This file contains hidden or 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
(* CONVERT MARKDOWN LIST TO NUMERAL OUTLINE | |
-- Stephen Margheim | |
-- open source | |
This script translates simple Markdown outlines into formatted numeral outlines. For example, an outline of the the form: | |
- item 1 | |
- sub-item 1 | |
- sub-sub-item 1 | |
- sub-sub-sub-item 1 | |
- sub-item 2 | |
- item 2 | |
This would translate into: | |
1. item 1 | |
1.1 sub-item 1 | |
1.1.1 sub-sub-item 1 | |
1.1.1.1 sub-sub-sub-item 1 | |
1.2 sub-sub-item 2 | |
2. item 2 | |
This script works from the clipboard, so it is totally application agnostic. It only handles outlines that go no more than 6 levels deep. | |
*) | |
--set up properties | |
property theTab : ASCII character 9 | |
property LF : ASCII character 10 | |
--get the input text | |
set t to the clipboard | |
--find and replace all tabs with "x" | |
set f to " " | |
set r to "x" | |
set nt to my find_replace_repeated(t, f, r) | |
--create list | |
set l to paragraphs of nt | |
--get the Markdown Symbol used in the Outline | |
set x to item 1 of l | |
set x_chars to text items of x | |
set OutlineSymbol to item 1 of x_chars | |
--separate the outline prefixes from the outline's text | |
set theOutlineText_list to {} | |
set theOutlinePrefix_list to {} | |
repeat with i from 1 to count of l | |
set x to item i of l | |
set post to my rightString(x, OutlineSymbol) | |
copy post to end of theOutlineText_list | |
set pre to my leftString(x, OutlineSymbol) | |
copy pre to end of theOutlinePrefix_list | |
end repeat | |
--add "-" back to outline prefixes | |
repeat with i from 1 to count of theOutlinePrefix_list | |
set x to item i of theOutlinePrefix_list | |
if x is "" then | |
set item i of theOutlinePrefix_list to "-" | |
else | |
set a to x & "-" | |
set new to my replaceString(x, x, a) | |
set item i of theOutlinePrefix_list to new | |
end if | |
end repeat | |
--prepare to transform outline prefixes to proper numbers | |
set theList to theOutlinePrefix_list | |
set baseLength to length of item 1 of theList | |
set item 1 of theList to "1" | |
--generate proper numbers | |
repeat with i from 2 to count of theList | |
--i is child of (i - 1) | |
if length of item (i - 1) of theList is less than (length of ((item i of theList) as string)) then | |
set x to item i of theList | |
set num to ((item (i - 1) of theList) as number) | |
set y to (num * 10) + 1 | |
set item i of theList to y as string | |
--i is sibling of (i - 1) | |
else if length of item (i - 1) of theList is equal to length of (item i of theList as string) then | |
set x to item i of theList | |
set num to ((item (i - 1) of theList) as number) | |
set y to (num + 1) | |
set item i of theList to y as string | |
--i is sibling of some preceeding item | |
else if length of item (i - 1) of theList is greater than length of (item i of theList as string) then | |
set x to item i of theList | |
set x_len to length of item i of theList | |
set x_pos to i | |
set l to reverse of theList | |
set rx_pos to ((count of theList) + 1) - x_pos | |
repeat with j from (rx_pos + 1) to count of l | |
if length of item j of l = x_len then | |
set y_pos to (((count of theList) + 1) - j) | |
set y_num to item y_pos of theList as number | |
set y to y_num + 1 | |
set item i of theList to y as string | |
exit repeat | |
end if | |
end repeat | |
end if | |
end repeat | |
--insert periods to create full outline format | |
set z to {} | |
repeat with i from 1 to count of theList | |
set chars to text items of item i of theList | |
if (count of chars) is greater than 0 then | |
set p_list to my insertItem(chars, ".", 1) | |
if (count of chars) is greater than 2 then | |
set p_list to my insertItem(p_list, ".", 3) | |
if (count of chars) is greater than 3 then | |
set p_list to my insertItem(p_list, ".", 5) | |
if (count of chars) is greater than 4 then | |
set p_list to my insertItem(p_list, ".", 7) | |
if (count of chars) is greater than 5 then | |
set p_list to my insertItem(p_list, ".", 9) | |
set p_text to p_list as string | |
copy p_text to end of z | |
end if | |
set p_text to p_list as string | |
copy p_text to end of z | |
end if | |
set p_text to p_list as string | |
copy p_text to end of z | |
end if | |
set p_text to p_list as string | |
copy p_text to end of z | |
end if | |
set p_text to p_list as string | |
copy p_text to end of z | |
end if | |
end repeat | |
--remove any duplicate entries from the list | |
set finalList to my removeDuplicates(z) | |
--add tabs back to list | |
repeat with i from 1 to count of finalList | |
if length of item i of finalList = 3 then | |
set item i of finalList to theTab & item i of finalList | |
else if length of item i of finalList = 5 then | |
set item i of finalList to theTab & theTab & item i of finalList | |
else if length of item i of finalList = 7 then | |
set item i of finalList to theTab & theTab & theTab & item i of finalList | |
else if length of item i of finalList = 9 then | |
set item i of finalList to theTab & theTab & theTab & theTab & item i of finalList | |
else if length of item i of finalList = 11 then | |
set item i of finalList to theTab & theTab & theTab & theTab & theTab & item i of finalList | |
end if | |
end repeat | |
if not (count of finalList) = (count of theOutlineText_list) then error | |
set combinedList to my interlaceLists(finalList, theOutlineText_list) | |
set combinedList_grouped to my groupList(combinedList, 2) | |
set combinedList_final to {} | |
repeat with i from 1 to count of combinedList_grouped | |
set theGroup to item i of combinedList_grouped | |
set newItem to my implode(" ", theGroup) | |
copy newItem to end of combinedList_final | |
end repeat | |
combinedList_final | |
--create text from list | |
set tid to AppleScript's text item delimiters | |
set AppleScript's text item delimiters to LF | |
set finalText to combinedList_final as string | |
set AppleScript's text item delimiters to tid | |
set the clipboard to finalText | |
(* HANDLERS *) | |
on find_replace_repeated(the_string, search_strings, replace_strings) | |
set ListNumber to the (count of search_strings) as number | |
set OldDelims to AppleScript's text item delimiters | |
considering case | |
repeat with i from 1 to ListNumber | |
set AppleScript's text item delimiters to item i of search_strings | |
set newText to text items of the_string | |
set AppleScript's text item delimiters to item i of replace_strings | |
set the_string to newText as text | |
set AppleScript's text item delimiters to OldDelims | |
end repeat | |
end considering | |
return the_string | |
end find_replace_repeated | |
on rightString(str, del) | |
-- ljr (http://applescript.bratis-lover.net/library/string/) | |
local str, del, oldTIDs | |
set oldTIDs to AppleScript's text item delimiters | |
try | |
set str to str as string | |
if str does not contain del then return str | |
set AppleScript's text item delimiters to del | |
set str to str's text items 2 thru -1 as string | |
set AppleScript's text item delimiters to oldTIDs | |
return str | |
on error eMsg number eNum | |
set AppleScript's text item delimiters to oldTIDs | |
error "Can't rightString: " & eMsg number eNum | |
end try | |
end rightString | |
on leftString(str, del) | |
-- ljr (http://applescript.bratis-lover.net/library/string/) | |
local str, del, oldTIDs | |
set oldTIDs to AppleScript's text item delimiters | |
try | |
set str to str as string | |
if str does not contain del then return str | |
set AppleScript's text item delimiters to del | |
set str to str's first text item | |
set AppleScript's text item delimiters to oldTIDs | |
return str | |
on error eMsg number eNum | |
set AppleScript's text item delimiters to oldTIDs | |
error "Can't leftString: " & eMsg number eNum | |
end try | |
end leftString | |
on replaceString(theText, oldString, newString) | |
-- ljr (http://applescript.bratis-lover.net/library/string/) | |
local ASTID, theText, oldString, newString, lst | |
set ASTID to AppleScript's text item delimiters | |
try | |
considering case | |
set AppleScript's text item delimiters to oldString | |
set lst to every text item of theText | |
set AppleScript's text item delimiters to newString | |
set theText to lst as string | |
end considering | |
set AppleScript's text item delimiters to ASTID | |
return theText | |
on error eMsg number eNum | |
set AppleScript's text item delimiters to ASTID | |
error "Can't replaceString: " & eMsg number eNum | |
end try | |
end replaceString | |
on insertItem(lst, val, idx) | |
-- HAS (http://applemods.sourceforge.net/mods/Data/List.php) | |
local lst, val, idx, ndx, l | |
try | |
if lst's class is not list then error "not a list." number -1704 | |
set ndx to idx as integer | |
script k | |
property l : lst | |
end script | |
set len to count k's l | |
if ndx < 0 then | |
set ndx to len + ndx + 1 | |
if ndx < 0 then error "index " & idx & " is out of range." | |
end if | |
if ndx is 0 then | |
return {val} & lst | |
else if ndx is len then | |
return lst & {val} | |
else if ndx < len then | |
return (lst's items 1 thru ndx) & {val} & ¬ | |
(lst's items (ndx + 1) thru -1) | |
else | |
error "index " & idx & " is out of range." | |
end if | |
on error eMsg number eNum | |
error "Can't insertItem: " & eMsg number eNum | |
end try | |
end insertItem | |
on removeDuplicates(lst) | |
-- HAS (http://applemods.sourceforge.net/mods/Data/List.php) | |
local lst, itemRef, res, itm | |
try | |
if lst's class is not list then error "not a list." number -1704 | |
script k | |
property l : lst | |
property res : {} | |
end script | |
repeat with itemRef in k's l | |
set itm to itemRef's contents | |
-- note: minor speed optimisation when removing duplicates | |
-- from ordered lists: assemble new list in reverse so | |
-- 'contains' operator checks most recent item first | |
if k's res does not contain {itm} then ¬ | |
set k's res's beginning to itm | |
end repeat | |
return k's res's reverse | |
on error eMsg number eNum | |
error "Can't removeDuplicates: " & eMsg number eNum | |
end try | |
end removeDuplicates | |
on interlaceLists(list1, list2) | |
-- HAS (http://applemods.sourceforge.net/mods/Data/List.php) | |
local list1, list2 | |
try | |
if list1's class is not list then error "not a list." number -1704 | |
if list2's class is not list then error "not a list." number -1704 | |
script k | |
property l1 : list1 | |
property l2 : list2 | |
property res : {} | |
end script | |
if (count of k's l1) is not (count of k's l2) then error "lists are different lengths." | |
repeat with i from 1 to count k's l1 | |
set k's res's end to k's l1's item i | |
set k's res's end to k's l2's item i | |
end repeat | |
return k's res | |
on error eMsg number eNum | |
error "Can't interlaceLists: " & eMsg number eNum | |
end try | |
end interlaceLists | |
on groupList(lst, groupLen) | |
-- HAS (http://applemods.sourceforge.net/mods/Data/List.php) | |
local lst, tailLen, groupLen, idx | |
try | |
if lst's class is not list then error "not a list." number -1704 | |
script k | |
property l : lst | |
property res : {} | |
end script | |
set tailLen to (count of k's l) mod groupLen | |
repeat with idx from 1 to ((count of k's l) - tailLen) by groupLen | |
set k's res's end to k's l's items idx thru (idx + groupLen - 1) | |
end repeat | |
if tailLen is not 0 then | |
set k's res's end to k's l's items -tailLen thru -1 | |
end if | |
return k's res | |
on error eMsg number eNum | |
error "Can't groupList: " & eMsg number eNum | |
end try | |
end groupList | |
on implode(delimiter, pieces) | |
-- ljr (http://applescript.bratis-lover.net/library/string/), modified from Applescript.net (http://bbs.applescript.net/viewtopic.php?pid=65358) | |
local delimiter, pieces, ASTID | |
set ASTID to AppleScript's text item delimiters | |
try | |
set AppleScript's text item delimiters to delimiter | |
set pieces to "" & pieces | |
set AppleScript's text item delimiters to ASTID | |
return pieces --> text | |
on error eMsg number eNum | |
set AppleScript's text item delimiters to ASTID | |
error "Can't implode: " & eMsg number eNum | |
end try | |
end implode |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment