Text file list enhancement

Looking for an example of how to enhance this bit of code:
I’d like to accomplish the following but not sure how.

  1. Is there a way to insert something to mylist so that when I enter another date the real estate that this long string of text spans across the page and it’s getting quite wide.

  2. Is there a way to turn mylist into a dialogue prompt? So when I run the script it asks for the next date and the user just enters it and it will write to the text file when executed.

-- Example usage:
set myList to {"3/30/24 " & return, "4/6/24 " & return, "4/13/24 " & return, "4/18/24 " & return, "4/29/24 " & return, "5/4/24 " & return, "5/8/24 " & return, "5/13/24 " & return, "5/18/24 " & return, "5/25/24 " & return, "5/31/24 " & return, "6/8/24 " & return, "6/27/24 " & return, "7/6/24 " & return, "7/13/24 "}
-- Replace with your list of items
set outputFile to (path to desktop as text) & "July 1.txt" -- Replace with your desired output file path

I can’t seem to get my head around what you are asking.
First, why do you have the returns in every item in your list?
The 1st thing you listed was a run-on sentence that I couldn’t understand what you wanted.
Give an example.

This script that I have is used to track how many times a particular item gets completed. Let’s say getting a haircut; I learn better by using practical examples.

I had several of these scripts that write to text files and I wanted to see if I could get it to work, which it does.

I can keep adding dates to the list but as I mentioned, the list of dates is getting long and I know there’s a better way, thus my post.

Here’s my example:

on countAndWriteToFile(itemList, outputPath)
	set itemCount to count of itemList
	
	-- Convert the item count to text
	set itemCountText to itemCount as text
	set Cost to itemCount * 17.0 as text
	
	-- Write the item count to the specified file
	try
		set fileDescriptor to open for access outputPath with write permission
		write "Data generated by Haircut Counter Handler on " & (current date) & linefeed & linefeed & "Total haircuts in 2024 = " & itemCountText & linefeed & "Total Cost for haircuts in 2014 is = " & Cost & return & return & "2024 Haircut Dates" & return & return & itemList to fileDescriptor
		close access fileDescriptor
		display dialog "Item count has been written to the file." buttons {"OK"} default button "OK"
	on error errMsg
		close access fileDescriptor
		display dialog "An error occurred: " & errMsg buttons {"OK"} default button "OK"
	end try
end countAndWriteToFile

-- Example usage:
set myList to {"Jan 30 " & return, "Mar 5 " & return, "Apr 9 " & return, "Apr 15 " & return, "May 7 " & return, "June 4 " & return, "Jul 2 "}
-- Replace with your list of items
set outputFile to (path to desktop as text) & "Haircuts.txt" -- Replace with your desired output file path


countAndWriteToFile(myList, outputFile)

Another issue I see is the mixing of line endings, i.e. returns & linefeeds.
Use one or the other, not both.

Also, what do you do with this file once it’s generated? Do you read it with a text editor, or do you parse it with another script?

Here is a cleaned up version of yours…

on countAndWriteToFile(itemList, outputPath)
	local itemCount, Cost, fileDescriptor, msg, tid
	set tid to text item delimiters
	set itemCount to count itemList
	set Cost to itemCount * 17.0
	set text item delimiters to linefeed
	-- Write the item count to the specified file
	try
		set fileDescriptor to open for access outputPath with write permission
		set eof fileDescriptor to 0
		write "Data generated by Haircut Counter Handler on " & (current date) & linefeed & linefeed & "Total haircuts in 2024 = " & (itemCount as text) & linefeed & "Total Cost for haircuts in 2014 is = $" & Cost & linefeed & linefeed & "2024 Haircut Dates" & linefeed & linefeed & (itemList as text) to fileDescriptor
		set msg to (itemCount as text) & " items have been written to the file."
	on error errMsg
		set msg to "An error occurred: " & errMsg
	end try
	try
		close access fileDescriptor
	end try
	display alert msg giving up after 5
	set text item delimiters to tid
end countAndWriteToFile

-- Example usage:
set myList to {"Jan 30", "Mar 5", "Apr 9", "Apr 15", "May 7", "June 4", "Jul 2"}
-- Replace with your list of items
set outputFile to (path to desktop as text) & "Haircuts.txt" -- Replace with your desired output file path


countAndWriteToFile(myList, outputFile)

How do you keep adding dates to the list? Via a script, or manually, or other way?

Manually. That’s what I’m trying to fix. I don’t know how, that’s why I’m asking

But where do you have the list of dates saved for when you want to add to it? Do you save it out to a file and then read it back in when you need it?

It just writes to a text file, so when I add to it, I add another date and run the script. The script does what I want but I’d like to make it more efficient and use a dialog or something. Here’s an example of text file:

Data generated by Haircut Counter Handler on Thursday, July 4, 2024 at 7:10:50?AM

Total haircuts in 2024 = 7
Total Cost for haircuts in 2014 is = 119.0

2024 Haircut Dates

Jan 30
Mar 5
Apr 9
Apr 15
May 7
June 4
Jul 2

Since you are writing the dates to a log file, you can just store them there instead of in the script. In your example they are the last items, so if you need them somewhere else they can be read from the file.

Got an example of how that would look? Thanks

Here is a quick example of the text file being re-read to get the list of dates…

property outputPath : (path to desktop as text) & "Haircuts.txt"

