Script (Updated): Markdown formatting + image capture + link copying utility (probably less useless)

EDITED 2020.03.11: lastest update posted here.

I know that the experienced MD user will suggest using the special keys cognitively. As a beginner in MD and as a user who is used to format my note after the typing, I still want to have a quick utility script. Not trying to suggest this is a better way for anyone, I simply enjoy programming and to try different methods. I also hope that some of the codings can be useful for other users.

I assign this script to a shortcut (in fact, I then assign it to a magic mouse gesture by linking BTT with that shortcut - complicated!).

(1) If the user is in a markdown file and has some text selected, the script will show this:

I select the text to be formatted and activate the script. I can format the text by just type in the index letter and hit enter without looking at the list box. I am aware that this is not the “markdown” way - but this method is more consistent with the way I use RTF.

(2) If the user is not at a markdown file, or no text is selected in the markdown file, the script will show this:

Screenshot 2020-03-02 at 21.11.56

(2.1) The “T.BuildTable” will ask for row and col. An empty pattern of a table will be in the clipboard ready to be pasted. I believe that it will be faster just to type out the table for experienced markdown user. Just try to leave a function here in case of my need.

(2.2) For "G.GrabImage&Link. The user can just select and capture an area and hit enter. The captured image will be saved with a unique name in a group that is defined in the script (same name for each database). A markdown image link will be in the clipboard, to be pasted into the md file. This link is the least flexible type “![](dt item link)” (according to @bluefrog)- but it serves the basic purpose.

Nothing fancy. Just trying to see if I can/should make the switch into markdown.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

-- By Ngan 2020.03.02

property theStyle : {"I.Italic", "B.Bold", "E.Bold&Italic", "Q.Quote", "C.Chapter", "S.Section", "X.Clear Text Format", "Y.Clear Heading Format"}
property theFunction : {"T.BuildTable", "G.Grab&Link"}
property imgAssetsLoc : "/Image Asset"

global theDoc

tell application id "DNtp"
	
	set theDoc to content record of think window 1
	set theDocLoc to location of theDoc
	set theImgAsset to get record at imgAssetsLoc
	
	
	if (type of theDoc is markdown) and (exists (selected text of think window 1)) then
		set theList to theStyle & theFunction
	else
		set theList to theFunction
	end if
	
	set theChoice to (choose from list theList with empty selection allowed) as string
	set theChoice to text 1 of theChoice
	
	
	if theChoice is "I" then
		set (selected text of think window 1) to "*" & (selected text of think window 1) & "*"
	else if theChoice is "B" then
		set (selected text of think window 1) to "**" & (selected text of think window 1) & "**"
	else if theChoice is "E" then
		set (selected text of think window 1) to "***" & (selected text of think window 1) & "***"
	else if theChoice is "Q" then
		set (selected text of think window 1) to ">" & (selected text of think window 1)
	else if theChoice is "C" then
		set (selected text of think window 1) to "### " & (selected text of think window 1)
	else if theChoice is "S" then
		set (selected text of think window 1) to "#### " & (selected text of think window 1)
	else if theChoice is "X" then
		set (selected text of think window 1) to my trimText(selected text of think window 1, "*")
	else if theChoice is "Y" then
		set (selected text of think window 1) to my trimText(selected text of think window 1, "#")
		
	else if theChoice is "T" then
		activate
		my buildTable()
		return
	else if theChoice is "G" then
		my grapImgandGetMDLink()
		return
	end if
	
	
end tell

on buildTable()
	local numRow, numCol, theHD1, theHD2
	tell application id "DNtp"
		
		set a to text returned of (display dialog "Row, Col" default answer "3,3")
		
		set numRow to (item 1 of my strToList(a, ",")) as integer
		set numCol to (item 2 of my strToList(a, ",")) as integer
		
		set {theHD1, theHD2, theCol, theRow} to {" ", " ", " ", " "}
		
		repeat numCol times
			set theHD1 to theHD1 & "   |"
			set theHD2 to theHD2 & "---|"
		end repeat
		
		repeat numCol times
			set theRow to theRow & "   |"
		end repeat
		
		set theCol to ""
		repeat numRow times
			set theCol to theCol & return & theRow
		end repeat
		
		set the clipboard to theHD1 & return & theHD2 & theCol & return & return
		display alert "paste the layout to the  file" giving up after 1
	end tell
end buildTable

