Purpose: merge my notes (rtf, rtfd, md).
Why using a script instead of using the standard merge function.
(1) I take notes in snippets of info and I merge different snippets dynamically by using tags or string search. My older notes are in RTF/RTFD format and they have different fonts and font sizes. This chaos of formatting is the main reason for my newer notes to be in MD format. I need to find a way to reformat all snippets in the merged file for a more homogeneous look (easier to read). DT3’s standard merge function can’t do that.
(2) I want to know which files/notes are merged. DT3’s standard merge function can’t do that.
(3) I want to give a meaningful name to the merged file at the time of creation, and place the note in a sperate group. The DT3’s merge function creates the merged file in the same group with the selected items - but if the items are the results of a search, I get confused in finding the merged file sometimes.
(4) Perhaps the most important reason is that I am testing to use “Dialog Toolkit Plus.scptd” to create customised dialogue box. The script addition is developed by Shane Stanley. Shane and Mark are the developers of Script Debugger. You can now download Dialog Toolkit Plus here in Late Night Software website.
How to use the script:
- Download “Dialog Toolkit Plus.scptd” and save it under “/Library/Script Libraries”
- Save the script under DT’s script menu.
Demo:
- I select the items and invoke the script. The options are self-explanatory. Bear in mind that the format of the merged file is decided by DT’s internal function. For example, if all files to be merged are in md(rtf) format, the merged file will be in md(rtf) format. If the files are a mixture of md and rtf/rtfd, the merged file will be in rtf/rtfd format.
- All unique tags of the merged notes are appended at the top of the merged file. I use [[…]] as a link to those tags for my merge view/file. This method may not be wanted by everyone. If the option “Add [[Tags]] at Beginning” is disabled, the same tags will be assigned to the merged document (the standard results from using DT’s merge function)
- All filenames of the merged notes are appended at the end of the merged file. Almost like a reference for my convenience.
The configuration:
- You need to create a new group for holding the merged file and specify the location in
property mergedViewGpLocation
- If you prefer to choose different font face, add the fontface to
property fontChoice
, else just put your commonly used font in the first item offontChoice
. The “Reformat…” options are only used when the merged file is in RTF/RTFD.
property mergedViewGpLocation : "/MergeView"
property fontChoice : {"SFProText-Light", "Arial", "Calibri", "Helvetica", "HelveticaNeue", "LucidaGrande", "TimesNewRomanPSMT", "Verdana"}
The script:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use script "Dialog Toolkit Plus" version "1.1.0"
--by ngan 2020.04.21
--v1b2
property mergedViewGpLocation : "/MergeView" -- if u intend to use the script on multiple databases, the location and name of the groups must be the same in each database.
property fontChoice : {"SFProText-Light", "Arial", "Calibri", "Helvetica", "HelveticaNeue", "LucidaGrande", "TimesNewRomanPSMT", "Verdana"}
global theRecords, numRecords
global mergedViewGpsName
global paraSpace, lineSpace, fontSize, fontFace, reformatFile, addTag, addFileName, thefilename, mergedViewGp
global allRecordTags, eachRecordTags, allRecordNamesRTF, allRecordNamesMD, eachRecordName
tell application id "DNtp"
set theRecords to selection
set numRecords to count of theRecords
if numRecords < 2 then
display alert "Choose more than one record"
return
end if
set mergedViewGpsName to {}
repeat with eachGp in mergedViewGpLocation
set end of mergedViewGpsName to item 1 of eachGp
end repeat
-- "Dialog Toolkit Plus" coding
set accViewWidth to 500
set {theButtons, minWidth} to create buttons {"Cancel", "OK"} default button 2 given «class btns»:2
if minWidth > accViewWidth then set accViewWidth to minWidth -- make sure buttons fit
set {paraSpace, paragraphSpaceLabel, theTop, fieldLeft} to create side labeled field "12" bottom 0 total width 200 label text "Paragraph Spacing:" field left 0
set {lineSpace, lineSpaceLabel, theTop, fieldLeft} to create side labeled field "8" bottom (theTop + 8) total width 200 label text "Line Spacing: " field left 0
set {fontSize, fontSizeLabel, theTop, fieldLeft} to create side labeled field "12" bottom (theTop + 8) total width 200 label text "Font Size: " field left 0
set {fontFace, fontFaceLabel, theTop} to create labeled popup fontChoice bottom (theTop + 8) left inset 0 popup width 150 max width 250 label text "Font Face:" popup left 85 initial choice 1
set {reformatFile, theTop, newWidth} to create checkbox "Reformat the merged document" bottom (theTop + 10) max width accViewWidth with initial state
set {theRule, theTop} to create rule (theTop + 12) rule width accViewWidth
set {addTag, unusedTop, newWidth} to create checkbox "Add [[Tags]] at Beginning" bottom (theTop + 8) max width accViewWidth / 2 - 8 with initial state
set {addFileName, theTop, newWidth} to create checkbox "Add [[FileName]] at End" bottom (theTop + 8) max width accViewWidth / 2 - 8 left inset accViewWidth / 2 + 8 with initial state
set {theRule2, theTop} to create rule (theTop + 12) rule width accViewWidth
set {thefilename, filenameLabel, theTop, fieldLeft} to create side labeled field "" bottom (theTop + 8) total width accViewWidth label text "Filename: " field left 0
set {boldLabel, theTop} to create label "Total of " & numRecords & " records to be merged" bottom theTop + 20 max width accViewWidth control size large size with bold type
set allControls to {paraSpace, paragraphSpaceLabel, lineSpace, lineSpaceLabel, fontSize, fontSizeLabel, fontFace, fontFaceLabel, reformatFile, theRule, addTag, addFileName, theRule2, thefilename, filenameLabel, boldLabel}
set {buttonName, controlsResults} to display enhanced window "Merge Records" acc view width accViewWidth acc view height theTop acc view controls allControls buttons theButtons active field thefilename with align cancel button
-- end of "Dialog Toolkit Plus" coding
if buttonName is "Cancel" then
return
else
-- extract parameters from the dialog box
set paraSpace to controlsResults's item 1
set lineSpace to controlsResults's item 3
set fontSize to controlsResults's item 5
set fontFace to controlsResults's item 7
set reformatFile to controlsResults's item 9
set addTag to controlsResults's item 11
set addFileName to controlsResults's item 12
set thefilename to (controlsResults's item 14) & " (" & numRecords & ")"
-- set mergedViewGpName to controlsResults's item 16
set mergedViewGp to get record at mergedViewGpLocation
if thefilename is "" then
display alert "No filename is entered"
return
end if
-- get all tags from all records
if addTag then
set allRecordTags to {}
repeat with each in theRecords
set eachRecordTags to name of (parents of each whose tag type is ordinary tag)
repeat with i from 1 to length of eachRecordTags
set eachRecordTags's item i to "[[" & (eachRecordTags's item i) & "]] "
end repeat
set allRecordTags to allRecordTags & eachRecordTags
end repeat
end if
-- get name of all records
if addFileName then
set allRecordNamesRTF to ""
set allRecordNamesMD to ""
-- two formats are needed for the line return of md and rtf
repeat with each in theRecords
set eachRecordName to "[[" & name of each & "]]" & return
set allRecordNamesMD to allRecordNamesMD & return & eachRecordName
set allRecordNamesRTF to allRecordNamesRTF & eachRecordName
end repeat
end if
-- get unique tags and sort them
set allRecordTags to my listToStr(my sortlist(my getUniqueItemsLOL(allRecordTags)), " ")
-- merge the records and place the merged file into the mergeView Group
set theMergedFile to merge records theRecords in mergedViewGp
set name of theMergedFile to thefilename
-- if tags are add at the top of file, there is no need to tag the file
if addTag then set tags of theMergedFile to ""
if type of theMergedFile is markdown then
if {addTag, addFileName} is {true, true} then
set plain text of theMergedFile to ">" & allRecordTags & return & return & "___" & return & return & plain text of theMergedFile & return & return & "___" & return & allRecordNamesMD
else if {addTag, addFileName} is {true, false} then
set plain text of theMergedFile to ">" & allRecordTags & return & return & "___" & return & return & plain text of theMergedFile
else if {addTag, addFileName} is {false, true} then
set plain text of theMergedFile to plain text of theMergedFile & return & return & "___" & return & allRecordNamesMD
end if
else if type of theMergedFile is in {rtf, rtfd} then
if addTag then make new paragraph at beginning of text of theMergedFile with data allRecordTags & return & my setRuler("_", 80) & return & return
if addFileName then make new paragraph at end of text of theMergedFile with data return & return & my setRuler("_", 80) & return & allRecordNamesRTF
if reformatFile then
set size of text of theMergedFile to fontSize
set line spacing of text of theMergedFile to lineSpace
set paragraph spacing of text of theMergedFile to paraSpace
set font of text of theMergedFile to fontFace
end if
end if
open tab for record theMergedFile
end if
end tell
on listToStr(theList, d)
local thestr
set {tid, text item delimiters} to {text item delimiters, d}
set thestr to theList as text
set text item delimiters to tid
return thestr
end listToStr
on getUniqueItemsLOL(a)
-- credit to someone else on the internet but I can't find the name
script o
property p : a
end script
set b to {}
repeat with i from 1 to a's length
tell o's p's item i to if ({it} is not in b) then set b's end to it
end repeat
return b
end getUniqueItemsLOL
on sortlist(theList)
set theIndexList to {}
set theSortedList to {}
repeat (length of theList) times
set theLowItem to ""
repeat with a from 1 to (length of theList)
if a is not in theIndexList then
set theCurrentItem to item a of theList as text
if theLowItem is "" then
set theLowItem to theCurrentItem
set theLowItemIndex to a
else if theCurrentItem comes before theLowItem then
set theLowItem to theCurrentItem
set theLowItemIndex to a
end if
end if
end repeat
set end of theSortedList to theLowItem
set end of theIndexList to theLowItemIndex
end repeat
return theSortedList
end sortlist
on vLookup(lookupVal, lookUpPos, getValPos, theList)
--only for list of list with more than 1 items
local i, j, k
set j to lookUpPos
set k to getValPos
repeat with i from 1 to length of theList
if (item j of item i of theList) is equal to lookupVal then return item k of item i of theList
end repeat
return {}
end vLookup
on setRuler(symbol, n)
set theRuler to ""
repeat n times
set theRuler to theRuler & symbol
end repeat
return theRuler as string
end setRuler