on run
	local myList, myAns, flag, mn, dy, msg
	-- Example usage:
	
	set myList to getItemList()
	if class of myList is boolean then return
	set flag to false
	set msg to "Enter a date for a haircut"
	repeat until flag
		set myAns to display dialog msg default answer "" with title "Haircut Dates"
		if button returned of myAns = "OK" then set myAns to text returned of myAns
		if (count of words of myAns) = 2 then
			set mn to word 1 of myAns
			if mn is in "JanFebMarAprMayJunJulAugSepOctNovDec" then
				set dy to word 2 of myAns
				try
					set dy to dy as integer
					if dy ≤ 31 then
						set flag to true
						exit repeat
					end if
				end try
			end if
		end if
		set msg to "Date was in incorrect format!" & return & return & "Enter a date for a haircut"
	end repeat
	if flag then set end of myList to (mn & " " & dy)
	countAndWriteToFile(myList)
	return myList
end run

on countAndWriteToFile(itemList)
	local itemCount, Cost, fileDescriptor, msg, tid
	set tid to text item delimiters
	set itemCount to count itemList
	set Cost to itemCount * 17.0
	set text item delimiters to linefeed
	-- Write the item count to the specified file
	try
		set fileDescriptor to open for access outputPath with write permission
		set eof fileDescriptor to 0
		write "Data generated by Haircut Counter Handler on " & (current date) & linefeed & linefeed & "Total haircuts in 2024 = " & (itemCount as text) & linefeed & "Total Cost for haircuts in 2014 is = $" & Cost & linefeed & linefeed & "2024 Haircut Dates" & linefeed & linefeed & (itemList as text) to fileDescriptor
		set msg to (itemCount as text) & " items have been written to the file."
	on error errMsg
		set msg to "An error occurred: " & errMsg
	end try
	try
		close access fileDescriptor
	end try
	display alert msg giving up after 5
	set text item delimiters to tid
end countAndWriteToFile

on getItemList()
	local myData
	try
		set myData to read file outputPath
	on error
		return false
	end try
	set myData to items 8 thru -1 of paragraphs of myData
end getItemList

** Edit ** I edited mine to ask for a date to add to the list, but red_menace beat me to it

Here is another version. The following script reads the dates (it can be other text) from the last part of the log file and asks for a new entry. The input is then added to the list, which is written back to the log file - the list of dates is not kept in the script. I’ve split it up a little and made it more general-purpose so that it can be modified for other items.

property header : "Data generated by Haircut Counter" -- date suffix is added when written to a file
property object : {"haircut", "haircuts"} -- {singular, plural}
property cost : "17.00"
property logFile : (path to desktop as text) & "Haircuts 2024.txt"
property delimiter : linefeed & tab -- delimiting text at the beginning and between date items

on run -- example
	set newDateList to addToList from logFile
	set output to assembleText for newDateList
	writeText from output into logFile
end run

to addToList from filePath -- get a list of dates from a file, adding a new entry at the end
	try
		tell (read file filePath) to set dateText to text ((my (offset of delimiter in it)) + (count delimiter)) thru -1
		set {prevTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, delimiter}
		tell text items of dateText
			set {dateList, previous} to {it, {"Last entries:" & return} & it & return}
			if (count it) > 5 then set previous to {"Last 5 entries:" & return} & items -5 thru -1 of it & return
		end tell
		set {previous, AppleScript's text item delimiters} to {previous as text, prevTID}
	on error errmess -- no file?
		log errmess
		set dateList to {}
		set previous to ""
	end try
	tell (current date) to set newDate to text 1 thru 3 of (its month as text) & space & its day
	set end of dateList to text returned of (display dialog previous & "Enter date to add:" default answer newDate with title "Add Entry to Log")
	return dateList
end addToList

to assembleText for itemList -- assemble text pieces for writing to a file
	tell (current date) to set {theDate, theYear} to {it as text, its year}
	tell theDate to set theDate to text 1 thru -4 & space & text -2 thru -1 -- fix Sonoma Narrow No-Break Space bug (English)
	set itemCount to (count itemList)
	set totalCost to "$" & (do shell script "echo \"" & itemCount * cost & "\" | awk '{printf(\"%.2f\", $1)}'") -- formatting
	set {prevTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, delimiter}
	set {itemListText, AppleScript's text item delimiters} to {itemList as text, prevTID}
	set theText to header & " - last updated " & theDate & linefeed & linefeed & "The total number of " & item 2 of object & " in " & theYear & " is " & itemCount & return & "The total cost of " & item 2 of object & " in " & theYear & " is " & totalCost & linefeed & linefeed & theYear & " " & item 1 of object & " dates:" & delimiter & itemListText
	return theText
end assembleText

to writeText from fileText into filePath -- write text to a file
	try
		set fileRef to open for access filePath with write permission
		set eof fileRef to 0 -- overwrite
		write fileText to fileRef
		close access fileRef
		display dialog "File " & quoted form of filePath & " has been updated." buttons {"OK"} default button "OK" giving up after 5
		return true
	on error errmess number errnum
		try
			close access fileRef
		end try
		display alert "Error " & errnum message errMsg buttons {"OK"} default button "OK"
		return false
	end try
end writeText
1 Like

Thanks for the example. I’ll give it a try later today.

I used these enhancements and they work great. I was going to ask about using variables vs properties but I found this post that helps explain.

Thanks for you help, this works and I learned something!