on grapImgandGetMDLink()
	
	
	set dateSting to (short date string of (current date)) & "." & (time string of (current date))
	set dateSting to my findAndReplaceInText(dateSting, ":", ".")
	set dateSting to my findAndReplaceInText(dateSting, "/", ".")
	
	do shell script "screencapture -ci"
	
	tell application id "DNtp"
		set theImageFile to paste clipboard to (get record at imgAssetsLoc)
		set the name of theImageFile to dateSting
		set theLink to reference URL of theImageFile
		set the clipboard to "![](" & theLink & ")"
		
	end tell
end grapImgandGetMDLink

on strToList(thestr, d)
	local theList
	set {tid, text item delimiters} to {text item delimiters, d}
	set theList to every text item of thestr
	set text item delimiters to tid
	return theList
end strToList

on trimText(theText, theTrim)
	set AppleScript's text item delimiters to the theTrim
	set the item_list to every text item of theText
	set AppleScript's text item delimiters to the ""
	set theText to the item_list as string
	set AppleScript's text item delimiters to ""
	return theText
end trimText

on findAndReplaceInText(theText, theSearchString, theReplacementString)
	set AppleScript's text item delimiters to theSearchString
	set theTextItems to every text item of theText
	set AppleScript's text item delimiters to theReplacementString
	set theText to theTextItems as string
	set AppleScript's text item delimiters to ""
	return theText
end findAndReplaceInText

Wow, a shortcut for a shortcut. Isn’t it just simpler to learn the markdown syntax? There’s like 3 or 4 markdown commands that matter for 90% of most uses. If that’s difficult then use double-click in DEVONthink 3 to open the .md file in Texts or some other free and simple markdown editor that accepts standard commands such as command-B for bolding text.

1 Like

I do the formatting after the typing and/or review. For example, after the review of my note, I want to bold a sentence, I need to type ** at the beginning of the sentence and ** at the end of the sentences. To me, that’'s clumsy. BTW, at least for my UK Logitech keyboard, finding # is not easy!

For this script, I can just select the sentence and bold the whole sentence. Isn’t it? I am not suggesting anyone to use it haha. And… it just me - I want to use as few complementary app as possible. For me (only), DT, BTT, and TE, and Scrivener are giving me all I need as core activities…

In fact, there is one more reason (at least for me), I have already assigned Individual short cuts (bold, italic, chapter heading, etc) for my rtf file. So I don’t want to memorise another different set of keys just for md…

FWIW, the normal approach to markdown is format-as-you-go. That’s what makes it simpler than Word, Pages, etc.

Yeah…

But I like “un-distracted” writing. So, finish typing down my thoughts before deciding how to format (or not formatting at all) is my priority.

The beauty of Markdown is that you don’t need to leave the keyboard for formatting commands (unlike mouse movements and popups and mouse clicks.).

Understand very well. But it depends on the workflow.

If I am preparing a note, I think it is likely that I will get used to typing * and # on the run.

But I am also doing a lot of quotation in my note. I used to read through the piece, then highlight the important terms/sentence. Then I add my view and my note and highlight my most important arguments (I don’t want to be distracted by formatting). The typing of the symbol is becoming less convenient. And I don’t want to use another app to facilitate this process. My experiment in the last few days also tells me that unformatting is clumsy.

MD is attractive to me for two reasons: (1) A unified css means that I can change all the look and feel of the notes in one go. (2) Portability. But I want to stay with same writing and formatting process to what I am doing in RTF/Word. So, I may not be a typical MD user?

If you use Typora or a similar Wysiwyg Markdown editor you have both ways, formatting commands when typing, or via a menu shortcut.

Yes… but I really don’t want to use another editor(!). I think the editor in DT3 is good enough - as long as my script works…

Sure. If I used a Markdown editor, I prefer a WYSIWYG one. In Devonthink you could use the built-in or just double-click and use an external one.

Thanks for mentioning Typora. I checked on it before (mentioned by this forum for quite a few times) and it’s really nice.
For my usage, I prefer working in DT window, so that I can work on those cmd fields and tags all together…

And… I quite like scripting - it’s a very relaxing sport (for me!).

Add two more functions: (1) garb screen capture and paste a markdown link (2) build an empty n x n table. For the fun of programming only. Updated in post#1.

I almost certainly won’t use these scripts (because I’m used to Markdown, and I use an external editor (Emacs) where this sort if thing is built in anyway), but I want to say that I (genuinely) admire how much effort you put in to developing and sharing these and your other scripts for the benefit of others. It’s really appreciated.

Thank you!

1 Like

Thanks. I guess I just want to see how flexible can DT3 be…!

