Text Parser

I have a .txt file entitled tasks.txt that contains all of my tasks in the following format:

@context action >project |start date-due date (although not all entries have projects or start/due dates).

Example:
@internet email mark >proposal -feb 8
@internet email scott >proposal |feb 4-feb 6
@internet lookup directions >proposal |feb 12
@errands pickup parcel

I would like to enter a search string (@internet, for example) into a script via Launchbar, and have the script dump into ‘current.txt’ only those lines that match the search string.

In current.txt, if the search was for a context (@internet) I would like the script to remove any lines whose start dates have not yet arrived, and remove just the start date itself of those that have arrived (not the entire line). Next it would sort the lines by due date and then alphabetically.

On the other hand, if the search was for a project (>proposal) then it would only remove the indiviual start dates that have arrived, while keeping the lines of the entries whose start dates have not yet arrived. Then sort again by date and then alphabetically.

Thus if I were to search for @internet today (feb 4), the following would be displayed from the above list:

@internet email scott >proposal -feb 6
@internet email mark >proposal -feb 8

And if I were to search for >proposal, the following would be displayed from the above list:

@internet email scott >proposal -feb 6
@internet email mark >proposal -feb 8
@internet lookup directions >proposal |feb 12

Unfortunately, my scripting ability is very limited. I have been researching for several days in attempts to develop something, but have been completely unsuccessful. It is beyond me. Any assistance would be appreciated.

Thank-you kindly.

You haven’t chosen a format for your task statements that makes for easy searching the way you want to search.

Parsing text is all about exact details. As just one example, your date format will be problematic, as will a date entry like |feb 12. What does the pipe character signify?

Where are the files tasks.txt and current.txt located? Will searches for a context or project always start with “@” or “>”?

Hi envisage,

Also, usually records are stored in text files with a delimiter that separates fields. Are the fields separated with tabs?

Adam,

What do you mean by format for my text statements? Delimiters? As for the date format, would it be better if it was 02/08, for example? I simply use the pipe character to indicate a start date, and the hyphen to indicate a due date, but they are not necessary and could be removed if it would make it easier.

Bruce,

tasks.txt and current.txt are located under Users/User/Core/Agenda/Tasks. And yes, searches for context would always begin with @, and searches for projects would always begin with >.

Kel,

The fields are not separated by tabs. I enter tasks into tasks.txt by inputing text into Launchbar and appending it to the file, and Launchbar does not seem to allow me to input tabs. Could the symbols work as delimiters? @ for context, > for project, | for start date, - for due date, or something of this sort?

The real problem here is that you are, in essence, creating and querying a small database using a tool we don’t have (LaunchBar; I use QuickSilver) and I would do the whole thing in AppleScript.

Databases are not flexible about delimiters (the column separators), nor are they about the column headings. You could get the same data into a uniform format and it would be easy to search. For example:

Using [Type, Action, Person if any, about, start, finish] we get:

which because of its structure is easy to search

set ToDo to paragraphs of (read alias ((path to desktop folder as text) & "tasks.txt"))
set TD to {}
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
repeat with P in ToDo
	set TD's end to text items of P
end repeat
set AppleScript's text item delimiters to tid
TD -->{{"internet", "email", "mark", "proposal", "2/8", ""}, {"internet", "email", "scott", "proposal", "2/4", "2/6"}, {"internet", "lookup", "\"\"", "proposal", "2/12", ""}, {"errand", "pickup", "", "parcel", "", ""}}

set tDay to current date
set SD to date (item 5 of item 1 of TD) --> date "Thursday, February 8, 2007 12:00:00 AM"
set diff to (SD - tDay) / days --> 2.157268518519 days to go (from midnight the 5th)

set SD2 to date (item 5 of item 2 of TD)
set d2 to (SD2 - tDay) --> -0.159 minus means before 12:00:01 AM today

A nest of 4 lists of 6 items each. Easy to get at. Start date is always item 5 of any line and can be coerced to a date.

Hi Adam,

I think “email Mark” is one field (action). This needs to be specified. Are all actions 2 words? There needs to be more rules.

gl,

Hard to guess what’s what, Kel - he doesn’t tell us enough about what he stores, and why he’s not just putting this stuff in a calendar in iCal and scripting what he wants back out of it. (or why he’s not using one of the many applications that Google reveals if you search on: ToDo OS X. Lots of apps).

Hi Adam,

:slight_smile:

Yes, it is hard to do this without enough information knowing what can happen.

Hi envisage,

Instead of using separate delimiters for each field, you should use one delimiter to separate fields. The delimiter should be text that you know won’t be used in individual fields, like tab, although you said you can’t use tab to enter text in the app. There might be some other character you never use instead of space to delimit the fields.

gl,

Hi Adam & Kel,

