Experimental: enhanced(?) merge documents script

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 of fontChoice. 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
2 Likes

This looks like a very useful script. Thank you for sharing! When I try to compile the script, I encounter a “syntax error” on the following line:

The error tells me “Expected end of line, etc. but found plural class name.” And when it pops up, the word “records” is highlighted in the code quoted above.

I will do my best to figure this out, and don’t want to put you on the spot to troubleshoot. But I wondered if you might have already addressed this issue with an updated version of the script? Thanks in any case!