1 Like

You are right (at least for me). Instead of just reading Typora’s site and YouTube for demo. I sit down and use the editor. The app is minimal looking with WYSIWYG interface, add non-std syntax such as highlight - it’s a hybrid of md and custom word processor while retaining the two key features I need (css style and portability of format). I think this app is suitable for me as a dual-users of rtf and md. I hope they’ll stay free for a while.

I’m a pretty heavy Markdown user, and I regularly move back and forth between coding as I go in a plain text editor, and using Typora. I don’t envision using this script. But I just want to weigh in that there’s no reason to apologize for sharing a script! It’s generous to share it, I admire your work on it, and I’ll keep this in mind should a need come up for it. Well done.

Updated Version (V1b6) with three additional functions: copy item link, copy cited text link, copy bookmark link.
The source document can be pdf, rtf, plain text, or markdown file, the links are in markdown format, saved in clipboard for pasting to markdown file.
For my usage, I attached shift-ctrl-M to the script as a shortcut.

(1) If text is selected in a markdown file, this is the menu:
Formatting functions are available.

(2) If no text is selected in any types of current document, or text is selected in a non-markdown document, this is the menu:
The script assumes that the user is planning to use function 1-5 for the two scenarios mentioned above.
Screenshot 2020-03-11 at 16.12.33

Scenario: Some text is selected in a pdf, function 3-5 are used respectively.

Configuration 1: The three types of link display filename as link’s name.

Configuration 2: The three types of link display simple link’s name.
DT Item link will always show the full filename regardless of the configuration.

Configuration 3: two other settings
Example 7: the link’s name is placed before the cited text.
Example 8: the search string in the DT’s link is based on a string instead of based on position.

There are quite a few changes, so I post the new script here:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions

--By Ngan 2020.03.02
--v1b6 2020.03.11
--add 3 functions. Item-link, cite link, bookmark link

-- settings for "3. Cite Link", "4. Bookmark Link", "5. Item Link"
property linkName : "DF" -- DS:[position only] DF:[document name], "DA" [aliases name]
property linkBeforeCitedText : true -- true: put link as the first line before cited text. false: link after the cited text
property searchMethod : "S" -- "S" search by string  "P" search by position (paragraph for rtf, page for pdf). For markdown always search by string
property queryWordLen : 10 -- number of words used in search string


--Note for "property useFilepathForImageLink"
-- if "useFilepathForImageLink: true", image link is based on file path. Image in md can only be viewed in one computer and external md editor.
--if "useFilepathForImageLink:false", image link is based on DT Link. Image in md can be viewed in DT3 and DTTG, BUT NOT in external md editor
property useFilepathForImageLink : false

-- Note for "property useOneImageAssetsGpForAllDBs"
--if useOneImageAssetsGpForAllDBs: true,  use one image assets group for ALL databases
--if useOneImageAssetsGpForAllDBs: false,  use one image assets group for EACH database
property useOneImageAssetsGpForAllDBs : true

--Note: only need to define "property imgAssetsUUID" if useOneImageAssetsGpForAllDBs : true
--if useFilepathForImageLink : true, this group must be an index group
property imgAssetsUUID : "9A72DEC0-A97E-XXXX-XXXXXXXXXXXX" -- uuid of  the index folder for the centralised image assets

--Note: only need to define "property imgAssetsLocation" if useOneImageAssetsGpForAllDBs : false
--if useFilepathForImageLink : true, this group must be an index group
property imgAssetsLocation : "/your group/subgroup" -- example only


-- ignore these settings, for my personal used only
property characterToTrim : "- "
property regexForCardUID : "[c/n][0-9][0-9][0-9][0-9]"
property theCmd : missing value -- just for flexibility, probaby won't be used
--

-- How the list is displayed
property theStyle : {"I. Italic", "B. Bold", "S. Bold&Italic", "U. Underline", "C. Chapter", "S. Section", "X. Clear All Text Format"}
property theOtherFunction : {"1. Build Table", "2. Capture Image Link", "3. Cite Link", "4. Bookmark Link", "5. Item Link"}


global theWin, theDoc, theImgAsset
global theDocType, withText
global theCitedText