I use a text file because I find it quicker and simpler than iCal or another program (I have experimented with many of the to-do apps available for OS X). I also use GeekTool to display the contents of the text file on my desktop.

I have a simpler idea for the script…

Can applescript simply find text within a text file, without it having any delimiters? If so, could a script do the following:

  1. Do a search for specific text (i.e. “@internet”)

  2. Set the current date to the following format ‘month.day’ (i.e. ‘02.04’ … as to allow for mathematical comparison between dates)

  3. Do a wildcard search for . (for any dates in the file). If any lines have (anywhere on them) a date greater than the current date as set above, exclude them from the return.

Result: Return any lines that contain the search term but do not have a date greater than the current date.

I do not know applescript well enough to know the actual commands, but this is what I would like the script to do:

Return lines that contain “search_term” and do not contain “.” that is greater than “current_date” (i.e. 02.05)

~

Is this possible?

Thank-you for your continued help.

Sure you can find text within a text file. What you’re asking for is the line of text that contains something and within that line a date (use a slash if you don’t have any urls in your lines). Your format of the date doesn’t matter as long as the month is first and even that’s not critical - the leading zeros don’t matter. No matter what format you use, the AppleScript to do it has to read the whole file in. The script could also delete events that have passed, or move them to a history file for that matter. Lots of things are possible. But bear in mind that you’re asking someone else to do it, and that scripts are basically as dumb as a box of rocks - they do exactly what they’re programmed for, not what you might intend - 0 flexibility, 0 imagination - and hence a pattern of some kind in the input is best when designing filters for them.

How would you distinguish between these when entering a line of text in LaunchBar?

Bruce,

I guess I do not fully understand how this works, but would the period ‘.’ be enough to distinguish the two? The date would be the only location in the line where the period is used. So the search term would never contain a period, and the date would always contain one.

Adam,

Thank-you for the script you wrote above, and for the clarification regarding the necessity of consistent delimiters. The only difference in the structure is that the action is one field, as Kel noted.

context, action, project, start date, due date

example: internet, call mark, proposal, 02/04, 02/06

How could I have your script dump into current.txt only those lines that contain a specified search_term variable and do not contain any start dates (field 4) past the current date? Would it also be possible in current.txt to sort the lines by due date (field 5), and then by action (field 2), and then remove the delimiters?

Thanks again.

What separates the search term and the date(s)? A space?

Hi Bruce,

Yes. Currently, a space separates the search term from the date(s). However, I could change this so that commas act as a delimiter, if need be.

Could the following possibly work?


do shell script "
greaterdate='anything greater than' $(date +%m.%d)
grep @contact Users/User/Core/Agenda/Tasks/tasks.txt | grep -v ${greaterdate}"

In essence I would like the script to return any lines that contain (@contact) and exclude any lines that contain a date (in the format: ‘02.04’, or if necessary ‘02/04’) greater than the current date. I do not know how to use the ‘greater than’ command.

Also, could the result be sorted and then dumped into another .txt file?

What happens towards the end of the year when you start adding entries for January 2008?

You can’t use greater than or less than with dates - you can only add or subtract them and see whether the result is positive or negative.

date “2/6” will always come out in this year at one microsecond after midnight.

date "Tuesday, February 6, 2007 12:00:00 AM"

Adam,

How can I use your script, as described above…

Also, can the script read all of the start dates fields (field 4) at once, rather than individually, as the number of lines in tasks.txt are constantly changing with additions and deletions.

Thank-you for your time.

Something like this - (Not Tested! - gotta run)


set srch to text returned of (display dialog "Enter a search term" default answer "")
set ToDo to paragraphs of (read alias ((path to desktop folder as text) & "tasks.txt"))
set TD to {}
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to ","
repeat with P in ToDo
	set TD's end to text items of P
end repeat
set AppleScript's text item delimiters to tid
-- TD now contains all the lines separated into fields that were in tasks.txt
-- Now go thru them:
set tEvents to {}
set tDay to current date
repeat with aTD in TD
	if aTD contains srch then
		set SD to date (item 5 of aTD)
		if ((SD - tDay) / days div 1) ≤ 0 then -- the start is before today or today
			set end of tEvents to aTD
		end if
	end if
end repeat
-- now you've got the events that contain the search term and meet the date spec in a new list of lists.
-- next you'd sort on the fields (but you don't say on what basis - what if the search term is a date or is an action?
-- Then build a text file from the lists:
set outP to "Current Tasks for " & short date string of tDay & return
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to " *** " -- to separate the fields
repeat with aP in tEvents
	set outP to (outP & (contents of aP) as text) & return
end repeat
set AppleScript's text item delimiters to tid
-- write it out
set CT to open for access ((path to desktop folder as text) & "current.txt") with write permission
try
	set eof of CT to 0 -- erase it if it already exists, leave out line to append it.
	write outP to CT
	close CT
on error
	close CT
end try