Skip to content

Instantly share code, notes, and snippets.

@fractaledmind
Last active August 31, 2018 06:02
Show Gist options
  • Save fractaledmind/6470371 to your computer and use it in GitHub Desktop.
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.)
(* 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