tell application id "DNtp"
	
	set theWin to think window 1
	set theDoc to content record of think window 1
	set theCitedText to selected text of theWin as string
	
	
	set theDocLoc to location of theDoc
	if useOneImageAssetsGpForAllDBs then
		if imgAssetsUUID is not missing value then set theImgAsset to get record with uuid imgAssetsUUID
	else
		if imgAssetsLocation is not missing value then set theImgAsset to get record at imgAssetsLocation
	end if
	
	if (type of theDoc is markdown) and (exists (selected text of think window 1)) then
		set theList to theStyle & " " & theOtherFunction
	else
		set theList to theOtherFunction
	end if
	
	set theChoice to (choose from list theList with prompt "Items 1-5 are created in clipboard" with empty selection allowed) as string
	set theChoice to text 1 of theChoice
	
	
	if theChoice is "I" then
		set (selected text of think window 1) to "*" & (selected text of think window 1) & "*"
	else if theChoice is "B" then
		set (selected text of think window 1) to "**" & (selected text of think window 1) & "**"
	else if theChoice is "S" then
		set (selected text of think window 1) to "***" & (selected text of think window 1) & "***"
	else if theChoice is "U" then
		set (selected text of think window 1) to "<u>" & (selected text of think window 1) & "</u>"
	else if theChoice is "C" then
		set (selected text of think window 1) to "### " & (selected text of think window 1)
	else if theChoice is "S" then
		set (selected text of think window 1) to "#### " & (selected text of think window 1)
	else if theChoice is "X" then
		set (selected text of think window 1) to my TrimText(my TrimText(my TrimText(my TrimText(my TrimText(selected text of think window 1, "*"), "<u>"), "</u>"), "#"), "==")
		
	else if theChoice is "1" then
		activate
		my buildTable()
		return
	else if theChoice is "2" then
		my grapImgandGetMDLink()
		return
	else if theChoice is "3" then
		my getLink(theWin, theDoc, theCitedText, queryWordLen, "C")
	else if theChoice is "4" then
		my getLink(theWin, theDoc, theCitedText, queryWordLen, "B")
	else if theChoice is "5" then
		my getLink(theWin, theDoc, theCitedText, queryWordLen, "D")
	end if
	
	
end tell

on buildTable()
	local numRow, numCol, theHD1, theHD2
	tell application id "DNtp"
		
		set a to text returned of (display dialog "Row, Col" default answer "3,3")
		
		set numRow to (item 1 of my strToList(a, ",")) as integer
		set numCol to (item 2 of my strToList(a, ",")) as integer
		
		set {theHD1, theHD2, theCol, theRow} to {" ", " ", " ", " "}
		
		repeat numCol times
			set theHD1 to theHD1 & "   |"
			set theHD2 to theHD2 & "---|"
		end repeat
		
		repeat numCol times
			set theRow to theRow & "   |"
		end repeat
		
		set theCol to ""
		repeat numRow times
			set theCol to theCol & return & theRow
		end repeat
		
		set the clipboard to theHD1 & return & theHD2 & theCol & return & return
		display alert "paste the layout to the  file" giving up after 1
	end tell
end buildTable

on grapImgandGetMDLink()
	
	
	set dateSting to my getDateString()
	
	do shell script "screencapture -ci"
	
	tell application id "DNtp"
		set theImageFile to paste clipboard to theImgAsset
		set the name of theImageFile to dateSting
		
		if useFilepathForImageLink then
			set theLink to path of theImageFile
			set the clipboard to "<img src=\"" & theLink & "\" style=\"zoom:50%;\" >"
		else
			set theLink to reference URL of theImageFile
			set the clipboard to "![](" & theLink & ")"
		end if
		
		
		
	end tell
end grapImgandGetMDLink

on getLink(theWin, theDoc, theCitedText, queryWordLen, linkType)
	local rPos, cPos -- realPositionOfText, citedPositionOfText
	local dl, pl, sl, cl -- docBackLink, positionBackLink, searchStringBackLink,customBackLink
	local dldn, pldn, sldn, cldn -- name of dl,pl,sl,cl
	local ctl, tq -- citedTextAsList, textQuery 
	local theID, theYear, theAuthor, theType
	
	local dn, an, cn
	local theBLDisplay, theBL
	
	
	tell application id "DNtp"
		
		set {dn, dl, an, cn} to {name of theDoc, reference URL of theDoc, aliases of theDoc, get custom meta data for theCmd from theDoc default value theCmd}
		
		
		-- extract the search string of the selected text or page
		if theCitedText is not "" then
			set ctl to my strToList(theCitedText, " ")
			set tq to items 1 thru (my min(queryWordLen, length of ctl)) of ctl
			set tq to my listToStr(tq, "%20")
			set sl to dl & "?search=" & tq
			set sldn to "Goto"
		else
			set sl to ""
			set sldn to ""
		end if
		
		-- extract the position of the selected text or page
		if the kind of theDoc is in "PDF+Text" then
			set {rPos, cPos} to {(current page of theWin), (current page of theWin) + 1}
			set pl to dl & "?page=" & rPos
			set pldn to " Page " & (rPos + 1)
			
		else if kind of theDoc is "Markdown" then
			if theCitedText is not "" then
				set pl to dl & "?search=" & tq
				set pldn to ""
			else
				set pl to dl
				set pldn to ""
			end if
			
			
		else
			if kind of theDoc is not "Markdown Document" then
				set {rPos, cPos} to {(current line of theWin), my getNonBlankParagraphNum(theWin, current line of theWin)}
			else
				set {rPos, cPos} to {0, 0}
			end if
			set pl to dl & "?line=" & rPos
			set pldn to " Paragraph " & cPos
			
		end if
		
		if searchMethod is "S" then
			set theBL to sl
		else if searchMethod is "P" then
			set theBL to pl
		end if
		
		if linkName is "DF" then
			-- display full filename as name of link
			set theBLDisplay to dn & pldn
			
			
		else if linkName is "DA" then
			-- display aliases name as name of link
			set theBLDisplay to an & pldn
			
			
		else if linkName is "DC" then
			-- display content of a cmd as name of link
			set theBLDisplay to cn & pldn
			
			
		else if linkName is "DS" then
			-- display "Link" as  name of link
			set theBLDisplay to "" & pldn
			
			
			
		else if linkName is "DM" then
			set dldn to dn
			set {theID, theYear, theAuthor, theType} to my getCitationInfo(dldn)
			
			set theType to my firstN(1, theType)
			if theCitedText is not "" then
				set cl to sl -- use pl fot page/paragraph link, sl for search link
			else
				set cl to pl
			end if
			
			if theType is "O" then -- other source
				set cldn to dldn & ": " & pldn
			else if theType is "R" then -- source is literature 
				set cldn to " (" & theAuthor & ", " & theYear & ": " & (cPos) & " &nbsp;" & theID & ") "
			else if (theType is "A") or (theType is "C") then -- source is annotationNote or card
				set cldn to " (" & theAuthor & ", " & theYear & ": para " & (cPos) & " &nbsp;" & theID & "-" & theType & ")"
			end if
			
			set theBLDisplay to cldn
			set theBL to cl
			
			
		end if
		
		if linkType = "C" then
			if linkBeforeCitedText then
				set theFullLink to "> [" & theBLDisplay & "](" & theBL & ")" & return & return & ">" & theCitedText
				
			else
				set theFullLink to ">" & theCitedText & " [" & theBLDisplay & "](" & theBL & ")"
			end if
			
		else if linkType = "B" then
			set theFullLink to "*Bookmark:* [" & theBLDisplay & "](" & theBL & ")"
			
		else if linkType = "D" then
			set theFullLink to "[" & dn & "](" & dl & ")"
		end if
		
		set the clipboard to theFullLink
		
	end tell
	
end getLink

on strToList(thestr, d)
	local theList
	set {tid, text item delimiters} to {text item delimiters, d}
	set theList to every text item of thestr
	set text item delimiters to tid
	return theList
end strToList

on listToStr(theList, theDelimiter)
	set {tid, text item delimiters} to {text item delimiters, theDelimiter}
	set thestr to theList as text
	set text item delimiters to tid
	return thestr
end listToStr

on TrimText(theText, theTrim)
	set AppleScript's text item delimiters to the theTrim
	set the item_list to every text item of theText
	set AppleScript's text item delimiters to the ""
	set theText to the item_list as string
	set AppleScript's text item delimiters to ""
	return theText
end TrimText

on getDateString()
	set y to get year of (current date) as string
	set m to month of (current date) as integer
	set m to my PadNum(m, 2) as string
	set d to get day of (current date)
	set d to my PadNum(d, 2) as string
	set t to get time string of (current date) as string
	set t to my findAndReplaceInText(t, ":", ".") as string
	
	return y & "." & m & "." & d & "." & t
	
	
end getDateString

on findAndReplaceInText(theText, theSearchString, theReplacementString)
	set AppleScript's text item delimiters to theSearchString
	set theTextItems to every text item of theText
	set AppleScript's text item delimiters to theReplacementString
	set theText to theTextItems as string
	set AppleScript's text item delimiters to ""
	return theText
end findAndReplaceInText

on getNonBlankParagraphNum(theWin, theCurrentLine)
	local ap, nep -- all-paragraphs, non-empty-paragraphs
	tell application id "DNtp"
		set ap to every paragraph of the text of theWin
		set nep to {}
		repeat with i from 1 to (theCurrentLine + 1)
			if (item i of ap) is not "
" then
				set end of nep to item i of ap
			end if
		end repeat
		return count nep
	end tell
	
end getNonBlankParagraphNum

on PadNum(lngNum, lngDigits)
	
	set strNum to lngNum as string
	set lngGap to (lngDigits - (length of strNum))
	repeat while lngGap > 0
		set strNum to "0" & strNum
		set lngGap to lngGap - 1
	end repeat
	strNum
end PadNum

on min(x, y)
	if x ≤ y then
		return x
	else
		return y
	end if
end min


-- ignore these handlers
on getCitationInfo(theDocNm)
	local theNmlist, firstWord, thePos, lastWord, theType, theID, theYear, theAuthor
	
	set theNmlist to my strToList(theDocNm, " ")
	
	set thePos to my getItemPosInList("-", theNmlist)
	set firstWord to item 1 of theNmlist
	set lastWord to item -1 of theNmlist
	
	set theType to my getDocType(theDocNm)
	
	if theType is "O" then
		return {"", "", "", theType} -- no citation info
	else
		set theID to item 1 of theNmlist
		set theYear to item 2 of theNmlist
		if thePos is 0 then
			set theAuthor to item 3 of theNmlist
		else
			set theAuthor to items 3 thru thePos of theNmlist
			if the length of theAuthor ≤ 4 then
				set theAuthor to my listToStr(items 3 thru (thePos - 1) of theNmlist, " ")
			else
				set theAuthor to my listToStr((my TrimText((item 3 of theNmlist), ",") & " et al."), " ")
			end if
			
		end if
		return {theID, theYear, theAuthor, theType}
	end if
	
end getCitationInfo
on getDocType(theDocNm)
	local lnm
	set lnm to my strToList(theDocNm, " ")
	if my regexMatch(lnm's item -1, regexForCardUID) then
		return "C" --card
	else if lnm's item -1 contains "(annotation)" then
		return "A" -- annotation
	else if lnm's item 1 contains "." then
		return "R" --ref literature 
	else
		return "O" -- other ref
	end if
end getDocType
on getItemPosInList(theItem, theList)
	repeat with a from 1 to count of theList
		if item a of theList is theItem then return a
	end repeat
	return 0
end getItemPosInList
on regexMatch(s, regex)
	-- ignore case
	local ignoreCase, extraCommand
	set ignoreCase to true
	if ignoreCase then
		set extraCommand to "shopt -s nocasematch; "
	else
		set extraCommand to ""
	end if
	
	do shell script "export LANG='" & user locale of (system info) & ".UTF-8'; shopt -s compat31; " & extraCommand & "[[ " & quoted form of s & " =~ " & quoted form of regex & " ]] && printf '%s\\n' \"${BASH_REMATCH[@]}\" || printf ''"
	
	if result is not "" then
		return true
	else
		return false
	end if
	
end regexMatch
on firstN(n, s)
	return text from character 1 to character n of s
end firstN


1 Like

@ ngan

I love the script! Thx so much for sharing!

Z

Wow! Big work

@ngan, isn’t it easier to use Keyboard Maestro for all this stuff? It’s more simple and flexible with ready-made interface solutions. Like a tiny transparent shrinkable floating pane with macros, where you can configure all MD tags including tables and assign to any macro a hot key if needed, KM has great input dialogs and so on.

And IMHO you may be confusing the use cases. Manuscript and longread (or short texts) are different things. For one I use Mellel, for other - MD in DT or iA Writer. But if you want to concentrate and pull complex things out of your head, then you are right - any distraction is bad. I use Omni Outliner for this.

Thanks.
Many have reminded there are always 3rd part apps that can do a 100x better/easier job. (1) Don’t want to use increasingly number of apps surrounding DT, just not my preference. I am already happy with the apps that I have (which is already too many for me: BTT, popclip). (2) Script is very capable to build around DT, and it’s fun to do programming. Just a few hours scripting is actually relaxing. I guess that’s why people build models, chair, even their own house.

All of the experienced users are 100% correct from efficacy point of view, and I am not confusing with the use case. I simply do not attempt to be the smartest users of all tools, and rather knowing one app and one language very well and enjoy the fun of DIY.

Not trying to be philosophical, it’s a matter of perspective and expectation.

1 Like