Full Code of mjdescy/TodoTxtMac for AI

master a2655cf4e1f7 cached
266 files
1.5 MB
272.6k tokens
4 symbols
1 requests
Download .txt
Showing preview only (1,570K chars total). Download the full file or copy to clipboard to get everything.
Repository: mjdescy/TodoTxtMac
Branch: master
Commit: a2655cf4e1f7
Files: 266
Total size: 1.5 MB

Directory structure:
gitextract_uzrkr__8/

├── .gitignore
├── LICENSE.md
├── README.md
├── Sparkle.framework/
│   └── Versions/
│       └── A/
│           ├── Headers/
│           │   ├── SUAppcast.h
│           │   ├── SUAppcastItem.h
│           │   ├── SUErrors.h
│           │   ├── SUExport.h
│           │   ├── SUStandardVersionComparator.h
│           │   ├── SUUpdater.h
│           │   ├── SUVersionComparisonProtocol.h
│           │   ├── SUVersionDisplayProtocol.h
│           │   └── Sparkle.h
│           ├── Modules/
│           │   └── module.modulemap
│           ├── PrivateHeaders/
│           │   └── SUUnarchiver.h
│           ├── Resources/
│           │   ├── Autoupdate.app/
│           │   │   └── Contents/
│           │   │       ├── Info.plist
│           │   │       ├── MacOS/
│           │   │       │   └── Autoupdate
│           │   │       ├── PkgInfo
│           │   │       └── Resources/
│           │   │           ├── AppIcon.icns
│           │   │           ├── SUStatus.nib
│           │   │           ├── ar.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ca.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── cs.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── da.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── de.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── el.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── en.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── es.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── fi.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── fr.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── he.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── is.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── it.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ja.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ko.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── nb.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── nl.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── pl.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── pt_BR.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── pt_PT.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ro.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ru.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── sk.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── sl.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── sv.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── th.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── tr.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── uk.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── zh_CN.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           └── zh_TW.lproj/
│           │   │               └── Sparkle.strings
│           │   ├── Info.plist
│           │   ├── SUModelTranslation.plist
│           │   ├── SUStatus.nib
│           │   ├── ar.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ca.lproj/
│           │   │   └── Sparkle.strings
│           │   ├── cs.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── da.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── de.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── el.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── en.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── es.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── fi.lproj/
│           │   │   └── Sparkle.strings
│           │   ├── fr.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── he.lproj/
│           │   │   └── Sparkle.strings
│           │   ├── is.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── it.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ja.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ko.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── nb.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── nl.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── pl.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── pt_BR.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── pt_PT.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ro.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ru.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── sk.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── sl.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── sv.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── th.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── tr.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── uk.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── zh_CN.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   └── zh_TW.lproj/
│           │       ├── SUAutomaticUpdateAlert.nib
│           │       ├── SUUpdateAlert.nib
│           │       ├── SUUpdatePermissionPrompt.nib
│           │       └── Sparkle.strings
│           └── Sparkle
├── TodoTxtMac/
│   ├── Base.lproj/
│   │   ├── MainMenu.xib
│   │   ├── RelativeDates.strings
│   │   └── TTMDocument.xib
│   ├── FontNameTransformer.h
│   ├── FontNameTransformer.m
│   ├── Images.xcassets/
│   │   └── AppIcon.appiconset/
│   │       └── Contents.json
│   ├── NSDate+RelativeDates.h
│   ├── NSDate+RelativeDates.m
│   ├── NSMutableAttributableString+ColorRegExMatches.h
│   ├── NSMutableAttributableString+ColorRegExMatches.m
│   ├── NSUserDefaults+myColorSupport.h
│   ├── NSUserDefaults+myColorSupport.m
│   ├── RegExCategories.h
│   ├── RegExCategories.m
│   ├── RelativeDates.strings
│   ├── TTMAppController.h
│   ├── TTMAppController.m
│   ├── TTMAppDelegate.h
│   ├── TTMAppDelegate.m
│   ├── TTMDateUtility.h
│   ├── TTMDateUtility.m
│   ├── TTMDocument.h
│   ├── TTMDocument.m
│   ├── TTMDocumentStatusBarText.h
│   ├── TTMDocumentStatusBarText.m
│   ├── TTMFieldEditor.h
│   ├── TTMFieldEditor.m
│   ├── TTMFilterPredicates.h
│   ├── TTMFilterPredicates.m
│   ├── TTMFilters.xib
│   ├── TTMFiltersController.h
│   ├── TTMFiltersController.m
│   ├── TTMFindReplace.xib
│   ├── TTMPredicateEditorCompletedRowTemplate.h
│   ├── TTMPredicateEditorCompletedRowTemplate.m
│   ├── TTMPredicateEditorDateRowTemplate.h
│   ├── TTMPredicateEditorDateRowTemplate.m
│   ├── TTMPredicateEditorDueRowTemplate.h
│   ├── TTMPredicateEditorDueRowTemplate.m
│   ├── TTMPredicateEditorHiddenRowTemplate.h
│   ├── TTMPredicateEditorHiddenRowTemplate.m
│   ├── TTMPredicateEditorTextRowTemplate.h
│   ├── TTMPredicateEditorTextRowTemplate.m
│   ├── TTMPredicateEditorThresholdRowTemplate.h
│   ├── TTMPredicateEditorThresholdRowTemplate.m
│   ├── TTMPreferences.xib
│   ├── TTMPreferencesController.h
│   ├── TTMPreferencesController.m
│   ├── TTMTableView.h
│   ├── TTMTableView.m
│   ├── TTMTableViewDelegate.h
│   ├── TTMTableViewDelegate.m
│   ├── TTMTask.h
│   ├── TTMTask.m
│   ├── TTMTasklistMetadata.h
│   ├── TTMTasklistMetadata.m
│   ├── TTMTasklistMetadata.xib
│   ├── TodoTxtMac-Info.plist
│   ├── TodoTxtMac-Prefix.pch
│   ├── TodoTxtMac.entitlements
│   ├── en.lproj/
│   │   ├── Credits.rtf
│   │   ├── InfoPlist.strings
│   │   └── RelativeDates.strings
│   └── main.m
├── TodoTxtMac.xcodeproj/
│   ├── project.pbxproj
│   └── project.xcworkspace/
│       ├── contents.xcworkspacedata
│       └── xcshareddata/
│           └── TodoTxtMac.xccheckout
├── TodoTxtMacTests/
│   ├── TTMDateUtility_UnitTests.m
│   ├── TTMTask_AppendText_UnitTests.m
│   ├── TTMTask_CompletionDate_UnitTests.m
│   ├── TTMTask_Contexts_UnitTests.m
│   ├── TTMTask_CreationDate_UnitTests.m
│   ├── TTMTask_DecreasePriority_UnitTests.m
│   ├── TTMTask_DecrementDueDate_UnitTests.m
│   ├── TTMTask_DecrementThresholdDate_UnitTests.m
│   ├── TTMTask_DueDate_UnitTests.m
│   ├── TTMTask_DueState_UnitTests.m
│   ├── TTMTask_IncreasePriority_UnitTests.m
│   ├── TTMTask_IncrementDueDate_UnitTests.m
│   ├── TTMTask_IncrementThresholdDate_UnitTests.m
│   ├── TTMTask_Init_UnitTests.m
│   ├── TTMTask_IsCompleted_UnitTests.m
│   ├── TTMTask_IsHidden_UnitTests.m
│   ├── TTMTask_MarkComplete_UnitTests.m
│   ├── TTMTask_MarkIncomplete_UnitTests.m
│   ├── TTMTask_Postpone_UnitTests.m
│   ├── TTMTask_PrependText_UnitTests.m
│   ├── TTMTask_Priority_UnitTests.m
│   ├── TTMTask_Projects_UnitTests.m
│   ├── TTMTask_RemoveDueDate_UnitTests.m
│   ├── TTMTask_RemovePriority_UnitTests.m
│   ├── TTMTask_RemoveThresholdDate_UnitTests.m
│   ├── TTMTask_ReplaceText_UnitTests.m
│   ├── TTMTask_SetDueDate_UnitTests.m
│   ├── TTMTask_SetThresholdDate_UnitTests.m
│   ├── TTMTask_ThresholdDate_UnitTests.m
│   ├── TTMTask_ThresholdState_UnitTests.m
│   ├── TTMTask_ToggleCompletion_UnitTests.m
│   ├── TTMTasklistMetadata_UnitTests.m
│   ├── TodoTxtMacTests-Info.plist
│   └── en.lproj/
│       └── InfoPlist.strings
└── dsa_pub.pem

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# taken from http://blog.illuminex.com/2009/10/better-sample-gitignore-file-for-xcode.html

# Mac OS X Finder and whatnot
.DS_Store


# Sparkle distribution Private Key (Don't check me in!)
dsa_priv.pem


# XCode (and ancestors) per-user config (very noisy, and not relevant)
*.mode1
*.mode1v3
*.mode2v3
*.perspective
*.perspectivev3
*.pbxuser

# Xcode 4 http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects
xcuserdata


# Generated files
VersionX-revision.h


# build products
build/
*.[oa]

# Other source repository archive directories (protects when importing)
.hg
.svn
CVS


# automatic backup files
*~.nib
*.swp
*~
*(Autosaved).rtfd/
Backup[ ]of[ ]*.pages/
Backup[ ]of[ ]*.key/
Backup[ ]of[ ]*.numbers/



================================================
FILE: LICENSE.md
================================================
TodoTxtMac: A Todo.txt todo manager for Mac OS X




Copyright (C) 2014 Michael Descy

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.




The MIT License (MIT)

Copyright (C) 2014 Michael Descy

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


================================================
FILE: README.md
================================================
# TodoTxtMac

# Overview

TodoTxtMac is a minimalist, keyboard-driven to-do manager for Mac OS X that conforms to the todo.txt format spec. Version 2.0.0 and up are supported only on Mac OS X 10.11 (El Capitan). Version 1.6.1 can be used on lower versions of Mac OS X, down to Mac OS X 10.8, though support is not guaranteed.

# Goals

This application is inspired by the [Todotxt.net][] application for Microsoft Windows with numerous improvements and modifications specific to the Mac OS X platform. It is designed to pair well with other todo.txt applications, such as [SwiftoDo][], [Todotxt.net][], [SimpleTask][], [topydo][], and [many others][].

From a design perspective the goal is to be the fastest, simplest, and cleanest implementation possible.

[todotxt.net]: http://benrhughes.github.io/todotxt.net/
[SwiftoDo]: https://itunes.apple.com/us/app/swiftodo-task-list-for-todo.txt/id1073798440?ls=1&mt=8
[SimpleTask]: https://play.google.com/store/apps/details?id=nl.mpcjanssen.todotxtholo
[topydo]: https://github.com/bram85/topydo
[many others]: http://todotxt.com

# Features

## General features

- Full compliance with the todo.txt format spec.
- Fully keyboard-driven, with one-key bindings for commonly-used commands.
- Multiple selection in the task list.
- Support for due dates, which are formatted "due:YYYY-MM-DD".
- Shortcuts to toggle completion, change priority, set due dates, and delete all selected tasks.
- Archive completed tasks (to done.txt), either on command or automatically.
- Preserves Windows or Unix line endings in the todo.txt file for cross-platform compatability.
- Automatic update checking.
- Displays general metadata (task counts, etc.) about the task list.
- Undo/redo support.

## Adding/removing tasks

- Paste one or more tasks into the task list from the clipboard.
- Import one or more tasks into the task list via drag-and-drop.
- Optionally prepend the task creation task on newly created tasks (including those pasted in from the clipboard).
- Copy selected tasks to the clipboard.
- Cut selected tasks to the clipboard.
- Reload file on command.

## Sorting and filtering

- Sort task list by priority, project, context, due date, etc.
- Filter task list.
- Quick filters: preset filters mapped to number keys.
- Search field for quick, ad-hoc filtering of the task list.

## Due dates

- Set arbitrary due dates on selected tasks.
- Increment, decrement, or remove due dates.
- Postpone tasks by X (user-entered) days.
- Supports relative due dates, such as "due:tomorrow" and "due:Saturday" for new tasks. These strings can be localized.

## Fonts and colors

- User-customizable font for the task list.
- Bold priorities in task list.
- Colors completed tasks in light gray and applies strikethrough.
- Colors overdue tasks in purple and tasks due today in red. Both these colors are user customizable.
- User-customizable colors for projects, contexts, due dates, threshold dates, creation dates, and arbitrary tags in task list.

## Mac-specific user interface features

- Autosave on change (Note that the title bar will say "Edited" even after autosaving, because this is the Mac's default behavior).
- Autocomplete project names.
- Autocomplete context names.
- Multiple document interface.
- Full screen mode.
- Open todo.txt files by dragging and dropping them onto the application icon.

# Keyboard Shortcuts

## Working with tasks

- N: new task
- J: move down to next task
- K: move up to previous task
- X: toggle task completion
- D or Backspace: delete task (with confirmation)
- U or Enter: update task
- P: postpone task by X (user-entered) days
- S: set due date
- Option+S: set threshold date
- I: set priority to user-entered value (A-Z)
- T: append text to end of selected tasks
- R: prepend text to beginning of selected tasks (after priority and creation date if they exist)
- A: archive completed tasks (archive file done.txt must be set)
- Command+Up: Increase priority
- Command+Down: Decrease priority
- Command+Left or Command+Right: Remove priority
- Command+C: Copy selected tasks to the clipboard
- Command+X: Cut selected tasks (copy to the clipboard and delete from task list)
- Command+Shift+V: Paste tasks into the task list from the clipboard
- Command+Option+Up: Increase due date by 1 day
- Command+Option+Down: Decrease due date by 1 day
- Command+Option+Left or Command+Option+Right: Remove due date

## Undo/redo

- Command+Z: Undo
- Command+Shift+Z: Redo

## Working with files

- Command+N: new file
- Command+O: open file
- Command+S: save file (forces the file to save immediately)
- .: reload file
- Command+I: view task list metadata (task counts, etc.)
- Command+W: close file
- Command+Option+W: close all files

## Sorting the task list

- Command+0: order in file
- Command+1: priority
- Command+2: project
- Command+3: context
- Command+4: due date
- Command+5: creation date
- Command+6: completion date
- Command+7: threshold date
- Command+8: alphabetical

## Filtering the task list

- Command+F: find within displayed tasks (moves focus to the search field)
- F: define quick filters
- 1: apply quick filter 1
- 2: apply quick filter 2
- 3: apply quick filter 3
- 4: apply quick filter 4
- 5: apply quick filter 5
- 6: apply quick filter 6
- 7: apply quick filter 7
- 8: apply quick filter 8
- 9: apply quick filter 9
- 0: remove applied filter

# Features Not Planned

- This application is not meant for direct reordering of tasks in the todo.txt file.
- This application does not retain blank lines in the todo.txt file.
- This application does not support line breaks, long-form notes, attachments, or other features not part of the todo.txt format specification.

# Frequently Asked Questions (FAQ)

## Is there a preference to re-open my todo.txt file on launch?

Yes, but most people will not need such a preference, because the default behavior of TodoTxtMac is to reopen whatever todo.txt files were open when you last quit the app. To enjoy this behavior, do not close your todo.txt file's window prior to quitting the app.

If the TodoTxtMac is not reopening your files, or keeping a list of them in the "File > Open Recent" menu, then you should check the following preferences under System Preferences > General:

1. "Close windows when quitting an app" must be unchecked.
2. "Recent items" must not be "None".

If you need to force TodoTxtMac to open a particular todo file on launch, you may set a default todo.txt file in TodoTxtMac's Preferences > Startup.

You may also force TodoTxtMac to open a particular todo file on launch, you may launch the app with the command-line argument "todo-file", in the Terminal, as follows:

    $ open /Applications/TodoTxtMac.app --args -todo-file ~/Documents/todo.txt

## Is this application Dropbox-enabled?

No. Unlike the official Todo.txt iOS application, this application does not call Dropbox's API. You can sync your file outside of TodoTxtMac via Dropbox or other services.

## TodoTxtMac says my todo.txt file cannot be autosaved. The file has been changed by another application.

Your todo.txt file can get modified outside of TodoTxtMac, especially if you are syncing the file via Dropbox or a similar service. TodoTxtMac uses Cocoa's default document object model to handle the file interactions. This means that the application will warn you of file changes that came from outside the application when you try to make changes to the file, not at the moment the file was changed. To avoid file conflicts, try the following strategies:

1. Reload your TodoTxtMac file manually (press `.`) before making changes to it, if you believe the file was updated (by Dropbox for example) recently.
2. Close TodoTxtMac when not using it for extended periods.
3. When presented with the option to "Save Anyway" or "Revert" changes, always revert changes. You will have to re-do your last action in TodoTxtMac, but you will not lose the changes that originated outside the application.

## Will this project be ported from Objective C to Swift?

When Apple officially deprecates Objective C, the plan is to migrate this project to Swift.

# License

This application is dual-licensed under the GNU General Public License and the MIT License. See LICENSE.txt for full license information.

# For Contributors

## Source Code Conventions

I am striving for very clean code. I am following the following general coding conventions:

- For clarity, limit nesting of brackets to two sets per line, as in: `[[thisString stringValue] isEqualToString:@"otherStringValue"]`.
- Maximum line length of 100 characters.
- Indent with spaces rather than tabs.
- Always use curly braces for conditionals and loops.
- Use descriptive variable and method names.

## Pull Requests

The project uses [git-flow] to implement Vincent Driessen's [branching model]. All pull requests should be directed at the "develop" branch.

[git-flow]: https://github.com/nvie/gitflow
[branching model]: http://nvie.com/posts/a-successful-git-branching-model/

# Credits/Thanks

Thanks to Gina Trapani who created the [Todo.txt][] format and the community of developers who created the command line tools and iOS/Android apps.

Thanks to Ben Hughes whose Windows application [todotxt.net][] formed the basis of this application's design and feature set. Todotxt.net is a fantastic program and did not have an analog on the Mac. After starting my application, I contributed some patches to todotxt.net and am happy to be a contributor on such a great project.

Thanks to Josh Wright <@BendyTree> for his [RegExCategories][] library.

Thanks to Sam Daitzman <@sdaitzman> for the application icon.

Thanks to Andy Matuschak and the other contributors for the [Sparkle framework].

[Todo.txt]: http://www.todotxt.com
[RegExCategories]: https://github.com/bendytree/Objective-C-RegEx-Categories
[OK Icon]: http://vector.me/browse/329308/ok_icon
[Vector.me]: http://vector.me/
[Sparkle framework]: http://sparkle.andymatuschak.org/


================================================
FILE: Sparkle.framework/Versions/A/Headers/SUAppcast.h
================================================
//
//  SUAppcast.h
//  Sparkle
//
//  Created by Andy Matuschak on 3/12/06.
//  Copyright 2006 Andy Matuschak. All rights reserved.
//

#ifndef SUAPPCAST_H
#define SUAPPCAST_H

#import <Foundation/Foundation.h>
#import "SUExport.h"

@class SUAppcastItem;
SU_EXPORT @interface SUAppcast : NSObject<NSURLDownloadDelegate>

@property (copy) NSString *userAgentString;
@property (copy) NSDictionary *httpHeaders;

- (void)fetchAppcastFromURL:(NSURL *)url completionBlock:(void (^)(NSError *))err;
- (SUAppcast *)copyWithoutDeltaUpdates;

@property (readonly, copy) NSArray *items;
@end

#endif


================================================
FILE: Sparkle.framework/Versions/A/Headers/SUAppcastItem.h
================================================
//
//  SUAppcastItem.h
//  Sparkle
//
//  Created by Andy Matuschak on 3/12/06.
//  Copyright 2006 Andy Matuschak. All rights reserved.
//

#ifndef SUAPPCASTITEM_H
#define SUAPPCASTITEM_H

#import <Foundation/Foundation.h>
#import "SUExport.h"

SU_EXPORT @interface SUAppcastItem : NSObject
@property (copy, readonly) NSString *title;
@property (copy, readonly) NSDate *date;
@property (copy, readonly) NSString *itemDescription;
@property (strong, readonly) NSURL *releaseNotesURL;
@property (copy, readonly) NSString *DSASignature;
@property (copy, readonly) NSString *minimumSystemVersion;
@property (copy, readonly) NSString *maximumSystemVersion;
@property (strong, readonly) NSURL *fileURL;
@property (copy, readonly) NSString *versionString;
@property (copy, readonly) NSString *displayVersionString;
@property (copy, readonly) NSDictionary *deltaUpdates;
@property (strong, readonly) NSURL *infoURL;

// Initializes with data from a dictionary provided by the RSS class.
- (instancetype)initWithDictionary:(NSDictionary *)dict;
- (instancetype)initWithDictionary:(NSDictionary *)dict failureReason:(NSString **)error;

@property (getter=isDeltaUpdate, readonly) BOOL deltaUpdate;
@property (getter=isCriticalUpdate, readonly) BOOL criticalUpdate;
@property (getter=isInformationOnlyUpdate, readonly) BOOL informationOnlyUpdate;

// Returns the dictionary provided in initWithDictionary; this might be useful later for extensions.
@property (readonly, copy) NSDictionary *propertiesDictionary;

- (NSURL *)infoURL;

@end

#endif


================================================
FILE: Sparkle.framework/Versions/A/Headers/SUErrors.h
================================================
//
//  SUErrors.h
//  Sparkle
//
//  Created by C.W. Betts on 10/13/14.
//  Copyright (c) 2014 Sparkle Project. All rights reserved.
//

#ifndef SUERRORS_H
#define SUERRORS_H

#import <Foundation/Foundation.h>
#import "SUExport.h"

/**
 * Error domain used by Sparkle
 */
SU_EXPORT extern NSString *const SUSparkleErrorDomain;

typedef NS_ENUM(OSStatus, SUError) {
    // Appcast phase errors.
    SUAppcastParseError = 1000,
    SUNoUpdateError = 1001,
    SUAppcastError = 1002,
    SURunningFromDiskImageError = 1003,
    
    // Downlaod phase errors.
    SUTemporaryDirectoryError = 2000,
    
    // Extraction phase errors.
    SUUnarchivingError = 3000,
    SUSignatureError = 3001,
    
    // Installation phase errors.
    SUFileCopyFailure = 4000,
    SUAuthenticationFailure = 4001,
    SUMissingUpdateError = 4002,
    SUMissingInstallerToolError = 4003,
    SURelaunchError = 4004,
    SUInstallationError = 4005,
    SUDowngradeError = 4006,
    
    // System phase errors
    SUSystemPowerOffError = 5000
};

#endif


================================================
FILE: Sparkle.framework/Versions/A/Headers/SUExport.h
================================================
//
//  SUExport.h
//  Sparkle
//
//  Created by Jake Petroules on 2014-08-23.
//  Copyright (c) 2014 Sparkle Project. All rights reserved.
//

#ifndef SUEXPORT_H
#define SUEXPORT_H

#ifdef BUILDING_SPARKLE
#define SU_EXPORT __attribute__((visibility("default")))
#else
#define SU_EXPORT
#endif

#endif


================================================
FILE: Sparkle.framework/Versions/A/Headers/SUStandardVersionComparator.h
================================================
//
//  SUStandardVersionComparator.h
//  Sparkle
//
//  Created by Andy Matuschak on 12/21/07.
//  Copyright 2007 Andy Matuschak. All rights reserved.
//

#ifndef SUSTANDARDVERSIONCOMPARATOR_H
#define SUSTANDARDVERSIONCOMPARATOR_H

#import <Foundation/Foundation.h>
#import "SUExport.h"
#import "SUVersionComparisonProtocol.h"

/*!
    Sparkle's default version comparator.

    This comparator is adapted from MacPAD, by Kevin Ballard.
    It's "dumb" in that it does essentially string comparison,
    in components split by character type.
*/
SU_EXPORT @interface SUStandardVersionComparator : NSObject <SUVersionComparison>

/*!
    Returns a singleton instance of the comparator.
*/
+ (SUStandardVersionComparator *)defaultComparator;

/*!
    Compares version strings through textual analysis.

    See the implementation for more details.
*/
- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB;
@end

#endif


================================================
FILE: Sparkle.framework/Versions/A/Headers/SUUpdater.h
================================================
//
//  SUUpdater.h
//  Sparkle
//
//  Created by Andy Matuschak on 1/4/06.
//  Copyright 2006 Andy Matuschak. All rights reserved.
//

#ifndef SUUPDATER_H
#define SUUPDATER_H

#import <Foundation/Foundation.h>
#import "SUExport.h"
#import "SUVersionComparisonProtocol.h"
#import "SUVersionDisplayProtocol.h"

@class SUAppcastItem, SUAppcast;

@protocol SUUpdaterDelegate;

/*!
    The main API in Sparkle for controlling the update mechanism.

    This class is used to configure the update paramters as well as manually
    and automatically schedule and control checks for updates.
 */
SU_EXPORT @interface SUUpdater : NSObject

@property (unsafe_unretained) IBOutlet id<SUUpdaterDelegate> delegate;

+ (SUUpdater *)sharedUpdater;
+ (SUUpdater *)updaterForBundle:(NSBundle *)bundle;
- (instancetype)initForBundle:(NSBundle *)bundle;

@property (readonly, strong) NSBundle *hostBundle;
@property (strong, readonly) NSBundle *sparkleBundle;

@property BOOL automaticallyChecksForUpdates;

@property NSTimeInterval updateCheckInterval;

/*!
 * The URL of the appcast used to download update information.
 *
 * This property must be called on the main thread.
 */
@property (copy) NSURL *feedURL;

@property (nonatomic, copy) NSString *userAgentString;

@property (copy) NSDictionary *httpHeaders;

@property BOOL sendsSystemProfile;

@property BOOL automaticallyDownloadsUpdates;

@property (nonatomic, copy) NSString *decryptionPassword;

/*!
    Explicitly checks for updates and displays a progress dialog while doing so.

    This method is meant for a main menu item.
    Connect any menu item to this action in Interface Builder,
    and Sparkle will check for updates and report back its findings verbosely
    when it is invoked.
 */
- (IBAction)checkForUpdates:(id)sender;

/*!
    Checks for updates, but does not display any UI unless an update is found.

    This is meant for programmatically initating a check for updates. That is,
    it will display no UI unless it actually finds an update, in which case it
    proceeds as usual.

    If the fully automated updating is turned on, however, this will invoke that
    behavior, and if an update is found, it will be downloaded and prepped for
    installation.
 */
- (void)checkForUpdatesInBackground;

/*!
    Checks for updates and, if available, immediately downloads and installs them.
    A progress dialog is shown but the user will never be prompted to read the
    release notes.
    
    You may want to respond to the userDidCancelDownload delegate method in case
    the user clicks the "Cancel" button while the update is downloading.
 */
- (void)installUpdatesIfAvailable;

/*!
    Returns the date of last update check.

    \returns \c nil if no check has been performed.
 */
@property (readonly, copy) NSDate *lastUpdateCheckDate;

/*!
    Begins a "probing" check for updates which will not actually offer to
    update to that version.

    However, the delegate methods
    SUUpdaterDelegate::updater:didFindValidUpdate: and
    SUUpdaterDelegate::updaterDidNotFindUpdate: will be called,
    so you can use that information in your UI.
 */
- (void)checkForUpdateInformation;

/*!
    Appropriately schedules or cancels the update checking timer according to
    the preferences for time interval and automatic checks.

    This call does not change the date of the next check,
    but only the internal NSTimer.
 */
- (void)resetUpdateCycle;

@property (readonly) BOOL updateInProgress;

@end

// -----------------------------------------------------------------------------
// SUUpdater Notifications for events that might be interesting to more than just the delegate
// The updater will be the notification object
// -----------------------------------------------------------------------------
SU_EXPORT extern NSString *const SUUpdaterDidFinishLoadingAppCastNotification;
SU_EXPORT extern NSString *const SUUpdaterDidFindValidUpdateNotification;
SU_EXPORT extern NSString *const SUUpdaterDidNotFindUpdateNotification;
SU_EXPORT extern NSString *const SUUpdaterWillRestartNotification;
#define SUUpdaterWillRelaunchApplicationNotification SUUpdaterWillRestartNotification;
#define SUUpdaterWillInstallUpdateNotification SUUpdaterWillRestartNotification;

// Key for the SUAppcastItem object in the SUUpdaterDidFindValidUpdateNotification userInfo
SU_EXPORT extern NSString *const SUUpdaterAppcastItemNotificationKey;
// Key for the SUAppcast object in the SUUpdaterDidFinishLoadingAppCastNotification userInfo
SU_EXPORT extern NSString *const SUUpdaterAppcastNotificationKey;

// -----------------------------------------------------------------------------
//	SUUpdater Delegate:
// -----------------------------------------------------------------------------

/*!
    Provides methods to control the behavior of an SUUpdater object.
 */
@protocol SUUpdaterDelegate <NSObject>
@optional

/*!
    Returns whether to allow Sparkle to pop up.

    For example, this may be used to prevent Sparkle from interrupting a setup assistant.

    \param updater The SUUpdater instance.
 */
- (BOOL)updaterMayCheckForUpdates:(SUUpdater *)updater;

/*!
    Returns additional parameters to append to the appcast URL's query string.

    This is potentially based on whether or not Sparkle will also be sending along the system profile.

    \param updater The SUUpdater instance.
    \param sendingProfile Whether the system profile will also be sent.

    \return An array of dictionaries with keys: "key", "value", "displayKey", "displayValue", the latter two being specifically for display to the user.
 */
- (NSArray *)feedParametersForUpdater:(SUUpdater *)updater sendingSystemProfile:(BOOL)sendingProfile;

/*!
    Returns a custom appcast URL.

    Override this to dynamically specify the entire URL.

    \param updater The SUUpdater instance.
 */
- (NSString *)feedURLStringForUpdater:(SUUpdater *)updater;

/*!
    Returns whether Sparkle should prompt the user about automatic update checks.

    Use this to override the default behavior.

    \param updater The SUUpdater instance.
 */
- (BOOL)updaterShouldPromptForPermissionToCheckForUpdates:(SUUpdater *)updater;

/*!
    Called after Sparkle has downloaded the appcast from the remote server.

    Implement this if you want to do some special handling with the appcast once it finishes loading.

    \param updater The SUUpdater instance.
    \param appcast The appcast that was downloaded from the remote server.
 */
- (void)updater:(SUUpdater *)updater didFinishLoadingAppcast:(SUAppcast *)appcast;

/*!
    Returns the item in the appcast corresponding to the update that should be installed.

    If you're using special logic or extensions in your appcast,
    implement this to use your own logic for finding a valid update, if any,
    in the given appcast.

    \param appcast The appcast that was downloaded from the remote server.
    \param updater The SUUpdater instance.
 */
- (SUAppcastItem *)bestValidUpdateInAppcast:(SUAppcast *)appcast forUpdater:(SUUpdater *)updater;

/*!
    Called when a valid update is found by the update driver.

    \param updater The SUUpdater instance.
    \param item The appcast item corresponding to the update that is proposed to be installed.
 */
- (void)updater:(SUUpdater *)updater didFindValidUpdate:(SUAppcastItem *)item;

/*!
    Called when a valid update is not found.

    \param updater The SUUpdater instance.
 */
- (void)updaterDidNotFindUpdate:(SUUpdater *)updater;

/*!
    Called immediately before downloading the specified update.

    \param updater The SUUpdater instance.
    \param item The appcast item corresponding to the update that is proposed to be downloaded.
    \param request The mutable URL request that will be used to download the update.
 */
- (void)updater:(SUUpdater *)updater willDownloadUpdate:(SUAppcastItem *)item withRequest:(NSMutableURLRequest *)request;

/*!
    Called after the specified update failed to download.

    \param updater The SUUpdater instance.
    \param item The appcast item corresponding to the update that failed to download.
    \param error The error generated by the failed download.
 */
- (void)updater:(SUUpdater *)updater failedToDownloadUpdate:(SUAppcastItem *)item error:(NSError *)error;

/*!
    Called when the user clicks the cancel button while and update is being downloaded.

    \param updater The SUUpdater instance.
 */
- (void)userDidCancelDownload:(SUUpdater *)updater;

/*!
    Called immediately before installing the specified update.

    \param updater The SUUpdater instance.
    \param item The appcast item corresponding to the update that is proposed to be installed.
 */
- (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)item;

/*!
    Returns whether the relaunch should be delayed in order to perform other tasks.

    This is not called if the user didn't relaunch on the previous update,
    in that case it will immediately restart.

    \param updater The SUUpdater instance.
    \param item The appcast item corresponding to the update that is proposed to be installed.
    \param invocation The invocation that must be completed before continuing with the relaunch.

    \return \c YES to delay the relaunch until \p invocation is invoked.
 */
- (BOOL)updater:(SUUpdater *)updater shouldPostponeRelaunchForUpdate:(SUAppcastItem *)item untilInvoking:(NSInvocation *)invocation;

/*!
    Returns whether the application should be relaunched at all.

    Some apps \b cannot be relaunched under certain circumstances.
    This method can be used to explicitly prevent a relaunch.

    \param updater The SUUpdater instance.
 */
- (BOOL)updaterShouldRelaunchApplication:(SUUpdater *)updater;

/*!
    Called immediately before relaunching.

    \param updater The SUUpdater instance.
 */
- (void)updaterWillRelaunchApplication:(SUUpdater *)updater;

/*!
    Returns an object that compares version numbers to determine their arithmetic relation to each other.

    This method allows you to provide a custom version comparator.
    If you don't implement this method or return \c nil,
    the standard version comparator will be used.

    \sa SUStandardVersionComparator

    \param updater The SUUpdater instance.
 */
- (id<SUVersionComparison>)versionComparatorForUpdater:(SUUpdater *)updater;

/*!
    Returns an object that formats version numbers for display to the user.

    If you don't implement this method or return \c nil,
    the standard version formatter will be used.

    \sa SUUpdateAlert

    \param updater The SUUpdater instance.
 */
- (id<SUVersionDisplay>)versionDisplayerForUpdater:(SUUpdater *)updater;

/*!
    Returns the path which is used to relaunch the client after the update is installed.

    The default is the path of the host bundle.

    \param updater The SUUpdater instance.
 */
- (NSString *)pathToRelaunchForUpdater:(SUUpdater *)updater;

/*!
    Called before an updater shows a modal alert window,
    to give the host the opportunity to hide attached windows that may get in the way.

    \param updater The SUUpdater instance.
 */
- (void)updaterWillShowModalAlert:(SUUpdater *)updater;

/*!
    Called after an updater shows a modal alert window,
    to give the host the opportunity to hide attached windows that may get in the way.

    \param updater The SUUpdater instance.
 */
- (void)updaterDidShowModalAlert:(SUUpdater *)updater;

/*!
    Called when an update is scheduled to be silently installed on quit.

    \param updater The SUUpdater instance.
    \param item The appcast item corresponding to the update that is proposed to be installed.
    \param invocation Can be used to trigger an immediate silent install and relaunch.
 */
- (void)updater:(SUUpdater *)updater willInstallUpdateOnQuit:(SUAppcastItem *)item immediateInstallationInvocation:(NSInvocation *)invocation;

/*!
    Calls after an update that was scheduled to be silently installed on quit has been canceled.

    \param updater The SUUpdater instance.
    \param item The appcast item corresponding to the update that was proposed to be installed.
 */
- (void)updater:(SUUpdater *)updater didCancelInstallUpdateOnQuit:(SUAppcastItem *)item;

/*!
    Called after an update is aborted due to an error.

    \param updater The SUUpdater instance.
    \param error The error that caused the abort
 */
- (void)updater:(SUUpdater *)updater didAbortWithError:(NSError *)error;

@end

#endif


================================================
FILE: Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h
================================================
//
//  SUVersionComparisonProtocol.h
//  Sparkle
//
//  Created by Andy Matuschak on 12/21/07.
//  Copyright 2007 Andy Matuschak. All rights reserved.
//

#ifndef SUVERSIONCOMPARISONPROTOCOL_H
#define SUVERSIONCOMPARISONPROTOCOL_H

#import <Cocoa/Cocoa.h>
#import "SUExport.h"

/*!
    Provides version comparison facilities for Sparkle.
*/
@protocol SUVersionComparison

/*!
    An abstract method to compare two version strings.

    Should return NSOrderedAscending if b > a, NSOrderedDescending if b < a,
    and NSOrderedSame if they are equivalent.
*/
- (NSComparisonResult)compareVersion:(NSString *)versionA toVersion:(NSString *)versionB; // *** MAY BE CALLED ON NON-MAIN THREAD!

@end

#endif


================================================
FILE: Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h
================================================
//
//  SUVersionDisplayProtocol.h
//  EyeTV
//
//  Created by Uli Kusterer on 08.12.09.
//  Copyright 2009 Elgato Systems GmbH. All rights reserved.
//

#import <Cocoa/Cocoa.h>
#import "SUExport.h"

/*!
    Applies special display formatting to version numbers.
*/
@protocol SUVersionDisplay

/*!
    Formats two version strings.

    Both versions are provided so that important distinguishing information
    can be displayed while also leaving out unnecessary/confusing parts.
*/
- (void)formatVersion:(NSString **)inOutVersionA andVersion:(NSString **)inOutVersionB;

@end


================================================
FILE: Sparkle.framework/Versions/A/Headers/Sparkle.h
================================================
//
//  Sparkle.h
//  Sparkle
//
//  Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07)
//  Copyright 2006 Andy Matuschak. All rights reserved.
//

#ifndef SPARKLE_H
#define SPARKLE_H

#import <Cocoa/Cocoa.h>

// This list should include the shared headers. It doesn't matter if some of them aren't shared (unless
// there are name-space collisions) so we can list all of them to start with:

#import "SUAppcast.h"
#import "SUAppcastItem.h"
#import "SUStandardVersionComparator.h"
#import "SUUpdater.h"
#import "SUVersionComparisonProtocol.h"
#import "SUVersionDisplayProtocol.h"
#import "SUErrors.h"

#endif


================================================
FILE: Sparkle.framework/Versions/A/Modules/module.modulemap
================================================
framework module Sparkle {
  umbrella header "Sparkle.h"

  export *
  module * { export * }
}


================================================
FILE: Sparkle.framework/Versions/A/PrivateHeaders/SUUnarchiver.h
================================================
//
//  SUUnarchiver.h
//  Sparkle
//
//  Created by Andy Matuschak on 3/16/06.
//  Copyright 2006 Andy Matuschak. All rights reserved.
//

#ifndef SUUNARCHIVER_H
#define SUUNARCHIVER_H

#import <Foundation/Foundation.h>

@class SUHost;
@protocol SUUnarchiverDelegate;

@interface SUUnarchiver : NSObject

@property (copy, readonly) NSString *archivePath;
@property (copy, readonly) NSString *updateHostBundlePath;
@property (copy, readonly) NSString *decryptionPassword;
@property (weak) id<SUUnarchiverDelegate> delegate;

+ (SUUnarchiver *)unarchiverForPath:(NSString *)path updatingHostBundlePath:(NSString *)host withPassword:(NSString *)decryptionPassword;

- (void)start;
@end

@protocol SUUnarchiverDelegate <NSObject>
- (void)unarchiverDidFinish:(SUUnarchiver *)unarchiver;
- (void)unarchiverDidFail:(SUUnarchiver *)unarchiver;
@optional
- (void)unarchiver:(SUUnarchiver *)unarchiver extractedProgress:(double)progress;
@end

#endif


================================================
FILE: Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>BuildMachineOSBuild</key>
	<string>15E49a</string>
	<key>CFBundleDevelopmentRegion</key>
	<string>English</string>
	<key>CFBundleExecutable</key>
	<string>Autoupdate</string>
	<key>CFBundleIconFile</key>
	<string>AppIcon</string>
	<key>CFBundleIdentifier</key>
	<string>org.sparkle-project.Sparkle.Autoupdate</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.14.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleSupportedPlatforms</key>
	<array>
		<string>MacOSX</string>
	</array>
	<key>CFBundleVersion</key>
	<string>1.14.0</string>
	<key>DTCompiler</key>
	<string>com.apple.compilers.llvm.clang.1_0</string>
	<key>DTPlatformBuild</key>
	<string>7C1002</string>
	<key>DTPlatformVersion</key>
	<string>GM</string>
	<key>DTSDKBuild</key>
	<string>15C43</string>
	<key>DTSDKName</key>
	<string>macosx10.11</string>
	<key>DTXcode</key>
	<string>0721</string>
	<key>DTXcodeBuild</key>
	<string>7C1002</string>
	<key>LSBackgroundOnly</key>
	<string>1</string>
	<key>LSMinimumSystemVersion</key>
	<string>10.7</string>
	<key>LSUIElement</key>
	<string>1</string>
	<key>NSMainNibFile</key>
	<string>MainMenu</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>
</dict>
</plist>


================================================
FILE: Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/PkgInfo
================================================
APPL????

================================================
FILE: Sparkle.framework/Versions/A/Resources/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>BuildMachineOSBuild</key>
	<string>15E49a</string>
	<key>CFBundleDevelopmentRegion</key>
	<string>en</string>
	<key>CFBundleExecutable</key>
	<string>Sparkle</string>
	<key>CFBundleIdentifier</key>
	<string>org.sparkle-project.Sparkle</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>Sparkle</string>
	<key>CFBundlePackageType</key>
	<string>FMWK</string>
	<key>CFBundleShortVersionString</key>
	<string>1.14.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleSupportedPlatforms</key>
	<array>
		<string>MacOSX</string>
	</array>
	<key>CFBundleVersion</key>
	<string>1.14.0</string>
	<key>DTCompiler</key>
	<string>com.apple.compilers.llvm.clang.1_0</string>
	<key>DTPlatformBuild</key>
	<string>7C1002</string>
	<key>DTPlatformVersion</key>
	<string>GM</string>
	<key>DTSDKBuild</key>
	<string>15C43</string>
	<key>DTSDKName</key>
	<string>macosx10.11</string>
	<key>DTXcode</key>
	<string>0721</string>
	<key>DTXcodeBuild</key>
	<string>7C1002</string>
</dict>
</plist>


================================================
FILE: Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>ADP2,1</key>
	<string>Developer Transition Kit</string>
	<key>iMac1,1</key>
	<string>iMac G3 (Rev A-D)</string>
	<key>iMac4,1</key>
	<string>iMac (Core Duo)</string>
	<key>iMac4,2</key>
	<string>iMac for Education (17 inch, Core Duo)</string>
	<key>iMac5,1</key>
	<string>iMac (Core 2 Duo, 17 or 20 inch, SuperDrive)</string>
	<key>iMac5,2</key>
	<string>iMac (Core 2 Duo, 17 inch, Combo Drive)</string>
	<key>iMac6,1</key>
	<string>iMac (Core 2 Duo, 24 inch, SuperDrive)</string>
	<key>iMac7,1</key>
	<string>iMac Intel Core 2 Duo (aluminum enclosure)</string>
	<key>iMac8,1</key>
	<string>iMac (Core 2 Duo, 20 or 24 inch, Early 2008 )</string>
	<key>iMac9,1</key>
	<string>iMac (Core 2 Duo, 20 or 24 inch, Early or Mid 2009 )</string>
	<key>iMac10,1</key>
	<string>iMac (Core 2 Duo, 21.5 or 27 inch, Late 2009 )</string>
	<key>iMac11,1</key>
	<string>iMac (Core i5 or i7, 27 inch Late 2009)</string>
	<key>iMac11,2</key>
	<string>21.5&quot; iMac (mid 2010)</string>
	<key>iMac11,3</key>
	<string>iMac (Core i5 or i7, 27 inch Mid 2010)</string>
	<key>iMac12,1</key>
	<string>iMac (Core i3 or i5 or i7, 21.5 inch Mid 2010 or Late 2011)</string>
	<key>iMac12,2</key>
	<string>iMac (Core i5 or i7, 27 inch Mid 2011)</string>
	<key>iMac13,1</key>
	<string>iMac (Core i3 or i5 or i7, 21.5 inch Late 2012 or Early 2013)</string>
	<key>iMac13,2</key>
	<string>iMac (Core i5 or i7, 27 inch Late 2012)</string>
	<key>iMac14,1</key>
	<string>iMac (Core i5, 21.5 inch Late 2013)</string>
	<key>iMac14,2</key>
	<string>iMac (Core i5 or i7, 27 inch Late 2013)</string>
	<key>iMac14,3</key>
	<string>iMac (Core i5 or i7, 21.5 inch Late 2013)</string>
	<key>iMac14,4</key>
	<string>iMac (Core i5, 21.5 inch Mid 2014)</string>
	<key>iMac15,1</key>
	<string>iMac (Retina 5K Core i5 or i7, 27 inch Late 2014 or Mid 2015)</string>
	<key>iMac16,1</key>
	<string>iMac (Core i5, 21,5 inch Late 2015)</string>
	<key>iMac16,2</key>
	<string>iMac (Retina 4K Core i5 or i7, 21.5 inch Late 2015)</string>
	<key>iMac17,1</key>
	<string>iMac (Retina 5K Core i5 or i7, 27 inch Late 2015)</string>
	<key>MacBook1,1</key>
	<string>MacBook (Core Duo)</string>
	<key>MacBook2,1</key>
	<string>MacBook (Core 2 Duo)</string>
	<key>MacBook4,1</key>
	<string>MacBook (Core 2 Duo Feb 2008)</string>
	<key>MacBook5,1</key>
	<string>MacBook (Core 2 Duo, Late 2008, Unibody)</string>
	<key>MacBook5,2</key>
	<string>MacBook (Core 2 Duo, Early 2009, White)</string>
	<key>MacBook6,1</key>
	<string>MacBook (Core 2 Duo, Late 2009, Unibody)</string>
	<key>MacBook7,1</key>
	<string>MacBook (Core 2 Duo, Mid 2010, White)</string>
	<key>MacBook8,1</key>
	<string>MacBook (Core M, 12 inch, Early 2015)</string>
	<key>MacBookAir1,1</key>
	<string>MacBook Air (Core 2 Duo, 13 inch, Early 2008)</string>
	<key>MacBookAir2,1</key>
	<string>MacBook Air (Core 2 Duo, 13 inch, Mid 2009)</string>
	<key>MacBookAir3,1</key>
	<string>MacBook Air (Core 2 Duo, 11 inch, Late 2010)</string>
	<key>MacBookAir3,2</key>
	<string>MacBook Air (Core 2 Duo, 13 inch, Late 2010)</string>
	<key>MacBookAir4,1</key>
	<string>MacBook Air (Core i5 or i7, 11 inch, Mid 2011)</string>
	<key>MacBookAir4,2</key>
	<string>MacBook Air (Core i5 or i7, 13 inch, Mid 2011)</string>
	<key>MacBookAir5,1</key>
	<string>MacBook Air (Core i5 or i7, 11 inch, Mid 2012)</string>
	<key>MacBookAir5,2</key>
	<string>MacBook Air (Core i5 or i7, 13 inch, Mid 2012)</string>
	<key>MacBookAir6,1</key>
	<string>MacBook Air (Core i5 or i7, 11 inch, Mid 2013 or Early 2014)</string>
	<key>MacBookAir6,2</key>
	<string>MacBook Air (Core i5 or i7, 13 inch, Mid 2013 or Early 2014)</string>
	<key>MacBookAir7,1</key>
	<string>MacBook Air (Core i5 or i7, 11 inch, Early 2015)</string>
	<key>MacBookAir7,2</key>
	<string>MacBook Air (Core i5 or i7, 13 inch, Early 2015)</string>
	<key>MacBookPro1,1</key>
	<string>MacBook Pro Core Duo (15-inch)</string>
	<key>MacBookPro1,2</key>
	<string>MacBook Pro Core Duo (17-inch)</string>
	<key>MacBookPro2,1</key>
	<string>MacBook Pro Core 2 Duo (17-inch)</string>
	<key>MacBookPro2,2</key>
	<string>MacBook Pro Core 2 Duo (15-inch)</string>
	<key>MacBookPro3,1</key>
	<string>MacBook Pro Core 2 Duo (15-inch LED, Core 2 Duo)</string>
	<key>MacBookPro3,2</key>
	<string>MacBook Pro Core 2 Duo (17-inch HD, Core 2 Duo)</string>
	<key>MacBookPro4,1</key>
	<string>MacBook Pro (Core 2 Duo Feb 2008)</string>
	<key>MacBookPro5,1</key>
	<string>MacBook Pro Intel Core 2 Duo (aluminum unibody)</string>
	<key>MacBookPro5,2</key>
	<string>MacBook Pro Intel Core 2 Duo (aluminum unibody)</string>
	<key>MacBookPro5,3</key>
	<string>MacBook Pro Intel Core 2 Duo (aluminum unibody)</string>
	<key>MacBookPro5,4</key>
	<string>MacBook Pro Intel Core 2 Duo (aluminum unibody)</string>
	<key>MacBookPro5,5</key>
	<string>MacBook Pro Intel Core 2 Duo (aluminum unibody)</string>
	<key>MacBookPro6,1</key>
	<string>MacBook Pro Intel Core i5, Intel Core i7 (mid 2010)</string>
	<key>MacBookPro6,2</key>
	<string>MacBook Pro Intel Core i5, Intel Core i7 (mid 2010)</string>
	<key>MacBookPro7,1</key>
	<string>MacBook Pro Intel Core 2 Duo (mid 2010)</string>
	<key>MacBookPro8,1</key>
	<string>MacBook Pro Intel Core i5, Intel Core i7, 13&quot; (early 2011)</string>
	<key>MacBookPro8,2</key>
	<string>MacBook Pro Intel Core i7, 15&quot; (early 2011)</string>
	<key>MacBookPro8,3</key>
	<string>MacBook Pro Intel Core i7, 17&quot; (early 2011)</string>
	<key>MacBookPro9,1</key>
	<string>MacBook Pro (15-inch, Mid 2012)</string>
	<key>MacBookPro9,2</key>
	<string>MacBook Pro (13-inch, Mid 2012)</string>
	<key>MacBookPro10,1</key>
	<string>MacBook Pro (Retina, Mid 2012)</string>
	<key>MacBookPro10,2</key>
	<string>MacBook Pro (Retina, 13-inch, Late 2012)</string>
	<key>MacBookPro11,1</key>
	<string>MacBook Pro (Retina, 13-inch, Late 2013)</string>
	<key>MacBookPro11,2</key>
	<string>MacBook Pro (Retina, 15-inch, Late 2013)</string>
	<key>MacBookPro11,3</key>
	<string>MacBook Pro (Retina, 15-inch, Late 2013)</string>
	<key>MacbookPro11,4</key>
	<string>MacBook Pro (Retina, 15-inch, Mid 2015)</string>
	<key>MacbookPro11,5</key>
	<string>MacBook Pro (Retina, 15-inch, Mid 2015)</string>
	<key>MacbookPro12,1 </key>
	<string>MacBook Pro (Retina, 13-inch, Early 2015)</string>
	<key>Macmini1,1</key>
	<string>Mac Mini (Core Solo/Duo)</string>
	<key>Macmini2,1</key>
	<string>Mac mini Intel Core</string>
	<key>Macmini3,1</key>
	<string>Mac mini Intel Core</string>
	<key>Macmini4,1</key>
	<string>Mac mini Intel Core (Mid 2010)</string>
	<key>Macmini5,1</key>
	<string>Mac mini (Core i5, Mid 2011)</string>
	<key>Macmini5,2</key>
	<string>Mac mini (Core i5 or Core i7, Mid 2011)</string>
	<key>Macmini5,3</key>
	<string>Mac mini (Core i7, Server, Mid 2011)</string>
	<key>Macmini6,1</key>
	<string>Mac mini (Core i5, Late 2012)</string>
	<key>Macmini6,2</key>
	<string>Mac mini (Core i7, Normal or Server, Late 2012)</string>
	<key>Macmini7,1</key>
	<string>Mac mini (Core i5 or Core i7, Late 2014)</string>
	<key>MacPro1,1,Quad</key>
	<string>Mac Pro</string>
	<key>MacPro1,1</key>
	<string>Mac Pro (four-core)</string>
	<key>MacPro2,1</key>
	<string>Mac Pro (eight-core)</string>
	<key>MacPro3,1</key>
	<string>Mac Pro (January 2008 4- or 8- core &quot;Harpertown&quot;)</string>
	<key>MacPro4,1</key>
	<string>Mac Pro (March 2009)</string>
	<key>MacPro5,1</key>
	<string>Mac Pro (2010 or 2012)</string>
	<key>MacPro6,1</key>
	<string>Mac Pro (Late 2013)</string>
	<key>PowerBook1,1</key>
	<string>PowerBook G3</string>
	<key>PowerBook2,1</key>
	<string>iBook G3</string>
	<key>PowerBook2,2</key>
	<string>iBook G3 (FireWire)</string>
	<key>PowerBook2,3</key>
	<string>iBook G3</string>
	<key>PowerBook2,4</key>
	<string>iBook G3</string>
	<key>PowerBook3,1</key>
	<string>PowerBook G3 (FireWire)</string>
	<key>PowerBook3,2</key>
	<string>PowerBook G4</string>
	<key>PowerBook3,3</key>
	<string>PowerBook G4 (Gigabit Ethernet)</string>
	<key>PowerBook3,4</key>
	<string>PowerBook G4 (DVI)</string>
	<key>PowerBook3,5</key>
	<string>PowerBook G4 (1GHz / 867MHz)</string>
	<key>PowerBook4,1</key>
	<string>iBook G3 (Dual USB, Late 2001)</string>
	<key>PowerBook4,2</key>
	<string>iBook G3 (16MB VRAM)</string>
	<key>PowerBook4,3</key>
	<string>iBook G3 Opaque 16MB VRAM, 32MB VRAM, Early 2003)</string>
	<key>PowerBook5,1</key>
	<string>PowerBook G4 (17 inch)</string>
	<key>PowerBook5,2</key>
	<string>PowerBook G4 (15 inch FW 800)</string>
	<key>PowerBook5,3</key>
	<string>PowerBook G4 (17-inch 1.33GHz)</string>
	<key>PowerBook5,4</key>
	<string>PowerBook G4 (15 inch 1.5/1.33GHz)</string>
	<key>PowerBook5,5</key>
	<string>PowerBook G4 (17-inch 1.5GHz)</string>
	<key>PowerBook5,6</key>
	<string>PowerBook G4 (15 inch 1.67GHz/1.5GHz)</string>
	<key>PowerBook5,7</key>
	<string>PowerBook G4 (17-inch 1.67GHz)</string>
	<key>PowerBook5,8</key>
	<string>PowerBook G4 (Double layer SD, 15 inch)</string>
	<key>PowerBook5,9</key>
	<string>PowerBook G4 (Double layer SD, 17 inch)</string>
	<key>PowerBook6,1</key>
	<string>PowerBook G4 (12 inch)</string>
	<key>PowerBook6,2</key>
	<string>PowerBook G4 (12 inch, DVI)</string>
	<key>PowerBook6,3</key>
	<string>iBook G4</string>
	<key>PowerBook6,4</key>
	<string>PowerBook G4 (12 inch 1.33GHz)</string>
	<key>PowerBook6,5</key>
	<string>iBook G4 (Early-Late 2004)</string>
	<key>PowerBook6,7</key>
	<string>iBook G4 (Mid 2005)</string>
	<key>PowerBook6,8</key>
	<string>PowerBook G4 (12 inch 1.5GHz)</string>
	<key>PowerMac1,1</key>
	<string>Power Macintosh G3 (Blue &amp; White)</string>
	<key>PowerMac1,2</key>
	<string>Power Macintosh G4 (PCI Graphics)</string>
	<key>PowerMac2,1</key>
	<string>iMac G3 (Slot-loading CD-ROM)</string>
	<key>PowerMac2,2</key>
	<string>iMac G3 (Summer 2000)</string>
	<key>PowerMac3,1</key>
	<string>Power Macintosh G4 (AGP Graphics)</string>
	<key>PowerMac3,2</key>
	<string>Power Macintosh G4 (AGP Graphics)</string>
	<key>PowerMac3,3</key>
	<string>Power Macintosh G4 (Gigabit Ethernet)</string>
	<key>PowerMac3,4</key>
	<string>Power Macintosh G4 (Digital Audio)</string>
	<key>PowerMac3,5</key>
	<string>Power Macintosh G4 (Quick Silver)</string>
	<key>PowerMac3,6</key>
	<string>Power Macintosh G4 (Mirrored Drive Door)</string>
	<key>PowerMac4,1</key>
	<string>iMac G3 (Early/Summer 2001)</string>
	<key>PowerMac4,2</key>
	<string>iMac G4 (Flat Panel)</string>
	<key>PowerMac4,4</key>
	<string>eMac</string>
	<key>PowerMac4,5</key>
	<string>iMac G4 (17-inch Flat Panel)</string>
	<key>PowerMac5,1</key>
	<string>Power Macintosh G4 Cube</string>
	<key>PowerMac5,2</key>
	<string>Power Mac G4 Cube</string>
	<key>PowerMac6,1</key>
	<string>iMac G4 (USB 2.0)</string>
	<key>PowerMac6,3</key>
	<string>iMac G4 (20-inch Flat Panel)</string>
	<key>PowerMac6,4</key>
	<string>eMac (USB 2.0, 2005)</string>
	<key>PowerMac7,2</key>
	<string>Power Macintosh G5</string>
	<key>PowerMac7,3</key>
	<string>Power Macintosh G5</string>
	<key>PowerMac8,1</key>
	<string>iMac G5</string>
	<key>PowerMac8,2</key>
	<string>iMac G5 (Ambient Light Sensor)</string>
	<key>PowerMac9,1</key>
	<string>Power Macintosh G5 (Late 2005)</string>
	<key>PowerMac10,1</key>
	<string>Mac Mini G4</string>
	<key>PowerMac10,2</key>
	<string>Mac Mini (Late 2005)</string>
	<key>PowerMac11,2</key>
	<string>Power Macintosh G5 (Late 2005)</string>
	<key>PowerMac12,1</key>
	<string>iMac G5 (iSight)</string>
	<key>RackMac1,1</key>
	<string>Xserve G4</string>
	<key>RackMac1,2</key>
	<string>Xserve G4 (slot-loading, cluster node)</string>
	<key>RackMac3,1</key>
	<string>Xserve G5</string>
	<key>Xserve1,1</key>
	<string>Xserve (Intel Xeon)</string>
	<key>Xserve2,1</key>
	<string>Xserve (January 2008 quad-core)</string>
	<key>Xserve3,1</key>
	<string>Xserve (early 2009)</string>
</dict>
</plist>


================================================
FILE: TodoTxtMac/Base.lproj/MainMenu.xib
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
    <dependencies>
        <deployment identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="NSApplication"/>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application" customClass="NSObject">
            <connections>
                <outlet property="delegate" destination="lsB-8n-fAQ" id="u6u-dm-tYl"/>
            </connections>
        </customObject>
        <menu title="AMainMenu" systemMenu="main" id="29">
            <items>
                <menuItem title="TodoTxtMac" id="56">
                    <menu key="submenu" title="TodoTxtMac" systemMenu="apple" id="57">
                        <items>
                            <menuItem title="About TodoTxtMac" id="58">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Check for Updates..." id="xc3-uB-1hs">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="checkForUpdates:" target="565-dx-Ism" id="J12-bH-I7r"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="236">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Preferences…" keyEquivalent="," id="129">
                                <connections>
                                    <action selector="openPreferencesWindow:" target="7QU-ZR-XSK" id="6wW-fR-gGb"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="143">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Services" id="131">
                                <menu key="submenu" title="Services" systemMenu="services" id="130"/>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="144">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Hide TodoTxtMac" keyEquivalent="h" id="134">
                                <connections>
                                    <action selector="hide:" target="-1" id="367"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Hide Others" keyEquivalent="h" id="145">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="hideOtherApplications:" target="-1" id="368"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Show All" id="150">
                                <connections>
                                    <action selector="unhideAllApplications:" target="-1" id="370"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="149">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Quit TodoTxtMac" keyEquivalent="q" id="136">
                                <connections>
                                    <action selector="terminate:" target="-3" id="448"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="File" id="TdN-Dv-raJ">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="File" id="INu-wF-cUM">
                        <items>
                            <menuItem title="New" keyEquivalent="n" id="g3T-7j-OsP">
                                <connections>
                                    <action selector="newDocument:" target="-1" id="YhP-J5-FbS"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Open…" keyEquivalent="o" id="0Rb-22-wxm">
                                <connections>
                                    <action selector="openDocument:" target="-1" id="HlJ-9k-4FJ"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Open Recent" id="2hD-cz-gXK">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <menu key="submenu" title="Open Recent" systemMenu="recentDocuments" id="6YB-e5-wOI">
                                    <items>
                                        <menuItem title="Clear Menu" id="tIp-4p-jWS">
                                            <connections>
                                                <action selector="clearRecentDocuments:" target="-1" id="8HD-YM-8bP"/>
                                            </connections>
                                        </menuItem>
                                    </items>
                                </menu>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="d8H-fy-eaD"/>
                            <menuItem title="Close" keyEquivalent="w" id="Kcg-cx-ph1">
                                <connections>
                                    <action selector="performClose:" target="-1" id="BB2-Dp-6xc"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Close All" alternate="YES" keyEquivalent="w" id="Z9J-7O-Bas">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="closeAllWindows:" target="7QU-ZR-XSK" id="Ebz-IH-BZ1"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Save" keyEquivalent="s" id="IJj-uK-2iI">
                                <connections>
                                    <action selector="saveDocument:" target="-1" id="hkA-hA-5PU"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Save As…" keyEquivalent="S" id="Vbg-yR-v7K">
                                <connections>
                                    <action selector="saveDocumentAs:" target="-1" id="9fY-86-pQP"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Revert to Saved" id="6AX-Xe-5PC">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="revertDocumentToSaved:" target="-1" id="Zgp-ln-mz5"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="f5H-JZ-syD"/>
                            <menuItem title="Get Info (Metadata)" keyEquivalent="i" id="hel-oa-j2F">
                                <connections>
                                    <action selector="showTasklistMetadata:" target="-1" id="e0z-7y-0CN"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="9Ex-lN-cax"/>
                            <menuItem title="Reload" keyEquivalent="." id="Ntd-2t-4s5">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="reloadFile:" target="-1" id="bcz-EK-Zbg"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Reload All" alternate="YES" keyEquivalent="." id="Q6W-AH-Whq">
                                <modifierMask key="keyEquivalentModifierMask" option="YES"/>
                                <connections>
                                    <action selector="reloadAll:" target="7QU-ZR-XSK" id="2NE-Np-SLF"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Archive Completed Tasks" keyEquivalent="a" id="Kkd-iR-JVT">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="archiveCompletedTasks:" target="-1" id="yya-aD-oKe"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Edit" id="217">
                    <menu key="submenu" title="Edit" id="205">
                        <items>
                            <menuItem title="Undo" keyEquivalent="z" id="207">
                                <connections>
                                    <action selector="undo:" target="-1" id="223"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Redo" keyEquivalent="Z" id="215">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
                                <connections>
                                    <action selector="redo:" target="-1" id="231"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="206">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Cut" keyEquivalent="x" id="199">
                                <connections>
                                    <action selector="cut:" target="-1" id="228"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Copy" keyEquivalent="c" id="197">
                                <connections>
                                    <action selector="copy:" target="-1" id="224"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Copy Task to New Task" tag="7000" keyEquivalent="C" id="aGg-gt-UIO">
                                <connections>
                                    <action selector="copyTaskToNewTask:" target="-1" id="X2j-OZ-tBd"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Paste" keyEquivalent="v" id="203">
                                <connections>
                                    <action selector="paste:" target="-1" id="226"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Delete" hidden="YES" id="202">
                                <connections>
                                    <action selector="delete:" target="-1" id="235"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Select All" keyEquivalent="a" id="198">
                                <connections>
                                    <action selector="selectAll:" target="-1" id="232"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="doJ-np-pVi"/>
                            <menuItem title="Find" keyEquivalent="f" id="p6f-pv-EES">
                                <connections>
                                    <action selector="moveFocusToSearchBox:" target="-1" id="O41-7n-bnw"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Replace..." keyEquivalent="f" id="i9O-dp-SXT">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="replaceText:" target="-1" id="Hqx-1H-7KY"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Task" tag="3000" id="uCE-zB-agW">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Task" id="MoX-cC-Tbw">
                        <items>
                            <menuItem title="Add New Task" keyEquivalent="n" id="Z4D-Og-fXr">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="moveFocusToNewTaskTextField:" target="-1" id="897-Hc-KbJ"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Update" keyEquivalent="u" id="HxV-pn-JsT">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="updateSelectedTask:" target="-1" id="IH9-bZ-S6A"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Update Selected Task" hidden="YES" id="3i7-Ag-Atr">
                                <string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="updateSelectedTask:" target="-1" id="qJ6-ER-cbj"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Append Text" keyEquivalent="t" id="XTM-iP-85t">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="appendText:" target="-1" id="p5w-qa-iTB"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Prepend Text" keyEquivalent="r" id="N06-zv-uJi">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="prependText:" target="-1" id="Uvh-d3-wu5"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Delete" id="ezd-Y3-tV6">
                                <string key="keyEquivalent" base64-UTF8="YES">
CA
</string>
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="deleteSelectedTasks:" target="-1" id="P5W-AN-0tj"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Delete" hidden="YES" keyEquivalent="d" id="XcZ-V8-VXC">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="deleteSelectedTasks:" target="-1" id="11H-aK-AV3"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="vRD-AB-8sn"/>
                            <menuItem title="Toggle Completion" keyEquivalent="x" id="fGU-nC-gCi">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="toggleTaskCompletion:" target="-1" id="BkD-oH-dPy"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="teR-zl-kPy"/>
                            <menuItem title="Set Priority" keyEquivalent="i" id="xfO-3k-ZLi">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="setPriority:" target="-1" id="akj-aP-Kcg"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Increase Priority" keyEquivalent="" id="6js-VE-fon">
                                <connections>
                                    <action selector="increasePriority:" target="-1" id="wrI-DZ-VMH"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Decrease Priority" keyEquivalent="" id="j3w-FD-cEd">
                                <connections>
                                    <action selector="decreasePriority:" target="-1" id="rDF-Il-y56"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Remove Priority" keyEquivalent="" id="YWv-co-tds">
                                <connections>
                                    <action selector="removePriority:" target="-1" id="7g7-1h-4zM"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Remove Priority" hidden="YES" keyEquivalent="" id="7uc-lb-HaT">
                                <connections>
                                    <action selector="removePriority:" target="-1" id="922-am-W6H"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="rLe-sX-gaJ"/>
                            <menuItem title="Set Due Date" keyEquivalent="s" id="5fO-eP-YPw">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="setDueDate:" target="-1" id="7gK-A2-NsC"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Postpone" keyEquivalent="p" id="qhJ-ab-gOR">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="postpone:" target="-1" id="OEw-8l-YCH"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Increase Due Date By 1 Day" keyEquivalent="" id="VKT-bC-Sfo">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="increaseDueDateByOneDay:" target="-1" id="TY7-yn-JPo"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Decrease Due Date By 1 Day" keyEquivalent="" id="8X0-Ni-xRD">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="decreaseDueDateByOneDay:" target="-1" id="Qma-Th-G2K"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Remove Due Date" keyEquivalent="" id="lg0-ah-E37">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="removeDueDate:" target="-1" id="iCm-Nj-JHk"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Remove Due Date" hidden="YES" keyEquivalent="" id="rfK-9O-xPV">
                                <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                                <connections>
                                    <action selector="removeDueDate:" target="-1" id="auI-HN-cQk"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="rXL-8W-w5S"/>
                            <menuItem title="Set Threshold Date" keyEquivalent="s" id="l4o-09-m07">
                                <modifierMask key="keyEquivalentModifierMask" option="YES"/>
                                <connections>
                                    <action selector="setThresholdDate:" target="-1" id="Ugf-Kp-aQg"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Increase Threshold Date By 1 Day" keyEquivalent="" id="298-EH-Uic">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" option="YES" command="YES"/>
                                <connections>
                                    <action selector="increaseThresholdDateByOneDay:" target="-1" id="a5v-Bs-UWe"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Decrease Treshold Date By 1 Day" keyEquivalent="" id="Chu-wi-rII">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" option="YES" command="YES"/>
                                <connections>
                                    <action selector="decreaseThresholdDateByOneDay:" target="-1" id="n8g-S3-3Kb"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Remove Threshold Date" keyEquivalent="" id="6Iu-dJ-mki">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" option="YES" command="YES"/>
                                <connections>
                                    <action selector="removeThresholdDate:" target="-1" id="JAn-de-tBw"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Remove Threshold Date" hidden="YES" keyEquivalent="" id="wxr-lt-ibv">
                                <modifierMask key="keyEquivalentModifierMask" shift="YES" option="YES" command="YES"/>
                                <connections>
                                    <action selector="removeThresholdDate:" target="-1" id="Dd9-oI-0iG"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Sort" tag="4000" id="zaw-Cf-1uQ">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Sort" id="Oh9-df-kdx">
                        <items>
                            <menuItem title="Order In File" keyEquivalent="0" id="uAq-fh-i5h">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="NUv-TU-Reb"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="XrW-8C-6ZT"/>
                            <menuItem title="Priority" tag="1" keyEquivalent="1" id="dQS-l3-d0y">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="tGs-B4-4sC"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Project" tag="2" keyEquivalent="2" id="SCn-7e-0Pw">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="Iet-Dd-5eW"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Context" tag="3" keyEquivalent="3" id="iev-Ie-urO">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="3LI-Hc-yyM"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Due Date" tag="4" keyEquivalent="4" id="hAN-bI-6Lj">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="y7Z-UD-a81"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Creation Date" tag="5" keyEquivalent="5" id="aTb-nI-t5a">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="Zqt-xH-KnX"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Completion Date" tag="6" keyEquivalent="6" id="Syc-Jy-VcH">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="YfC-gi-PwP"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Threshold Date" tag="7" keyEquivalent="7" id="7gp-lw-eUf">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="H9G-OO-d9P"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Alphabetical" tag="8" keyEquivalent="8" id="ts8-6t-CtK">
                                <connections>
                                    <action selector="sortTaskListUsingTagforPreset:" target="-1" id="RCy-a1-sSA"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Filter" tag="5000" id="zFI-qf-XfA">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Filter" id="QFi-qB-Q0i">
                        <items>
                            <menuItem title="Define Filters" tag="-1" keyEquivalent="f" id="Tox-5H-i7g">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="openFiltersWindow:" target="7QU-ZR-XSK" id="Oqt-se-5Kr"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="vVy-kk-aGk"/>
                            <menuItem title="Remove Filter" keyEquivalent="0" id="f8L-Hj-7Fl">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="6Vs-wz-bSq"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="GOO-i2-vC0"/>
                            <menuItem title="Quick Filter 1" tag="1" keyEquivalent="1" id="26K-oV-RLQ">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="Dto-Hg-AuY"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Quick Filter 2" tag="2" keyEquivalent="2" id="jEv-9H-XhK">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="oMM-TT-WnO"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Quick Filter 3" tag="3" keyEquivalent="3" id="Bbf-lb-dWq">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="Qm9-Zx-Aqt"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Quick Filter 4" tag="4" keyEquivalent="4" id="z7P-iy-Jns">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="OdZ-xz-aGp"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Quick Filter 5" tag="5" keyEquivalent="5" id="ALm-yg-nEh">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="KPt-p6-4qJ"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Quick Filter 6" tag="6" keyEquivalent="6" id="8It-YB-3jc">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="zhf-GB-kSX"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Quick Filter 7" tag="7" keyEquivalent="7" id="RPL-WC-b0f">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="KKc-GA-5e7"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Quick Filter 8" tag="8" keyEquivalent="8" id="em5-Zj-zX8">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="pSy-0T-8Bx"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Quick Filter 9" tag="9" keyEquivalent="9" id="kWx-h9-xo5">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="filterTaskListUsingTagforPreset:" target="-1" id="X4G-QF-Z3g"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="View" id="295">
                    <menu key="submenu" title="View" id="296">
                        <items>
                            <menuItem title="Show Status Bar" tag="6000" keyEquivalent="/" id="4lx-6A-S2z">
                                <connections>
                                    <action selector="toggleStatusBarVisability:" target="-1" id="AWn-Xq-tHt"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Window" id="19">
                    <menu key="submenu" title="Window" systemMenu="window" id="24">
                        <items>
                            <menuItem title="Minimize" keyEquivalent="m" id="23">
                                <connections>
                                    <action selector="performMiniaturize:" target="-1" id="37"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Zoom" id="239">
                                <connections>
                                    <action selector="performZoom:" target="-1" id="240"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="92">
                                <modifierMask key="keyEquivalentModifierMask" command="YES"/>
                            </menuItem>
                            <menuItem title="Bring All to Front" id="5">
                                <connections>
                                    <action selector="arrangeInFront:" target="-1" id="39"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
                <menuItem title="Help" id="491">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <menu key="submenu" title="Help" systemMenu="help" id="492">
                        <items>
                            <menuItem title="TodoTxtMac Help" keyEquivalent="?" id="493">
                                <connections>
                                    <action selector="showHelp:" target="-1" id="494"/>
                                </connections>
                            </menuItem>
                            <menuItem title="TodoTxtMac Web Site" id="II1-IX-RtO">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="openWebSite:" target="7QU-ZR-XSK" id="9Ag-Y1-CGm"/>
                                </connections>
                            </menuItem>
                            <menuItem isSeparatorItem="YES" id="lRU-6h-IH1"/>
                            <menuItem title="Plaintext Productivity Web Site" id="9hp-z8-KLG">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="openPlaintextProductivityWebSite:" target="7QU-ZR-XSK" id="ECP-z5-0Cu"/>
                                </connections>
                            </menuItem>
                            <menuItem title="Todo.txt Tips from Plaintext Productivity" id="MgF-xZ-I3A">
                                <modifierMask key="keyEquivalentModifierMask"/>
                                <connections>
                                    <action selector="openTodoTxtTipsPlaintextProductivityWebSite:" target="7QU-ZR-XSK" id="tYj-xu-zQ4"/>
                                </connections>
                            </menuItem>
                        </items>
                    </menu>
                </menuItem>
            </items>
        </menu>
        <customObject id="419" customClass="NSFontManager"/>
        <customObject id="7QU-ZR-XSK" customClass="TTMAppController"/>
        <customObject id="lsB-8n-fAQ" customClass="TTMAppDelegate">
            <connections>
                <outlet property="appController" destination="7QU-ZR-XSK" id="Jmb-5i-JMS"/>
            </connections>
        </customObject>
        <customObject id="565-dx-Ism" customClass="SUUpdater"/>
        <customObject id="oKW-8b-22O" customClass="NSDocumentController"/>
        <userDefaultsController representsSharedInstance="YES" id="w2u-Zb-wUd"/>
        <menuItem title="Item" id="m59-bi-F45">
            <modifierMask key="keyEquivalentModifierMask"/>
        </menuItem>
    </objects>
</document>


================================================
FILE: TodoTxtMac/Base.lproj/TTMDocument.xib
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
    <dependencies>
        <deployment identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
        <capability name="stacking Non-gravity area distributions on NSStackView" minToolsVersion="7.0" minSystemVersion="10.11"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="TTMDocument">
            <connections>
                <outlet property="arrayController" destination="z03-iY-Esn" id="WqA-XF-LYw"/>
                <outlet property="bottomConstraint" destination="yCu-XX-tWa" id="l0K-0j-yVC"/>
                <outlet property="rawTextCell" destination="B31-jc-X0I" id="WRb-Kc-eMO"/>
                <outlet property="searchField" destination="MtW-Mu-7ja" id="Kva-PL-Nec"/>
                <outlet property="statusBarTextField" destination="Sky-Qt-diC" id="SoO-R7-lpJ"/>
                <outlet property="tableView" destination="FD8-v3-r5U" id="pBH-dg-EN3"/>
                <outlet property="tableViewDelegate" destination="EHv-Hj-tOM" id="h3o-MM-3Ms"/>
                <outlet property="textField" destination="4SD-Qr-9gz" id="SxF-oC-RrR"/>
                <outlet property="window" destination="5" id="18"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" visibleAtLaunch="NO" frameAutosaveName="TTMDocument" animationBehavior="default" id="5" userLabel="Window">
            <windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" unifiedTitleAndToolbar="YES"/>
            <windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
            <windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
            <rect key="contentRect" x="133" y="235" width="510" height="447"/>
            <rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
            <value key="minSize" type="size" width="94" height="86"/>
            <view key="contentView" wantsLayer="YES" id="6">
                <rect key="frame" x="0.0" y="0.0" width="510" height="447"/>
                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                <subviews>
                    <stackView distribution="fill" orientation="vertical" alignment="leading" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="sn0-eP-Rdc">
                        <rect key="frame" x="0.0" y="22" width="510" height="425"/>
                        <subviews>
                            <scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="C1v-eN-hR0">
                                <rect key="frame" x="0.0" y="0.0" width="510" height="425"/>
                                <clipView key="contentView" id="5aa-vY-NrO">
                                    <rect key="frame" x="0.0" y="0.0" width="510" height="425"/>
                                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                    <subviews>
                                        <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" alternatingRowBackgroundColors="YES" columnReordering="NO" emptySelection="NO" autosaveColumns="NO" id="FD8-v3-r5U" customClass="TTMTableView">
                                            <rect key="frame" x="0.0" y="0.0" width="510" height="425"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <size key="intercellSpacing" width="3" height="2"/>
                                            <color key="backgroundColor" name="_sourceListBackgroundColor" catalog="System" colorSpace="catalog"/>
                                            <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
                                            <tableColumns>
                                                <tableColumn identifier="rawText" width="507" minWidth="100" maxWidth="10000" id="Psh-Gi-D1c">
                                                    <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border" alignment="left" title="rawText">
                                                        <font key="font" metaFont="smallSystem"/>
                                                        <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
                                                        <color key="backgroundColor" white="0.33333298560000002" alpha="1" colorSpace="calibratedWhite"/>
                                                    </tableHeaderCell>
                                                    <textFieldCell key="dataCell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" alignment="left" title="Text Cell" id="B31-jc-X0I">
                                                        <font key="font" metaFont="system"/>
                                                        <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                                    </textFieldCell>
                                                    <tableColumnResizingMask key="resizingMask" resizeWithTable="YES"/>
                                                    <connections>
                                                        <binding destination="z03-iY-Esn" name="value" keyPath="arrangedObjects.rawText" id="Lqe-ON-xdz"/>
                                                    </connections>
                                                </tableColumn>
                                            </tableColumns>
                                            <connections>
                                                <outlet property="delegate" destination="EHv-Hj-tOM" id="uvv-h2-wBm"/>
                                                <outlet property="menu" destination="oa5-ZA-h8N" id="3EN-Hs-f7b"/>
                                                <outlet property="parentDocument" destination="-2" id="rdR-3Y-03G"/>
                                            </connections>
                                        </tableView>
                                    </subviews>
                                </clipView>
                                <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="ciJ-RQ-uYU">
                                    <rect key="frame" x="1" y="411" width="509" height="16"/>
                                    <autoresizingMask key="autoresizingMask"/>
                                </scroller>
                                <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="hIl-mE-RGE">
                                    <rect key="frame" x="494" y="1" width="15" height="0.0"/>
                                    <autoresizingMask key="autoresizingMask"/>
                                </scroller>
                            </scrollView>
                        </subviews>
                        <visibilityPriorities>
                            <integer value="1000"/>
                        </visibilityPriorities>
                        <customSpacing>
                            <real value="3.4028234663852886e+38"/>
                        </customSpacing>
                    </stackView>
                    <textField horizontalCompressionResistancePriority="1" translatesAutoresizingMaskIntoConstraints="NO" id="Sky-Qt-diC">
                        <rect key="frame" x="3" y="2" width="504" height="16"/>
                        <constraints>
                            <constraint firstAttribute="height" constant="16" id="NXt-rJ-2VE"/>
                        </constraints>
                        <textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Label" id="ZsD-0k-HPu">
                            <font key="font" metaFont="smallSystem"/>
                            <color key="textColor" name="disabledControlTextColor" catalog="System" colorSpace="catalog"/>
                            <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                            <connections>
                                <binding destination="-2" name="value" keyPath="self.statusBarText" id="m6H-KR-ctN"/>
                            </connections>
                        </textFieldCell>
                    </textField>
                </subviews>
                <constraints>
                    <constraint firstItem="sn0-eP-Rdc" firstAttribute="top" secondItem="6" secondAttribute="top" id="7c9-c9-eZ7"/>
                    <constraint firstItem="Sky-Qt-diC" firstAttribute="leading" secondItem="6" secondAttribute="leading" constant="5" id="brB-pD-hAb"/>
                    <constraint firstAttribute="trailing" secondItem="Sky-Qt-diC" secondAttribute="trailing" constant="5" id="j1w-Kd-0vp"/>
                    <constraint firstAttribute="bottom" secondItem="Sky-Qt-diC" secondAttribute="bottom" constant="2" id="jJO-2M-jzG"/>
                    <constraint firstAttribute="trailing" secondItem="C1v-eN-hR0" secondAttribute="trailing" id="oC8-pX-hMQ"/>
                    <constraint firstItem="C1v-eN-hR0" firstAttribute="leading" secondItem="6" secondAttribute="leading" id="wJj-wx-1bd"/>
                    <constraint firstAttribute="bottom" secondItem="sn0-eP-Rdc" secondAttribute="bottom" constant="22" id="yCu-XX-tWa"/>
                </constraints>
            </view>
            <toolbar key="toolbar" implicitIdentifier="4D4220C3-9B1C-441F-94D1-1A7D910A2AB0" allowsUserCustomization="NO" displayMode="iconOnly" sizeMode="small" id="Tbe-3z-Gsw">
                <allowedToolbarItems>
                    <toolbarItem implicitItemIdentifier="120A55A2-2D6F-4D5D-B771-5160A368118F" label="New Task" paletteLabel="New Task" visibilityPriority="100" id="B1S-jN-Ztr">
                        <nil key="toolTip"/>
                        <size key="minSize" width="96" height="22"/>
                        <size key="maxSize" width="100000" height="22"/>
                        <textField key="view" horizontalHuggingPriority="750" verticalHuggingPriority="750" id="4SD-Qr-9gz">
                            <rect key="frame" x="0.0" y="14" width="400" height="22"/>
                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                            <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" state="on" borderStyle="bezel" placeholderString="New task..." drawsBackground="YES" usesSingleLineMode="YES" id="Zzr-Le-XIh">
                                <font key="font" metaFont="system"/>
                                <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                            </textFieldCell>
                            <connections>
                                <action selector="addNewTask:" target="-2" id="y7y-5H-mBy"/>
                            </connections>
                        </textField>
                    </toolbarItem>
                    <toolbarItem implicitItemIdentifier="B4880FAB-0558-4D02-A666-EB071DE8A773" label="Search" paletteLabel="Search" visibilityPriority="100" id="a5W-c1-Nr2">
                        <nil key="toolTip"/>
                        <size key="minSize" width="96" height="22"/>
                        <size key="maxSize" width="140" height="22"/>
                        <searchField key="view" wantsLayer="YES" horizontalHuggingPriority="750" verticalHuggingPriority="750" id="MtW-Mu-7ja">
                            <rect key="frame" x="0.0" y="14" width="96" height="22"/>
                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                            <searchFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" refusesFirstResponder="YES" borderStyle="bezel" usesSingleLineMode="YES" bezelStyle="round" sendsSearchStringImmediately="YES" id="iTq-XW-8IB">
                                <font key="font" metaFont="system"/>
                                <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                            </searchFieldCell>
                            <connections>
                                <binding destination="-2" name="predicate" keyPath="self.searchFieldPredicate" id="GIK-On-p5m">
                                    <dictionary key="options">
                                        <string key="NSDisplayName">predicate</string>
                                        <string key="NSPredicateFormat">rawText contains[cd] $value</string>
                                    </dictionary>
                                </binding>
                            </connections>
                        </searchField>
                    </toolbarItem>
                </allowedToolbarItems>
                <defaultToolbarItems>
                    <toolbarItem reference="B1S-jN-Ztr"/>
                    <toolbarItem reference="a5W-c1-Nr2"/>
                </defaultToolbarItems>
            </toolbar>
            <contentBorderThickness minY="22"/>
            <connections>
                <outlet property="delegate" destination="-2" id="17"/>
            </connections>
        </window>
        <arrayController objectClassName="TTMTask" automaticallyRearrangesObjects="YES" id="z03-iY-Esn">
            <connections>
                <binding destination="-2" name="filterPredicate" keyPath="self.activeFilterPredicate" id="sjF-mO-jcs"/>
                <binding destination="-2" name="contentArray" keyPath="self.taskList" id="6bb-CW-xta"/>
            </connections>
        </arrayController>
        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
        <userDefaultsController representsSharedInstance="YES" id="ZDT-kG-QuA"/>
        <customObject id="EHv-Hj-tOM" customClass="TTMTableViewDelegate">
            <connections>
                <outlet property="arrayController" destination="z03-iY-Esn" id="bZW-B4-fSs"/>
            </connections>
        </customObject>
        <menu id="oa5-ZA-h8N">
            <items>
                <menuItem title="Add New Task" keyEquivalent="n" id="DaS-lw-tom">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="moveFocusToNewTaskTextField:" target="-1" id="P8g-Sf-ymP"/>
                    </connections>
                </menuItem>
                <menuItem title="Update" keyEquivalent="u" id="b76-Yn-FZw">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="updateSelectedTask:" target="-1" id="b1F-HN-zIR"/>
                    </connections>
                </menuItem>
                <menuItem title="Append Text" keyEquivalent="t" id="JCe-h2-3R5">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="appendText:" target="-1" id="70n-av-wTX"/>
                    </connections>
                </menuItem>
                <menuItem title="Prepend Text" keyEquivalent="r" id="XdX-J7-z0X">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="prependText:" target="-1" id="E4e-Qe-cDu"/>
                    </connections>
                </menuItem>
                <menuItem title="Delete" hidden="YES" keyEquivalent="d" id="c4f-YX-vjt">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="deleteSelectedTasks:" target="-1" id="c2H-zi-BHD"/>
                    </connections>
                </menuItem>
                <menuItem title="Delete" id="I9O-Bd-cNZ">
                    <string key="keyEquivalent" base64-UTF8="YES">
CA
</string>
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="deleteSelectedTasks:" target="-1" id="yvS-0a-hYS"/>
                    </connections>
                </menuItem>
                <menuItem isSeparatorItem="YES" id="xGk-rN-DCC"/>
                <menuItem title="Toggle Completion" keyEquivalent="x" id="N2B-it-TGO">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="toggleTaskCompletion:" target="-1" id="EJy-Uz-slU"/>
                    </connections>
                </menuItem>
                <menuItem isSeparatorItem="YES" id="ezm-BQ-bR2"/>
                <menuItem title="Set Priority" keyEquivalent="i" id="dnL-GF-ydk">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="setPriority:" target="-1" id="ruw-d8-hfs"/>
                    </connections>
                </menuItem>
                <menuItem title="Increase Priority" keyEquivalent="" id="7aA-PZ-bXA">
                    <connections>
                        <action selector="increasePriority:" target="-1" id="7de-cW-CqL"/>
                    </connections>
                </menuItem>
                <menuItem title="Decrease Priority" keyEquivalent="" id="bcL-Nb-Dox">
                    <connections>
                        <action selector="decreasePriority:" target="-1" id="BIK-5W-D4O"/>
                    </connections>
                </menuItem>
                <menuItem title="Remove Priority" keyEquivalent="" id="cCl-gJ-Ezx">
                    <connections>
                        <action selector="removePriority:" target="-1" id="lk4-kv-MSF"/>
                    </connections>
                </menuItem>
                <menuItem title="Remove Priority" hidden="YES" keyEquivalent="" id="gZs-7t-faP">
                    <connections>
                        <action selector="removePriority:" target="-1" id="Y0W-ql-vLx"/>
                    </connections>
                </menuItem>
                <menuItem isSeparatorItem="YES" id="8H5-zH-hDj"/>
                <menuItem title="Set Due Date" keyEquivalent="s" id="bAk-TR-UnI">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="setDueDate:" target="-1" id="Uon-ah-Duc"/>
                    </connections>
                </menuItem>
                <menuItem title="Postpone" keyEquivalent="p" id="WnK-Q7-CZy">
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="postpone:" target="-1" id="g12-14-v1p"/>
                    </connections>
                </menuItem>
                <menuItem title="Increase Due Date By 1 Day" keyEquivalent="" id="fw1-ni-PD5">
                    <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                    <connections>
                        <action selector="increaseDueDateByOneDay:" target="-1" id="Kbh-Fs-EEa"/>
                    </connections>
                </menuItem>
                <menuItem title="Decrease Due Date By 1 Day" keyEquivalent="" id="QXa-wL-6lD">
                    <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                    <connections>
                        <action selector="decreaseDueDateByOneDay:" target="-1" id="bJn-ip-371"/>
                    </connections>
                </menuItem>
                <menuItem title="Remove Due Date" keyEquivalent="" id="yDV-Ow-fu4">
                    <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                    <connections>
                        <action selector="removeDueDate:" target="-1" id="R6v-Z2-D81"/>
                    </connections>
                </menuItem>
                <menuItem title="Remove Due Date" hidden="YES" keyEquivalent="" id="YED-n9-vGT">
                    <modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
                    <connections>
                        <action selector="removeDueDate:" target="-1" id="4g7-AY-8O7"/>
                    </connections>
                </menuItem>
                <menuItem title="Update Selected Task" hidden="YES" id="hdk-6A-k2B">
                    <string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
                    <modifierMask key="keyEquivalentModifierMask"/>
                    <connections>
                        <action selector="updateSelectedTask:" target="-1" id="aG9-LP-3Li"/>
                    </connections>
                </menuItem>
                <menuItem isSeparatorItem="YES" id="FyL-Gq-jSo"/>
                <menuItem title="Set Threshold Date" keyEquivalent="s" id="fGM-0b-agh">
                    <modifierMask key="keyEquivalentModifierMask" option="YES"/>
                    <connections>
                        <action selector="setThresholdDate:" target="-1" id="IeD-mD-KUm"/>
                    </connections>
                </menuItem>
                <menuItem title="Increase Threshold Date By 1 Day" keyEquivalent="" id="eSY-Jn-eRV">
                    <modifierMask key="keyEquivalentModifierMask" shift="YES" option="YES" command="YES"/>
                    <connections>
                        <action selector="increaseThresholdDateByOneDay:" target="-1" id="oCb-9W-q5v"/>
                    </connections>
                </menuItem>
                <menuItem title="Decrease Treshold Date By 1 Day" keyEquivalent="" id="OTg-xM-h4t">
                    <modifierMask key="keyEquivalentModifierMask" shift="YES" option="YES" command="YES"/>
                    <connections>
                        <action selector="decreaseThresholdDateByOneDay:" target="-1" id="TNd-8N-PiX"/>
                    </connections>
                </menuItem>
                <menuItem title="Remove Threshold Date" keyEquivalent="" id="fG9-Xa-uEt">
                    <modifierMask key="keyEquivalentModifierMask" shift="YES" option="YES" command="YES"/>
                    <connections>
                        <action selector="removeThresholdDate:" target="-1" id="T6i-Nh-orO"/>
                    </connections>
                </menuItem>
                <menuItem title="Remove Threshold Date" hidden="YES" keyEquivalent="" id="alZ-Ry-3E5">
                    <modifierMask key="keyEquivalentModifierMask" shift="YES" option="YES" command="YES"/>
                    <connections>
                        <action selector="removeThresholdDate:" target="-1" id="tJc-eP-Twk"/>
                    </connections>
                </menuItem>
            </items>
            <point key="canvasLocation" x="206.5" y="704.5"/>
        </menu>
    </objects>
</document>


================================================
FILE: TodoTxtMac/FontNameTransformer.h
================================================
/*
     File: FontNameTransformer.h
 Abstract: Value transformer that turns fonts into a human-readable string with the font's name and size. This is used in the preferences window.
 
  Version: 1.9
 
 Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
 Inc. ("Apple") in consideration of your agreement to the following
 terms, and your use, installation, modification or redistribution of
 this Apple software constitutes acceptance of these terms.  If you do
 not agree with these terms, please do not use, install, modify or
 redistribute this Apple software.
 
 In consideration of your agreement to abide by the following terms, and
 subject to these terms, Apple grants you a personal, non-exclusive
 license, under Apple's copyrights in this original Apple software (the
 "Apple Software"), to use, reproduce, modify and redistribute the Apple
 Software, with or without modifications, in source and/or binary forms;
 provided that if you redistribute the Apple Software in its entirety and
 without modifications, you must retain this notice and the following
 text and disclaimers in all such redistributions of the Apple Software.
 Neither the name, trademarks, service marks or logos of Apple Inc. may
 be used to endorse or promote products derived from the Apple Software
 without specific prior written permission from Apple.  Except as
 expressly stated in this notice, no other rights or licenses, express or
 implied, are granted by Apple herein, including but not limited to any
 patent rights that may be infringed by your derivative works or by other
 works in which the Apple Software may be incorporated.
 
 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
 
 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 
 Copyright (C) 2013 Apple Inc. All Rights Reserved.
 
 */

#import <Cocoa/Cocoa.h>


@interface FontNameTransformer : NSValueTransformer {

}

@end


================================================
FILE: TodoTxtMac/FontNameTransformer.m
================================================
/*
     File: FontNameTransformer.m
 Abstract: Value transformer that turns fonts into a human-readable string with the font's name and size. This is used in the preferences window.
 
  Version: 1.9
 
 Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
 Inc. ("Apple") in consideration of your agreement to the following
 terms, and your use, installation, modification or redistribution of
 this Apple software constitutes acceptance of these terms.  If you do
 not agree with these terms, please do not use, install, modify or
 redistribute this Apple software.
 
 In consideration of your agreement to abide by the following terms, and
 subject to these terms, Apple grants you a personal, non-exclusive
 license, under Apple's copyrights in this original Apple software (the
 "Apple Software"), to use, reproduce, modify and redistribute the Apple
 Software, with or without modifications, in source and/or binary forms;
 provided that if you redistribute the Apple Software in its entirety and
 without modifications, you must retain this notice and the following
 text and disclaimers in all such redistributions of the Apple Software.
 Neither the name, trademarks, service marks or logos of Apple Inc. may
 be used to endorse or promote products derived from the Apple Software
 without specific prior written permission from Apple.  Except as
 expressly stated in this notice, no other rights or licenses, express or
 implied, are granted by Apple herein, including but not limited to any
 patent rights that may be infringed by your derivative works or by other
 works in which the Apple Software may be incorporated.
 
 The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
 MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
 THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
 FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
 OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
 
 IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
 MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
 AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
 STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.
 
 Copyright (C) 2013 Apple Inc. All Rights Reserved.
 
 */

#import "FontNameTransformer.h"


@implementation FontNameTransformer
+ (Class)tranformedValueClass {
    return [NSString class];
}

+ (BOOL)allowsReverseTransformation {
    return NO;
}

- (id)transformedValue:(id)value {
    if (value && [value isKindOfClass:[NSFont class]]) {
        return [NSString stringWithFormat:@"%@ %g", [value displayName], [value pointSize]];
    } else {
        return @"";
    }
}

@end


================================================
FILE: TodoTxtMac/Images.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "size" : "16x16",
      "idiom" : "mac",
      "filename" : "icon_16x16.png",
      "scale" : "1x"
    },
    {
      "size" : "16x16",
      "idiom" : "mac",
      "filename" : "icon_16x16@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "32x32",
      "idiom" : "mac",
      "filename" : "icon_32x32.png",
      "scale" : "1x"
    },
    {
      "size" : "32x32",
      "idiom" : "mac",
      "filename" : "icon_32x32@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "128x128",
      "idiom" : "mac",
      "filename" : "icon_128x128.png",
      "scale" : "1x"
    },
    {
      "size" : "128x128",
      "idiom" : "mac",
      "filename" : "icon_128x128@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "256x256",
      "idiom" : "mac",
      "filename" : "icon_256x256.png",
      "scale" : "1x"
    },
    {
      "size" : "256x256",
      "idiom" : "mac",
      "filename" : "icon_256x256@2x.png",
      "scale" : "2x"
    },
    {
      "size" : "512x512",
      "idiom" : "mac",
      "filename" : "icon_512x512.png",
      "scale" : "1x"
    },
    {
      "size" : "512x512",
      "idiom" : "mac",
      "filename" : "icon_512x512@2x.png",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

================================================
FILE: TodoTxtMac/NSDate+RelativeDates.h
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2016 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import <Foundation/Foundation.h>

@interface NSDate (RelativeDates)

- (NSDate*)advanceDateByWeekdays:(NSInteger)numberOfWeekdays;
- (NSDate*)advanceDateByNumberOfCalendarUnits:(NSInteger)numberOfCalendarUnits
                                 calendarUnit:(NSCalendarUnit)calendarUnit;
- (BOOL)isWeekendDay;
- (BOOL)isWeekday;

@end


================================================
FILE: TodoTxtMac/NSDate+RelativeDates.m
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import "NSDate+RelativeDates.h"

@implementation NSDate (RelativeDates)

- (NSCalendar*)currentCalendar {
    return [NSCalendar currentCalendar];
}

- (NSDate*)advanceDateByWeekdays:(NSInteger)numberOfWeekdays {
    NSDate *relativeDate = self;
    NSInteger weekdaysLeft = numberOfWeekdays;
    
    while (weekdaysLeft > 0) {
        NSDate *newDate = [relativeDate advanceDateByNumberOfCalendarUnits:1 calendarUnit:NSCalendarUnitDay];
        if (newDate == nil) {
            return relativeDate;
        }
        relativeDate = newDate;
        if ([relativeDate isWeekday]) {
            weekdaysLeft -= 1;
        }
    }
    return relativeDate;
}

- (NSDate*)advanceDateByNumberOfCalendarUnits:(NSInteger)numberOfCalendarUnits
                                 calendarUnit:(NSCalendarUnit)calendarUnit {
    return [[self currentCalendar] dateByAddingUnit:calendarUnit
                                              value:numberOfCalendarUnits
                                             toDate:self
                                            options:NSCalendarMatchFirst];
}

- (BOOL)isWeekendDay {
    long weekday = [[self currentCalendar] component:NSCalendarUnitWeekday fromDate:self];
    return (weekday == 1 || weekday == 7);
}

- (BOOL)isWeekday {
    return ![self isWeekendDay];
}

@end


================================================
FILE: TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.h
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import <Foundation/Foundation.h>

@interface NSMutableAttributedString (ColorRegExMatches)

/*!
 * @method applyColor:toRegexPatternMatches:
 * @abstract Adds foreground color attributes to a mutable attributed string based for all regular
 * epxression matches.
 * @param color Color to apply
 * @param regExPattern Regular expression pattern to apply colors to matches
 */
- (void)applyColor:(NSColor*)color toRegexPatternMatches:(NSString*)regExPattern;

/*!
 * @method applyColorToFullStringRange:
 * @abstract Adds foreground color attributes to the entire mutable attributed string.
 * @param color Color to apply
 */
- (void)applyColorToFullStringRange:(NSColor*)color;

@end


================================================
FILE: TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.m
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import "NSMutableAttributableString+ColorRegExMatches.h"
#import "RegExCategories.h"

@implementation NSMutableAttributedString (ColorRegExMatches)

- (void)applyColor:(NSColor*)color toRegexPatternMatches:(NSString*)regExPattern {
    NSArray *matches = [self.string matchesWithDetails:RX(regExPattern)];
    for (RxMatch *match in matches) {
        [self addAttribute:NSForegroundColorAttributeName
                   value:color
                   range:match.range];
    }
}

- (void)applyColorToFullStringRange:(NSColor*)color {
    [self addAttribute:NSForegroundColorAttributeName
           value:color
           range:NSMakeRange(0, [self.string length])];
}

@end


================================================
FILE: TodoTxtMac/NSUserDefaults+myColorSupport.h
================================================
// This code is lifted from Apple's Developer Documenation.
// Source: https://developer.apple.com/library/mac/documentation/cocoa/conceptual/DrawColor/Tasks/StoringNSColorInDefaults.html

#import <Foundation/Foundation.h>

@interface NSUserDefaults(myColorSupport)

- (void)setColor:(NSColor *)aColor forKey:(NSString *)aKey;
- (NSColor *)colorForKey:(NSString *)aKey;

@end



================================================
FILE: TodoTxtMac/NSUserDefaults+myColorSupport.m
================================================
// This code is lifted from Apple's Developer Documenation.
// Source: https://developer.apple.com/library/mac/documentation/cocoa/conceptual/DrawColor/Tasks/StoringNSColorInDefaults.html

#import "NSUserDefaults+myColorSupport.h"

@implementation NSUserDefaults(myColorSupport)

- (void)setColor:(NSColor *)aColor forKey:(NSString *)aKey {
    NSData *theData=[NSArchiver archivedDataWithRootObject:aColor];
    [self setObject:theData forKey:aKey];
}

- (NSColor *)colorForKey:(NSString *)aKey {
    NSColor *theColor=nil;
    NSData *theData=[self dataForKey:aKey];
    if (theData != nil)
        theColor=(NSColor *)[NSUnarchiver unarchiveObjectWithData:theData];
    return theColor;
}

@end

================================================
FILE: TodoTxtMac/RegExCategories.h
================================================
//
//  RegExCategories.h
//
//  https://github.com/bendytree/Objective-C-RegEx-Categories
//
//
//  The MIT License (MIT)
//
//  Copyright (c) 2013 Josh Wright <@BendyTree>
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in all
//  copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//  SOFTWARE.
//

#import <Foundation/Foundation.h>


/********************************************************/
/*********************** MACROS *************************/
/********************************************************/

/*
 * By default, we create an alias for NSRegularExpression
 * called `Rx` and creates a macro `RX()` for quick regex creation.
 *
 * If you don't want these macros, add the following statement
 * before you include this library:
 *
 * #define DisableRegExCategoriesMacros
 */


/**
 * Creates a macro (alias) for NSRegularExpression named `Rx`.
 *
 * ie.
 * NSRegularExpression* rx = [[Rx alloc] initWithPattern:@"\d+" options:0 error:nil];
 */

#ifndef DisableRegExCategoriesMacros
#define Rx NSRegularExpression
#endif


/**
 * Creates a macro (alias) for NSRegularExpression named `Rx`.
 *
 * ie.
 * NSRegularExpression* rx = [[Rx alloc] initWithPattern:@"\d+" options:0 error:nil];
 */

#ifndef DisableRegExCategoriesMacros
#define RX(pattern) [[NSRegularExpression alloc] initWithPattern:pattern]
#endif



/********************************************************/
/******************* MATCH OBJECTS **********************/
/********************************************************/

/**
 * RxMatch represents a single match. It contains the
 * matched value, range, sub groups, and the original
 * string.
 */

@interface RxMatch : NSObject
@property (retain) NSString* value;    /* The substring that matched the expression. */
@property (assign) NSRange   range;    /* The range of the original string that was matched. */
@property (retain) NSArray*  groups;   /* Each object is an RxMatchGroup. */
@property (retain) NSString* original; /* The full original string that was matched against.  */
@end


@interface RxMatchGroup : NSObject
@property (retain) NSString* value;
@property (assign) NSRange range;
@end





/**
 * Extend NSRegularExpression.
 */

@interface NSRegularExpression (ObjectiveCRegexCategories)


/*******************************************************/
/******************* INITIALIZATION ********************/
/*******************************************************/

/**
 * Initialize an Rx object from a string.
 *
 * ie.
 * Rx* rx = [[Rx alloc] initWithString:@"\d+"];
 */

- (NSRegularExpression*) initWithPattern:(NSString*)pattern;


/**
 * Initialize an Rx object from a string.
 *
 * ie.
 * Rx* rx = [Rx rx:@"\d+"];
 */

+ (NSRegularExpression*) rx:(NSString*)pattern;


/**
 * Initialize an Rx object from a string. By default, NSRegularExpression
 * is case sensitive, but this signature allows you to change that.
 *
 * ie.
 * Rx* rx = [Rx rx:@"\d+" ignoreCase:YES];
 */

+ (NSRegularExpression*) rx:(NSString*)pattern ignoreCase:(BOOL)ignoreCase;


/**
 * Initialize an Rx object from a string and options.
 *
 * ie.
 * Rx* rx = [Rx rx:@"\d+" options:NSRegularExpressionCaseInsensitive];
 */

+ (NSRegularExpression*) rx:(NSString*)pattern options:(NSRegularExpressionOptions)options;


/*******************************************************/
/********************** IS MATCH ***********************/
/*******************************************************/

/**
 * Returns true if the string matches the regex. May also
 * be called on NSString as [@"\d" isMatch:rx].
 *
 * ie.
 * Rx* rx = RX(@"\d+");
 * BOOL isMatch = [rx isMatch:@"Dog #1"]; // => true
 */

- (BOOL) isMatch:(NSString*)matchee;


/**
 * Returns the index of the first match of the passed string.
 *
 * ie.
 * int i = [RX(@"\d+") indexOf:@"Buy 1 dog or buy 2?"]; // => 4
 */

- (int) indexOf:(NSString*)str;


/**
 * Splits a string using the regex to identify delimeters. Returns
 * an NSArray of NSStrings.
 *
 * ie.
 * NSArray* pieces = [RX(@"[ ,]") split:@"A dog,cat"];
 *  => @[@"A", @"dog", @"cat"]
 */

- (NSArray*) split:(NSString*)str;


/**
 * Replaces all occurances in a string with a replacement string.
 *
 * ie.
 * NSString* result = [RX(@"ruf+") replace:@"ruf ruff!" with:@"meow"];
 *  => @"meow meow!"
 */

- (NSString*) replace:(NSString*)string with:(NSString*)replacement;


/**
 * Replaces all occurances of a regex using a block. The block receives the match
 * and should return the replacement.
 *
 * ie.
 * NSString* result = [RX(@"[A-Z]+") replace:@"i love COW" withBlock:^(NSString*){ return @"lamp"; }];
 *  => @"i love lamp"
 */

- (NSString*) replace:(NSString*)string withBlock:(NSString*(^)(NSString* match))replacer;


/**
 * Replaces all occurances of a regex using a block. The block receives a RxMatch object
 * that contains all the details of the match and should return a string
 * which is what the match is replaced with.
 *
 * ie.
 * NSString* result = [RX(@"\\w+") replace:@"hi bud" withDetailsBlock:^(RxMatch* match){ return [NSString stringWithFormat:@"%i", match.value.length]; }];
 *  => @"2 3"
 */

- (NSString*) replace:(NSString *)string withDetailsBlock:(NSString*(^)(RxMatch* match))replacer;


/**
 * Returns an array of matched root strings with no other match information.
 *
 * ie.
 * NSString* str = @"My email is me@example.com and yours is you@example.com";
 * NSArray* matches = [RX(@"\\w+[@]\\w+[.](\\w+)") matches:str];
 *  => @[ @"me@example.com", @"you@example.com" ]
 */

- (NSArray*) matches:(NSString*)str;


/**
 * Returns a string which is the first match of the NSRegularExpression.
 *
 * ie.
 * NSString* str = @"My email is me@example.com and yours is you@example.com";
 * NSString* match = [RX(@"\\w+[@]\\w+[.](\\w+)") firstMatch:str];
 *  => @"me@example.com"
 */

- (NSString*) firstMatch:(NSString*)str;


/**
 * Returns an NSArray of RxMatch* objects. Each match contains the matched
 * value, range, groups, etc.
 *
 * ie.
 * NSString* str = @"My email is me@example.com and yours is you@example.com";
 * NSArray* matches = [str matchesWithDetails:RX(@"\\w+[@]\\w+[.](\\w+)")];
 */

- (NSArray*) matchesWithDetails:(NSString*)str;


/**
 * Returns the first match as an RxMatch* object.
 *
 * ie.
 * NSString* str = @"My email is me@example.com and yours is you@example.com";
 * Rx* rx = RX(@"\\w+[@]\\w+[.](\\w+)");
 * RxMatch* match = [rx firstMatchWithDetails:str];
 */

- (RxMatch*) firstMatchWithDetails:(NSString*)str;

@end



/**
 * A category on NSString to make it easy to use
 * Rx in simple operations.
 */

@interface NSString (ObjectiveCRegexCategories)


/**
 * Initialize an NSRegularExpression object from a string.
 *
 * ie.
 * NSRegularExpression* rx = [@"\d+" toRx];
 */

- (NSRegularExpression*) toRx;


/**
 * Initialize an NSRegularExpression object from a string with
 * a flag denoting case-sensitivity. By default, NSRegularExpression
 * is case sensitive.
 *
 * ie.
 * NSRegularExpression* rx = [@"\d+" toRxIgnoreCase:YES];
 */

- (NSRegularExpression*) toRxIgnoreCase:(BOOL)ignoreCase;


/**
 * Initialize an NSRegularExpression object from a string with options.
 *
 * ie.
 * NSRegularExpression* rx = [@"\d+" toRxWithOptions:NSRegularExpressionCaseInsensitive];
 */

- (NSRegularExpression*) toRxWithOptions:(NSRegularExpressionOptions)options;


/**
 * Returns true if the string matches the regex. May also
 * be called as on Rx as [rx isMatch:@"some string"].
 *
 * ie.
 * BOOL isMatch = [@"Dog #1" isMatch:RX(@"\d+")]; // => true
 */

- (BOOL) isMatch:(NSRegularExpression*)rx;


/**
 * Returns the index of the first match according to
 * the regex passed in.
 *
 * ie.
 * int i = [@"Buy 1 dog or buy 2?" indexOf:RX(@"\d+")]; // => 4
 */

- (int) indexOf:(NSRegularExpression*)rx;


/**
 * Splits a string using the regex to identify delimeters. Returns
 * an NSArray of NSStrings.
 *
 * ie.
 * NSArray* pieces = [@"A dog,cat" split:RX(@"[ ,]")];
 *  => @[@"A", @"dog", @"cat"]
 */

- (NSArray*) split:(NSRegularExpression*)rx;


/**
 * Replaces all occurances of a regex with a replacement string.
 *
 * ie.
 * NSString* result = [@"ruf ruff!" replace:RX(@"ruf+") with:@"meow"];
 *  => @"meow meow!"
 */

- (NSString*) replace:(NSRegularExpression*)rx with:(NSString*)replacement;


/**
 * Replaces all occurances of a regex using a block. The block receives the match
 * and should return the replacement.
 *
 * ie.
 * NSString* result = [@"i love COW" replace:RX(@"[A-Z]+") withBlock:^(NSString*){ return @"lamp"; }];
 *  => @"i love lamp"
 */

- (NSString*) replace:(NSRegularExpression *)rx withBlock:(NSString*(^)(NSString* match))replacer;


/**
 * Replaces all occurances of a regex using a block. The block receives an RxMatch
 * object which contains all of the details for each match and should return a string
 * which is what the match is replaced with.
 *
 * ie.
 * NSString* result = [@"hi bud" replace:RX(@"\\w+") withDetailsBlock:^(RxMatch* match){ return [NSString stringWithFormat:@"%i", match.value.length]; }];
 *  => @"2 3"
 */

- (NSString*) replace:(NSRegularExpression *)rx withDetailsBlock:(NSString*(^)(RxMatch* match))replacer;


/**
 * Returns an array of matched root strings with no other match information.
 *
 * ie.
 * NSString* str = @"My email is me@example.com and yours is you@example.com";
 * NSArray* matches = [str matches:RX(@"\\w+[@]\\w+[.](\\w+)")];
 *  => @[ @"me@example.com", @"you@example.com" ]
 */

- (NSArray*) matches:(NSRegularExpression*)rx;


/**
 * Returns a string which is the first match of the NSRegularExpression.
 *
 * ie.
 * NSString* str = @"My email is me@example.com and yours is you@example.com";
 * NSString* match = [str firstMatch:RX(@"\\w+[@]\\w+[.](\\w+)")];
 *  => @"me@example.com"
 */

- (NSString*) firstMatch:(NSRegularExpression*)rx;


/**
 * Returns an NSArray of RxMatch* objects. Each match contains the matched
 * value, range, groups, etc.
 *
 * ie.
 * NSString* str = @"My email is me@example.com and yours is you@example.com";
 * NSArray* matches = [str matchesWithDetails:RX(@"\\w+[@]\\w+[.](\\w+)")];
 */

- (NSArray*) matchesWithDetails:(NSRegularExpression*)rx;


/**
 * Returns an the first match as an RxMatch* object.
 *
 * ie.
 * NSString* str = @"My email is me@example.com and yours is you@example.com";
 * RxMatch* match = [str firstMatchWithDetails:RX(@"\\w+[@]\\w+[.](\\w+)")];
 */

- (RxMatch*) firstMatchWithDetails:(NSRegularExpression*)rx;

@end

================================================
FILE: TodoTxtMac/RegExCategories.m
================================================
//
//  RegExCategories.m
//
//  https://github.com/bendytree/Objective-C-RegEx-Categories
//
//
//  The MIT License (MIT)
//
//  Copyright (c) 2013 Josh Wright <@BendyTree>
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy
//  of this software and associated documentation files (the "Software"), to deal
//  in the Software without restriction, including without limitation the rights
//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//  copies of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be included in all
//  copies or substantial portions of the Software.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//  SOFTWARE.
//

#import "RegExCategories.h"

@implementation NSRegularExpression (ObjectiveCRegexCategories)

- (id) initWithPattern:(NSString*)pattern
{
    return [self initWithPattern:pattern options:0 error:nil];
}

+ (NSRegularExpression*) rx:(NSString*)pattern
{
    return [[self alloc] initWithPattern:pattern];
}

+ (NSRegularExpression*) rx:(NSString*)pattern ignoreCase:(BOOL)ignoreCase
{
    return [[self alloc] initWithPattern:pattern options:ignoreCase?NSRegularExpressionCaseInsensitive:0 error:nil];
}

+ (NSRegularExpression*) rx:(NSString*)pattern options:(NSRegularExpressionOptions)options
{
    return [[self alloc] initWithPattern:pattern options:options error:nil];
}

- (BOOL) isMatch:(NSString*)matchee
{
    return [self numberOfMatchesInString:matchee options:0 range:NSMakeRange(0, matchee.length)] > 0;
}

- (int) indexOf:(NSString*)matchee
{
    NSRange range = [self rangeOfFirstMatchInString:matchee options:0 range:NSMakeRange(0, matchee.length)];
    return range.location == NSNotFound ? -1 : (int)range.location;
}

- (NSArray*) split:(NSString *)str
{
    NSRange range = NSMakeRange(0, str.length);
    
    //get locations of matches
    NSMutableArray* matchingRanges = [NSMutableArray array];
    NSArray* matches = [self matchesInString:str options:0 range:range];
    for(NSTextCheckingResult* match in matches) {
        [matchingRanges addObject:[NSValue valueWithRange:match.range]];
    }
    
    //invert ranges - get ranges of non-matched pieces
    NSMutableArray* pieceRanges = [NSMutableArray array];
    
    //add first range
    [pieceRanges addObject:[NSValue valueWithRange:NSMakeRange(0,
                                                               (matchingRanges.count == 0 ? str.length : [matchingRanges[0] rangeValue].location))]];
    
    //add between splits ranges and last range
    for(int i=0; i<matchingRanges.count; i++){
        BOOL isLast = i+1 == matchingRanges.count;
        unsigned long startLoc = [matchingRanges[i] rangeValue].location + [matchingRanges[i] rangeValue].length;
        unsigned long endLoc = isLast ? str.length : [matchingRanges[i+1] rangeValue].location;
        [pieceRanges addObject:[NSValue valueWithRange:NSMakeRange(startLoc, endLoc-startLoc)]];
    }
    
    //use split ranges to select pieces
    NSMutableArray* pieces = [NSMutableArray array];
    for(NSValue* val in pieceRanges) {
        NSRange range = [val rangeValue];
        NSString* piece = [str substringWithRange:range];
        [pieces addObject:piece];
    }
    
    return pieces;
}

- (NSString*) replace:(NSString*)string with:(NSString*)replacement
{
    return [self stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, string.length) withTemplate:replacement];
}

- (NSString*) replace:(NSString*)string withBlock:(NSString*(^)(NSString* match))replacer
{
    //no replacer? just return
    if (!replacer) return string;
    
    //copy the string so we can replace subsections
    NSMutableString* result = [string mutableCopy];
    
    //get matches
    NSArray* matches = [self matchesInString:string options:0 range:NSMakeRange(0, string.length)];
    
    //replace each match (right to left so indexing doesn't get messed up)
    for (int i=(int)matches.count-1; i>=0; i--) {
        NSTextCheckingResult* match = matches[i];
        NSString* matchStr = [string substringWithRange:match.range];
        NSString* replacement = replacer(matchStr);
        [result replaceCharactersInRange:match.range withString:replacement];
    }
    
    return result;
}

- (NSString*) replace:(NSString *)string withDetailsBlock:(NSString*(^)(RxMatch* match))replacer
{
    //no replacer? just return
    if (!replacer) return string;
    
    //copy the string so we can replace subsections
    NSMutableString* replaced = [string mutableCopy];
    
    //get matches
    NSArray* matches = [self matchesInString:string options:0 range:NSMakeRange(0, string.length)];
    
    //replace each match (right to left so indexing doesn't get messed up)
    for (int i=(int)matches.count-1; i>=0; i--) {
        NSTextCheckingResult* result = matches[i];
        RxMatch* match = [self resultToMatch:result original:string];
        NSString* replacement = replacer(match);
        [replaced replaceCharactersInRange:result.range withString:replacement];
    }
    
    return replaced;
}

- (NSArray*) matches:(NSString*)str
{
    NSMutableArray* matches = [NSMutableArray array];
    
    NSArray* results = [self matchesInString:str options:0 range:NSMakeRange(0, str.length)];
    for (NSTextCheckingResult* result in results) {
        NSString* match = [str substringWithRange:result.range];
        [matches addObject:match];
    }
    
    return matches;
}

- (NSString*) firstMatch:(NSString*)str
{
    NSTextCheckingResult* match = [self firstMatchInString:str options:0 range:NSMakeRange(0, str.length)];
    
    if (!match) return nil;
    
    return [str substringWithRange:match.range];
}

- (RxMatch*) resultToMatch:(NSTextCheckingResult*)result original:(NSString*)original
{
    RxMatch* match = [[RxMatch alloc] init];
    match.original = original;
    match.range = result.range;
    match.value = result.range.length ? [original substringWithRange:result.range] : nil;
    
    //groups
    NSMutableArray* groups = [NSMutableArray array];
    match.groups = groups;
    for(int i=0; i<result.numberOfRanges; i++){
        RxMatchGroup* group = [[RxMatchGroup alloc] init];
        group.range = [result rangeAtIndex:i];
        group.value = group.range.length ? [original substringWithRange:group.range] : nil;
        [groups addObject:group];
    }
    
    return match;
}

- (NSArray*) matchesWithDetails:(NSString*)str
{
    NSMutableArray* matches = [NSMutableArray array];
    
    NSArray* results = [self matchesInString:str options:0 range:NSMakeRange(0, str.length)];
    for (NSTextCheckingResult* result in results) {
        [matches addObject:[self resultToMatch:result original:str]];
    }
    
    return matches;
}

- (RxMatch*) firstMatchWithDetails:(NSString*)str
{
    NSArray* results = [self matchesInString:str options:0 range:NSMakeRange(0, str.length)];
    
    if (results.count == 0)
        return nil;
    
    return [self resultToMatch:results[0] original:str];
}

@end



@implementation NSString (ObjectiveCRegexCategories)

- (NSRegularExpression*) toRx
{
    return [[NSRegularExpression alloc] initWithPattern:self];
}

- (NSRegularExpression*) toRxIgnoreCase:(BOOL)ignoreCase
{
    return [NSRegularExpression rx:self ignoreCase:ignoreCase];
}

- (NSRegularExpression*) toRxWithOptions:(NSRegularExpressionOptions)options
{
    return [NSRegularExpression rx:self options:options];
}

- (BOOL) isMatch:(NSRegularExpression*)rx
{
    return [rx isMatch:self];
}

- (int) indexOf:(NSRegularExpression*)rx
{
    return [rx indexOf:self];
}

- (NSArray*) split:(NSRegularExpression*)rx
{
    return [rx split:self];
}

- (NSString*) replace:(NSRegularExpression*)rx with:(NSString*)replacement
{
    return [rx replace:self with:replacement];
}

- (NSString*) replace:(NSRegularExpression *)rx withBlock:(NSString*(^)(NSString* match))replacer
{
    return [rx replace:self withBlock:replacer];
}

- (NSString*) replace:(NSRegularExpression *)rx withDetailsBlock:(NSString*(^)(RxMatch* match))replacer
{
    return [rx replace:self withDetailsBlock:replacer];
}

- (NSArray*) matches:(NSRegularExpression*)rx
{
    return [rx matches:self];
}

- (NSString*) firstMatch:(NSRegularExpression*)rx
{
    return [rx firstMatch:self];
}

- (NSArray*) matchesWithDetails:(NSRegularExpression*)rx
{
    return [rx matchesWithDetails:self];
}

- (RxMatch*) firstMatchWithDetails:(NSRegularExpression*)rx
{
    return [rx firstMatchWithDetails:self];
}

@end



@implementation RxMatch
@synthesize value, range, groups, original;
@end

@implementation RxMatchGroup
@synthesize value, range;
@end

================================================
FILE: TodoTxtMac/RelativeDates.strings
================================================
/* Fri */
"Fri" = "Fri";

/* Friday */
"Friday" = "Friday";

/* Mon */
"Mon" = "Mon";

/* Monday */
"Monday" = "Monday";

/* Sat */
"Sat" = "Sat";

/* Saturday */
"Saturday" = "Saturday";

/* Sun */
"Sun" = "Sun";

/* Sunday */
"Sunday" = "Sunday";

/* Thu */
"Thu" = "Thu";

/* Thursday */
"Thursday" = "Thursday";

/* today */
"today" = "today";

/* tomorrow */
"tomorrow" = "tomorrow";

/* Tue */
"Tue" = "Tue";

/* Tuesday */
"Tuesday" = "Tuesday";

/* Wed */
"Wed" = "Wed";

/* Wednesday */
"Wednesday" = "Wednesday";

/* yesterday */
"yesterday" = "yesterday";



================================================
FILE: TodoTxtMac/TTMAppController.h
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import <Foundation/Foundation.h>
@class TTMPreferencesController;
@class TTMFiltersController;

@interface TTMAppController : NSObject

// Constants for command-line argument names
extern NSString *const TodoFileArgument;

@property (nonatomic, retain) TTMPreferencesController *preferencesController;
@property (nonatomic, retain) TTMFiltersController *filtersController;

- (IBAction)openPreferencesWindow:(id)sender;
- (IBAction)openFiltersWindow:(id)sender;
- (IBAction)openWebSite:(id)sender;
- (IBAction)openPlaintextProductivityWebSite:(id)sender;
- (IBAction)openTodoTxtTipsPlaintextProductivityWebSite:(id)sender;

#pragma mark - User Defaults-related Methods

/*!
 * @method initializeUserDefaults:
 * @abstract This method sets up preferences managed by NSUserDefaultsController.
 */
- (void)initializeUserDefaults:(id)sender;

/*!
 * @method resetUserDefaults:
 * @abstract This method resets preferences managed by NSUserDefaultsController to default values.
 * It does not reset fitler-related preferences.
 */
- (void)resetUserDefaults:(id)sender;

#pragma mark - Command-line Argument-related Methods

/*!
 * @method openTodoFileFromCommandLineArgument:
 * @abstract This method opens a todo.txt file based on the command line argument. 
 * The name of the argument is defined in the TodoFileArgument constant.
 * If there is no command line argument, this method does nothing.
 */
- (void)openTodoFileFromCommandLineArgument;

/*!
 * @method commandLineArgumentTodoFile:
 * @abstract This method returns the value of the todo-file command line argument.
 * If there is no command-line argument, it returns null.
 */
- (NSString*)commandLineArgumentTodoFile;

/*!
 * @method openDocumentFromFilePath:
 * @abstract This method opens a todo.txt file (TTMDocument) based on a file path.
 */
- (void)openDocumentFromFilePath:(NSString*)filePath;

/*!
 * @method openDocumentFromFilePath:
 * @abstract This method opens a todo.txt file (TTMDocument) based on a file URL.
 */
- (void)openDocumentFromFileURL:(NSURL*)fileURL;

#pragma mark - Open Default Todo.txt File Methods

/*!
 * @method openDefaultTodoFile:
 * @abstract This method opens the default todo.txt file (TTMDocument) based on user preferences.
 * If the user preference for opening a default todo.txt file on startup is disabled,
 * this method does nothing.
 */
-(void)openDefaultTodoFile;

#pragma mark - Close All Windows Methods

/*!
 * @method closeAllWindows:
 * @abstract This method closes all open windows.
 */
- (IBAction)closeAllWindows:(id)sender;

/*!
 * @method documentController:didCloseAll:contextInfo
 * @abstract This method is a completion handler for closeAllWindows. It does nothing.
 */
- (void)documentController:(NSDocumentController *)docController
               didCloseAll:(BOOL)didCloseAll
               contextInfo:(void *)contextInfo;

#pragma mark - Reload All Methods

/*!
 * @method reloadAll:
 * @abstract This method refreshes the task list from disk for all open windows.
 */
- (IBAction)reloadAll:(id)sender;

#pragma mark - Visual Refresh Methods

/*!
 * @method visualRefreshAll:
 * @abstract This method visually refreshes the task list for all open windows.
 */
- (IBAction)visualRefreshAll:(id)sender;

@end


================================================
FILE: TodoTxtMac/TTMAppController.m
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import "TTMAppController.h"
#import "TTMPreferencesController.h"
#import "TTMFiltersController.h"
#import "TTMFilterPredicates.h"
#import "TTMDocument.h"
#import "TTMDocumentStatusBarText.h"

// Default user preference values, including those for saved filters
static NSDictionary *defaultValues() {
    
    static NSData *defaultPredicateData = nil;
    if (defaultPredicateData == nil) {
        defaultPredicateData = [TTMFilterPredicates defaultFilterPredicateData];
    }

    static NSDictionary *dict = nil;
    if (!dict) {
        dict = [[NSDictionary alloc] initWithObjectsAndKeys:
                @NO, @"prependDateOnNewTasks",
                @1, @"taskListSortType",
                defaultPredicateData, @"activefilterPredicate",
                @0, @"activefilterPreset",
                defaultPredicateData, @"filterPredicate1",
                defaultPredicateData, @"filterPredicate2",
                defaultPredicateData, @"filterPredicate3",
                defaultPredicateData, @"filterPredicate4",
                defaultPredicateData, @"filterPredicate5",
                defaultPredicateData, @"filterPredicate6",
                defaultPredicateData, @"filterPredicate7",
                defaultPredicateData, @"filterPredicate8",
                defaultPredicateData, @"filterPredicate9",
                @"", @"archiveFilePath",
                @NO, @"archiveTasksUponCompletion",
                @NO, @"useUserFont",
                @NO, @"moveToTaskListAfterTaskCreation",
                @YES, @"useHighlightColorsInTaskList",
                @NO, @"useCustomColorForOverdueTasks",
                @NO, @"useCustomColorForDueTodayTasks",
                @NO, @"useCustomColorForProjects",
                @NO, @"useCustomColorForContexts",
                @NO, @"useCustomColorForTags",
                @NO, @"useCustomColorForDueDates",
                @NO, @"useCustomColorForThresholdDates",
                @NO, @"useCustomColorForCreationDates",
                [NSArchiver archivedDataWithRootObject:[NSColor redColor]], @"dueTodayColor",
                [NSArchiver archivedDataWithRootObject:[NSColor purpleColor]], @"overdueColor",
                [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"projectColor",
                [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"contextColor",
                [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"tagColor",
                [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"dueDateColor",
                [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"thresholdDateColor",
                [NSArchiver archivedDataWithRootObject:[NSColor darkGrayColor]], @"creationDateColor",
                @NO, @"escapeKeyCancelsAllTextChanges",
                @NO, @"openDefaultTodoFileOnStartup",
                @"", @"defaultTodoFilePath",
                @YES, @"showStatusBar",
                [TTMDocumentStatusBarText defaultFormat], @"statusBarFormat",
                @0, @"levelsOfUndo",
                @YES, @"allowUndoOfArchiveCommand",
                @NO, @"hideFutureTasks",
                @NO, @"closingLastWindowClosesApplication",
                @NO, @"hideHiddenTasks",
                nil];
    }
    return dict;
}

// Default user preference values, excluding those for saved filters.
// Defined to help allow users to reset preferences without losing saved filters.
static NSDictionary *defaultValuesExcludingFilters() {
    static NSMutableDictionary *defaults = nil;
    if (defaults == nil) {
        defaults = [NSMutableDictionary dictionaryWithDictionary:defaultValues()];
        for (int i = 1; i <= 9; i++) {
            [defaults removeObjectForKey:[TTMFilterPredicates keyFromPresetNumber:i]];
        }
        [defaults removeObjectForKey:@"activefilterPredicate"];
    }
    return defaults;
}

@implementation TTMAppController

// Constants for command-line argument names
NSString *const TodoFileArgument = @"todo-file";

- (id)init {
    self = [super init];
    if (self) {
    }
    return self;
}

- (IBAction)openPreferencesWindow:(id)sender {
    if (!self.preferencesController) {
        self.preferencesController = [[TTMPreferencesController alloc]
                                      initWithWindowNibName:@"TTMPreferences"];
    }
    [self.preferencesController showWindow:self];
}

- (IBAction)openFiltersWindow:(id)sender {
    if (!self.filtersController) {
        self.filtersController = [[TTMFiltersController alloc]
                                  initWithWindowNibName:@"TTMFilters"];
    }
    [self.filtersController showWindow:self];
}

- (void)launchURLFromString:(NSString*)urlString {
    NSURL *url = [NSURL URLWithString:urlString];
    [[NSWorkspace sharedWorkspace] openURL:url];
}

- (IBAction)openWebSite:(id)sender {
    [self launchURLFromString:@"http://mjdescy.github.io/TodoTxtMac/"];
}

- (IBAction)openPlaintextProductivityWebSite:(id)sender {
    [self launchURLFromString:@"http://plaintext-productivity.net"];
}

- (IBAction)openTodoTxtTipsPlaintextProductivityWebSite:(id)sender {
    [self launchURLFromString:@"http://plaintext-productivity.net/1-00-tasks-introduction.html"];
}


#pragma mark - User Defaults-related Methods

- (void)initializeUserDefaults:(id)sender {
    [[NSUserDefaults standardUserDefaults] registerDefaults:defaultValues()];
    [[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:defaultValues()];
}

- (void)resetUserDefaults:(id)sender {
    [[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:
                                                                 defaultValuesExcludingFilters()];
    [[NSUserDefaultsController sharedUserDefaultsController] revertToInitialValues:self];
    [[NSUserDefaultsController sharedUserDefaultsController] setInitialValues:defaultValues()];
}

#pragma mark - Command-line Argument-related Methods

- (void)openTodoFileFromCommandLineArgument {
    NSString *fileToOpenOnLaunch = [self commandLineArgumentTodoFile];
    if (!fileToOpenOnLaunch) {
        return;
    }
    [self openDocumentFromFilePath:fileToOpenOnLaunch];
}

- (NSString*)commandLineArgumentTodoFile {
    NSUserDefaults *args = [NSUserDefaults standardUserDefaults];
    return [args stringForKey:TodoFileArgument];
}

- (void)openDocumentFromFilePath:(NSString*)filePath {
    NSURL *fileURL = [NSURL fileURLWithPath:filePath];
    [self openDocumentFromFileURL:fileURL];
}

- (void)openDocumentFromFileURL:(NSURL*)fileURL {
    [[NSDocumentController sharedDocumentController]
     openDocumentWithContentsOfURL:fileURL
     display:YES
     completionHandler:^(NSDocument *document, BOOL alreadyOpen, NSError *error){
         // NSLog(@"%@",document);
     }];
}

#pragma mark - Open Default Todo.txt File Methods

-(void)openDefaultTodoFile {
    if (![[NSUserDefaults standardUserDefaults] boolForKey:@"openDefaultTodoFileOnStartup"]) {
        return;
    }
    [self openDocumentFromFilePath:[[NSUserDefaults standardUserDefaults]
                                    stringForKey:@"defaultTodoFilePath"]];
}

#pragma mark - Close All Windows Methods

- (IBAction)closeAllWindows:(id)sender {
    [[NSDocumentController sharedDocumentController]
         closeAllDocumentsWithDelegate:self
                   didCloseAllSelector:@selector(documentController:didCloseAll:contextInfo:)
                           contextInfo:NULL];
}

- (void)documentController:(NSDocumentController *)docController
                     didCloseAll:(BOOL)didCloseAll
                     contextInfo:(void *)contextInfo {
    return;
}

#pragma mark - Reload All Methods

- (IBAction)reloadAll:(id)sender {
    NSArray *documents = [[NSDocumentController sharedDocumentController] documents];
    [documents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [(TTMDocument*)obj reloadFile:self];
    }];
}

#pragma mark - Visual Refresh Methods

- (IBAction)visualRefreshAll:(id)sender {
    NSArray *documents = [[NSDocumentController sharedDocumentController] documents];
    [documents enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [(TTMDocument*)obj visualRefreshOnly:self];
    }];
}

@end


================================================
FILE: TodoTxtMac/TTMAppDelegate.h
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import <Foundation/Foundation.h>
@class TTMAppController;

@interface TTMAppDelegate : NSObject <NSApplicationDelegate>

@property (nonatomic, retain) IBOutlet TTMAppController *appController;

@end


================================================
FILE: TodoTxtMac/TTMAppDelegate.m
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import "TTMAppDelegate.h"
#import "TTMFilterPredicates.h"
#import "TTMAppController.h"

@implementation TTMAppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
    [self.appController initializeUserDefaults:self];
    
    // Open file from command line argument. Does nothing if there is no command line argument.
    [self.appController openTodoFileFromCommandLineArgument];
    
    // Open default todo file, if one is selected and the option is enabled.
    [self.appController openDefaultTodoFile];
}

- (BOOL)applicationShouldOpenUntitledFile:(NSApplication *)sender {
    // Suppress creating an Untitled document on launch if either:
    // 1. there is a command line argument to open a todo file, or
    // 2. the open default todo.txt file on startup user preference is selected.
    // Without this method override, opening a todo file using the command line argument
    // or the default todo file user preference also opens an Untitled document every time.
    return ([self.appController commandLineArgumentTodoFile] == NULL &&
            ![[NSUserDefaults standardUserDefaults] boolForKey:@"openDefaultTodoFileOnStartup"]);
}

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication {
    return [[NSUserDefaults standardUserDefaults] boolForKey:@"closingLastWindowClosesApplication"];
}

@end


================================================
FILE: TodoTxtMac/TTMDateUtility.h
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import <Foundation/Foundation.h>

@interface TTMDateUtility : NSObject

/*!
 * @method convertStringToDate:
 * @abstract This method converts a string in "yyyy-MM-dd" format to an NSDate object.
 * @param dateString An NSString in "yyyy-MM-dd" format. It must not contain time elements.
 * @return Returns a date object based on the date string.
 */
+ (NSDate*)convertStringToDate:(NSString*)dateString;

/*!
 * @method convertDateToString:
 * @abstract This method returns today's date as a string in "yyyy-MM-dd" format.
 * @param date The date to convert to a string.
 * @return The date parameter as a string in "yyyy-MM-dd" format.
 */
+ (NSString*)convertDateToString:(NSDate*)date;

/*!
 * @method todayAsString:
 * @abstract This method returns today's date.
 * @return Today's date.
 */
+ (NSDate*)today;

/*!
 * @method todayAsString:
 * @abstract This method returns today's date as a string in "yyyy-MM-dd" format.
 * @return Today's date as a string in "yyyy-MM-dd" format.
 */
+ (NSString*)todayAsString;

/*!
 * @method addDays:toDate:
 * @abstract This method adds a number of days to the date.
 * @param days The number of days to add. Can be negative.
 * @param date The date to add days to.
 * @return A date offset by the given number of days.
 */
+ (NSDate*)addDays:(NSInteger)days toDate:(NSDate*)date;

/*!
 * @method dateWithoutTime:
 * @abstract This method strips the time element from a date.
 * @param date The date to return as of 00:00:00.
 * @return A date with the time element set to 00:00:00.
 * @discussion This method is necessary to allow for date "is equal" comparisons
 * in NSPredicateEditor.
 */
+ (NSDate*)dateWithoutTime:(NSDate*)date;

/*!
 * @method dateFromNaturalLanguageString:
 * @abstract This method returns a date based on a string such as "today" or "Monday".
 * @param string A string that could represent a relative due date.
 * @return A date, or nil if no date matches the string passed to the method.
 */
+ (NSDate*)dateFromNaturalLanguageString:(NSString*)string;

/*!
 * @method relativeDateFromWeekdayName:withAllowedWeekdayNames:withDateFormat
 * @abstract This method returns a date based on a string that represents a weekday name.
 * @return A date, or nil if no date matches the string passed to the method.
 * @param weekdayName A string that could be a weekday name.
 * @param allowedWeekdayNames An array of weekday names (or shortnames) that the weekdayName 
 * will be tested to match.
 * @param dateFormat Date format to apply to the weekdayName for matching purposes.
 * @discussion This is a convenience method called from
 * relativeDateFromWeekdayName:withAllowedWeekdayNames:withDateFormat.
 */
+ (NSDate*)relativeDateFromWeekdayName:(NSString*)weekdayName
               withAllowedWeekdayNames:(NSArray*)allowedWeekdayNames
                        withDateFormat:(NSString*)dateFormat;

/*!
 * @method dateStringFromNaturalLanguageString:
 * @abstract This method returns a string-formatted date in "YYYY-MM-DD" format, 
 * based on a string such as "today" or "Monday".
 * @param string A string that could represent a relative due date.
 * @return A string-formatted date in "YYYY-MM-DD" format, or nil if no date matches
 * the string passed to the method.
 */
+ (NSString*)dateStringFromNaturalLanguageString:(NSString*)string;

+ (NSInteger)daysBetweenDate:(NSDate*)startDate andEndDate:(NSDate*)endDate;

@end


================================================
FILE: TodoTxtMac/TTMDateUtility.m
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import "TTMDateUtility.h"
#import "NSDate+RelativeDates.h"

@implementation TTMDateUtility

+ (NSDate*)convertStringToDate:(NSString*)dateString {
    if (!dateString) {
        return nil;
    }
    
    // dateString must not contain a time element.
    // We add a time element to it to set the time to midnight.
    NSString *dateTimeString = [dateString stringByAppendingString:@" 00:00:00"];
    
    // Convert dateString to NSDate.
    NSDateFormatter *dateFormatter = [self dateFormatter];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    return [dateFormatter dateFromString:dateTimeString];
}

+ (NSDateFormatter*)dateFormatter {
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    [dateFormatter setCalendar:gregorian];
    [dateFormatter setLocale:[NSLocale systemLocale]];
    [dateFormatter setDateFormat:@"yyyy-MM-dd"];
    return dateFormatter;
}

+ (NSString*)convertDateToString:(NSDate*)date {
    if (!date) {
        return nil;
    }
    NSDateFormatter *dateFormatter = [self dateFormatter];
    return [dateFormatter stringFromDate:date];
}

+ (NSDate*)today {
    return [self dateWithoutTime:[NSDate date]];
}

+ (NSString*)todayAsString {
    return [self convertDateToString:[self today]];
}

+ (NSDate*)addDays:(NSInteger)days toDate:(NSDate*)date {
    NSDateComponents *dayComponent = [[NSDateComponents alloc] init];
    dayComponent.day = days;
    NSCalendar *theCalendar = [NSCalendar currentCalendar];
    return [theCalendar dateByAddingComponents:dayComponent toDate:date options:0];
}

+ (NSDate*)dateWithoutTime:(NSDate*)date {
    if (date == nil) {
        return nil;
    }
    NSDateComponents *comps = [[NSCalendar currentCalendar]
                               components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay
                               fromDate:date];
    
    return [[NSCalendar currentCalendar] dateFromComponents:comps];
}

+ (NSDate*)dateFromNaturalLanguageString:(NSString*)string {
    // This method's structure of comparing localized strings, rather than just using
    // an NSDataDetector, came about because NSDataDetector does not properly find dates
    // in short strings such as "today", "tomorrow", or "Friday". NSDataDetector does find
    // dates when a time is specified, such as "today at 00:00", but it also finds the time
    // when nonsense plus a time is specified, as in "never at 00:00" (which returns today's date
    // at midnight).

    if (!string) {
        return nil;
    }
    
    NSString *todayString = NSLocalizedStringFromTable(@"today", @"RelativeDates", @"today");
    if ([string caseInsensitiveCompare:todayString] ==
        NSOrderedSame) {
        return [self today];
    }
    
    NSString *tomorrowString = NSLocalizedStringFromTable(@"tomorrow", @"RelativeDates",
                                                          @"tomorrow");
    if ([string caseInsensitiveCompare:tomorrowString]
        == NSOrderedSame) {
        return  [self addDays:1 toDate:[self today]];
    }
    
    NSString *yesterdayString = NSLocalizedStringFromTable(@"yesterday", @"RelativeDates",
                                                           @"yesterday");
    if ([string caseInsensitiveCompare:yesterdayString]
        == NSOrderedSame) {
        return  [self addDays:-1 toDate:[self today]];
    }
    
    NSString *testString = [string lowercaseString];
    NSDate *returnDate;
    
    NSArray *weekdayNames =
        @[[NSLocalizedStringFromTable(@"Monday", @"RelativeDates", @"Monday") lowercaseString],
          [NSLocalizedStringFromTable(@"Tuesday", @"RelativeDates", @"Tuesday") lowercaseString],
          [NSLocalizedStringFromTable(@"Wednesday", @"RelativeDates", @"Wednesday") lowercaseString],
          [NSLocalizedStringFromTable(@"Thursday", @"RelativeDates", @"Thursday") lowercaseString],
          [NSLocalizedStringFromTable(@"Friday", @"RelativeDates", @"Friday") lowercaseString],
          [NSLocalizedStringFromTable(@"Saturday", @"RelativeDates", @"Saturday") lowercaseString],
          [NSLocalizedStringFromTable(@"Sunday", @"RelativeDates", @"Sunday") lowercaseString]];
    returnDate = [self relativeDateFromWeekdayName:testString
                           withAllowedWeekdayNames:weekdayNames
                                    withDateFormat:@"eeee"];
    if (returnDate) {
        return returnDate;
    }

    NSArray *shortWeekdayNames =
        @[[NSLocalizedStringFromTable(@"Mon", @"RelativeDates", @"Mon") lowercaseString],
          [NSLocalizedStringFromTable(@"Tue", @"RelativeDates", @"Tue") lowercaseString],
          [NSLocalizedStringFromTable(@"Wed", @"RelativeDates", @"Wed") lowercaseString],
          [NSLocalizedStringFromTable(@"Thu", @"RelativeDates", @"Thu") lowercaseString],
          [NSLocalizedStringFromTable(@"Fri", @"RelativeDates", @"Fri") lowercaseString],
          [NSLocalizedStringFromTable(@"Sat", @"RelativeDates", @"Sat") lowercaseString],
          [NSLocalizedStringFromTable(@"Sun", @"RelativeDates", @"Sun") lowercaseString]];
    returnDate = [self relativeDateFromWeekdayName:testString
                           withAllowedWeekdayNames:shortWeekdayNames
                                    withDateFormat:@"eee"];
    if (returnDate) {
        return returnDate;
    }
    
    return nil;
}

+ (NSDate*)relativeDateFromWeekdayName:(NSString*)weekdayName
               withAllowedWeekdayNames:(NSArray*)allowedWeekdayNames
                        withDateFormat:(NSString*)dateFormat {
    NSSet *weekdayNamesSet = [NSSet setWithArray:allowedWeekdayNames];
    if (![weekdayNamesSet containsObject:weekdayName]) {
        return nil;
    }
    
    NSDateFormatter *dateFormatter = [self dateFormatter];
    [dateFormatter setDateFormat:dateFormat];
    
    NSDate *todaysDate = [self today];
    
    for (NSUInteger i = 1; i < 8; i++) {
        NSDate *testDate = [self addDays:i toDate:todaysDate];
        NSString *generatedWeekdayName = [[dateFormatter stringFromDate:testDate] lowercaseString];
        if ([weekdayName caseInsensitiveCompare:generatedWeekdayName] == NSOrderedSame) {
            return testDate;
        }
    }
    
    return nil;
}

+ (NSString*)dateStringFromNaturalLanguageString:(NSString*)naturalLanguageString {
    NSDate *date = [self dateFromNaturalLanguageString:naturalLanguageString];
    if (date == nil) {
        return nil;
    } else {
        return [self convertDateToString:date];
    }
}

+ (NSInteger)daysBetweenDate:(NSDate*)startDate andEndDate:(NSDate*)endDate {
    NSCalendar *currentCalendar = [NSCalendar currentCalendar];
    NSDateComponents *components = [currentCalendar components:NSCalendarUnitDay fromDate:startDate toDate:endDate options:NSCalendarMatchFirst];
    
    return components.day;
}

@end

================================================
FILE: TodoTxtMac/TTMDocument.h
================================================
/**
 * @author Michael Descy
 * @copyright 2014-2015 Michael Descy
 * @discussion Dual-licensed under the GNU General Public License and the MIT License
 *
 *
 *
 * @license GNU General Public License http://www.gnu.org/licenses/gpl.html
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *
 *
 *
 * @license The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#import <Cocoa/Cocoa.h>
@class TTMAppController;
@class TTMFieldEditor;
@class TTMTask;
@class TTMTasklistMetadata;
@class TTMTableView;
@class TTMTableViewDelegate;

#define TASKMENUTAG   3000
#define SORTMENUTAG   4000
#define FILTERMENUTAG 5000
#define STATUSBARMENUITEMTAG 6000
#define COPYTASKTONEWTASKMENUTAG 7000

typedef enum : NSUInteger {
    TTMSortOrderInFile,
    TTMSortPriority,
    TTMSortProject,
    TTMSortContext,
    TTMSortDueDate,
    TTMSortCreationDate,
    TTMSortCompletionDate,
    TTMSortThresholdDate,
    TTMSortAlphabetical
} TTMTaskListSortType;

@interface TTMDocument : NSDocument

#pragma mark - Properties

// Data elements related to the task list
@property (nonatomic, copy) NSMutableArray *taskList;
@property (nonatomic) BOOL usesWindowsLineEndings;
@property (nonatomic, copy) NSString *preferredLineEnding;

// Window controls
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@property (nonatomic, retain) IBOutlet NSSearchField *searchField;
@property (nonatomic, retain) IBOutlet NSPredicate *searchFieldPredicate;
@property (nonatomic, retain) IBOutlet TTMTableView *tableView;
@property (nonatomic, retain) IBOutlet TTMTableViewDelegate *tableViewDelegate;
@property (nonatomic, retain) IBOutlet NSArrayController *arrayController;
@property (nonatomic, retain) IBOutlet NSCell *rawTextCell;
@property (nonatomic, retain) TTMFieldEditor *customFieldEditor;
@property (nonatomic, retain) IBOutlet NSTextField *statusBarTextField;
@property (nonatomic, retain) NSString *statusBarText;
@property (nonatomic, retain) IBOutlet NSLayoutConstraint *bottomConstraint;
@property (nonatomic, retain) IBOutlet NSView *findReplaceView;
@property (nonatomic, retain) IBOutlet NSTextField *findText;
@property (nonatomic, retain) IBOutlet NSTextField *replaceText;

// User font preference
@property (nonatomic) BOOL usingUserFont;
@property (nonatomic, retain) NSFont *userFont;

// Active filter predicate
@property (nonatomic, retain) NSPredicate *activeFilterPredicate;
@property (nonatomic) NSUInteger activeFilterPredicateNumber;

// Active sort type
@property (nonatomic) NSUInteger activeSortType;

// Tasklist metadata
@property (nonatomic, retain) TTMTasklistMetadata *tasklistMetadata;
@property (nonatomic, retain) TTMTasklistMetadata *filteredTasklistMetadata;
@property (nonatomic, retain) IBOutlet NSWindow *tasklistMetadataSheet;

// Task objects for undo/redo of task edits
@property (nonatomic, copy) NSArray *originalTasks;

@property (nonatomic, retain) NSDate *lastInternalModificationDate;


#pragma mark - File Loading and Saving Methods

/*!
 * @method reloadFile:
 * @abstract Reloads the task list file.
 */
- (IBAction)reloadFile:(id)sender;

/*!
 * @method getTaskListSelections
 * @abstract This method gets/saves selected items in the task list before the reload:
 * method reloads the task list file, to allow for selections to be retained (as much as possible)
 * after the user reloads the file.
 */
- (NSMutableArray*)getTaskListSelections;

/*!
 * @method setTaskListSelections:
 * @param taskListSelections Array of task items to select
 * @abstract This method re-sets selected items in the task list after the reload:
 * method reloads the task list file, to allow for selections to be retained (as much as possible)
 * after the user reloads the file. This method makes a best effort to select the same tasks as
 * were selected before (which are to be returned by the getTaskListSelections: method prior to
 * reloading the file. Tasks that change (i.e., are completed or otherwise modified) or removed 
 * from the list will not be selected after reload. For duplicate tasks (those with identical
 * raw text), the first of the duplicate tasks will be selected.
 */
- (void)setTaskListSelections:(NSArray*)taskListSelectedItems;

#pragma mark - Undo/Redo Methods

/*!
 * @method replaceTasks:withTasks:
 * @abstract This method replaces one array of tasks with another in the task list.
 * It is used for undo/redo operations, namely to undo the reload file command.
 */

- (void)replaceAllTasks:(NSArray*)newTasks;

/*!
 * @method replaceTasks:withTasks:
 * @abstract This method replaces one array of tasks with another in the task list. 
 * It is used for undo/redo operations.
 */
- (void)replaceTasks:(NSArray*)oldTasks withTasks:(NSArray*)newTasks;

/*!
 * @method addTasks:
 * @abstract This method adds an array of tasks to the task list.
 * It is used for undo/redo operations.
 */
- (void)addTasks:(NSArray*)newTasks;

/*!
 * @method addTasks:
 * @abstract This method removes an array of tasks from the task list.
 * It is used for undo/redo operations.
 */
- (void)removeTasks:(NSArray*)oldTasks;

/*!
 * @method addTasks:
 * @abstract This method performs and undo for the archive command.
 * It is used for undo/redo operations.
 */
- (void)undoArchiveTasks:(NSArray*)archivedTasks fromArchiveFile:(NSString*)archiveFilePath;

#pragma mark - Add/Remove Task(s) methods

/*!
 * @method createWorkingTaskWithRawText:createWorkingTaskWithRawText
 * @abstract Creates a task object to be inserted into the task list.
 * @param rawText The text to base the task on
 * @param newTaskId The (zero-based) numerical position of the task within the todo.txt file.
 */
- (TTMTask*)createWorkingTaskWithRawText:(NSString*)rawText withTaskId:(NSUInteger)newTaskId;

/*!
 * @method moveFocusToNewTaskTextField:
 * @abstract Moves focus to the new task text field so the user can type in a new task.
 */
- (IBAction)moveFocusToNewTaskTextField:(id)sender;

/*!
 * @method removeAllTasks:
 * @abstract Removes all tasks from the task list.
 * @discussion This method is called before a todo.txt file is loaded.
 */
- (void)removeAllTasks;

/*!
 * @method addTasksFromArray:removeAllTasksFirst:undoActionName
 * @abstract Add tasks from an array to the task list.
 * @param rawTextStrings The array of tasks' raw text strings.
 * @param removeAllRecordsFirst Set to YES if all records should be removed prior to adding tasks.
 * @param undoActionName Set to undo action name; blank if operation is not undoable
 */
- (void)addTasksFromArray:(NSArray*)rawTextStrings
      removeAllTasksFirst:(BOOL)removeAllRecordsFirst
           undoActionName:(NSString*)undoActionName;

/*!
 * @method addNewTask:
 * @abstract Adds a new task to the task list based on the content of the text field.
 */
- (IBAction)addNewTask:(id)sender;

/*!
 * @method tabFromTextFieldToTaskList:
 * @abstract Simulate a tab keypress to move from the text field to the task list.
 * @discussion This method is optionally called in the addNewTask: method.
 */
- (void)tabFromTextFieldToTaskList;

/*!
 * @method addNewTasksFromClipboard:
 * @abstract Adds tasks on the clipboard (one or more tasks separated by line breaks)
 * to the task lis
Download .txt
gitextract_uzrkr__8/

├── .gitignore
├── LICENSE.md
├── README.md
├── Sparkle.framework/
│   └── Versions/
│       └── A/
│           ├── Headers/
│           │   ├── SUAppcast.h
│           │   ├── SUAppcastItem.h
│           │   ├── SUErrors.h
│           │   ├── SUExport.h
│           │   ├── SUStandardVersionComparator.h
│           │   ├── SUUpdater.h
│           │   ├── SUVersionComparisonProtocol.h
│           │   ├── SUVersionDisplayProtocol.h
│           │   └── Sparkle.h
│           ├── Modules/
│           │   └── module.modulemap
│           ├── PrivateHeaders/
│           │   └── SUUnarchiver.h
│           ├── Resources/
│           │   ├── Autoupdate.app/
│           │   │   └── Contents/
│           │   │       ├── Info.plist
│           │   │       ├── MacOS/
│           │   │       │   └── Autoupdate
│           │   │       ├── PkgInfo
│           │   │       └── Resources/
│           │   │           ├── AppIcon.icns
│           │   │           ├── SUStatus.nib
│           │   │           ├── ar.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ca.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── cs.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── da.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── de.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── el.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── en.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── es.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── fi.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── fr.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── he.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── is.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── it.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ja.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ko.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── nb.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── nl.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── pl.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── pt_BR.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── pt_PT.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ro.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── ru.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── sk.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── sl.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── sv.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── th.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── tr.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── uk.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           ├── zh_CN.lproj/
│           │   │           │   └── Sparkle.strings
│           │   │           └── zh_TW.lproj/
│           │   │               └── Sparkle.strings
│           │   ├── Info.plist
│           │   ├── SUModelTranslation.plist
│           │   ├── SUStatus.nib
│           │   ├── ar.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ca.lproj/
│           │   │   └── Sparkle.strings
│           │   ├── cs.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── da.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── de.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── el.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── en.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── es.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── fi.lproj/
│           │   │   └── Sparkle.strings
│           │   ├── fr.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── he.lproj/
│           │   │   └── Sparkle.strings
│           │   ├── is.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── it.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ja.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ko.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── nb.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── nl.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── pl.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── pt_BR.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── pt_PT.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ro.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── ru.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── sk.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── sl.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── sv.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── th.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── tr.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── uk.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   ├── zh_CN.lproj/
│           │   │   ├── SUAutomaticUpdateAlert.nib
│           │   │   ├── SUUpdateAlert.nib
│           │   │   ├── SUUpdatePermissionPrompt.nib
│           │   │   └── Sparkle.strings
│           │   └── zh_TW.lproj/
│           │       ├── SUAutomaticUpdateAlert.nib
│           │       ├── SUUpdateAlert.nib
│           │       ├── SUUpdatePermissionPrompt.nib
│           │       └── Sparkle.strings
│           └── Sparkle
├── TodoTxtMac/
│   ├── Base.lproj/
│   │   ├── MainMenu.xib
│   │   ├── RelativeDates.strings
│   │   └── TTMDocument.xib
│   ├── FontNameTransformer.h
│   ├── FontNameTransformer.m
│   ├── Images.xcassets/
│   │   └── AppIcon.appiconset/
│   │       └── Contents.json
│   ├── NSDate+RelativeDates.h
│   ├── NSDate+RelativeDates.m
│   ├── NSMutableAttributableString+ColorRegExMatches.h
│   ├── NSMutableAttributableString+ColorRegExMatches.m
│   ├── NSUserDefaults+myColorSupport.h
│   ├── NSUserDefaults+myColorSupport.m
│   ├── RegExCategories.h
│   ├── RegExCategories.m
│   ├── RelativeDates.strings
│   ├── TTMAppController.h
│   ├── TTMAppController.m
│   ├── TTMAppDelegate.h
│   ├── TTMAppDelegate.m
│   ├── TTMDateUtility.h
│   ├── TTMDateUtility.m
│   ├── TTMDocument.h
│   ├── TTMDocument.m
│   ├── TTMDocumentStatusBarText.h
│   ├── TTMDocumentStatusBarText.m
│   ├── TTMFieldEditor.h
│   ├── TTMFieldEditor.m
│   ├── TTMFilterPredicates.h
│   ├── TTMFilterPredicates.m
│   ├── TTMFilters.xib
│   ├── TTMFiltersController.h
│   ├── TTMFiltersController.m
│   ├── TTMFindReplace.xib
│   ├── TTMPredicateEditorCompletedRowTemplate.h
│   ├── TTMPredicateEditorCompletedRowTemplate.m
│   ├── TTMPredicateEditorDateRowTemplate.h
│   ├── TTMPredicateEditorDateRowTemplate.m
│   ├── TTMPredicateEditorDueRowTemplate.h
│   ├── TTMPredicateEditorDueRowTemplate.m
│   ├── TTMPredicateEditorHiddenRowTemplate.h
│   ├── TTMPredicateEditorHiddenRowTemplate.m
│   ├── TTMPredicateEditorTextRowTemplate.h
│   ├── TTMPredicateEditorTextRowTemplate.m
│   ├── TTMPredicateEditorThresholdRowTemplate.h
│   ├── TTMPredicateEditorThresholdRowTemplate.m
│   ├── TTMPreferences.xib
│   ├── TTMPreferencesController.h
│   ├── TTMPreferencesController.m
│   ├── TTMTableView.h
│   ├── TTMTableView.m
│   ├── TTMTableViewDelegate.h
│   ├── TTMTableViewDelegate.m
│   ├── TTMTask.h
│   ├── TTMTask.m
│   ├── TTMTasklistMetadata.h
│   ├── TTMTasklistMetadata.m
│   ├── TTMTasklistMetadata.xib
│   ├── TodoTxtMac-Info.plist
│   ├── TodoTxtMac-Prefix.pch
│   ├── TodoTxtMac.entitlements
│   ├── en.lproj/
│   │   ├── Credits.rtf
│   │   ├── InfoPlist.strings
│   │   └── RelativeDates.strings
│   └── main.m
├── TodoTxtMac.xcodeproj/
│   ├── project.pbxproj
│   └── project.xcworkspace/
│       ├── contents.xcworkspacedata
│       └── xcshareddata/
│           └── TodoTxtMac.xccheckout
├── TodoTxtMacTests/
│   ├── TTMDateUtility_UnitTests.m
│   ├── TTMTask_AppendText_UnitTests.m
│   ├── TTMTask_CompletionDate_UnitTests.m
│   ├── TTMTask_Contexts_UnitTests.m
│   ├── TTMTask_CreationDate_UnitTests.m
│   ├── TTMTask_DecreasePriority_UnitTests.m
│   ├── TTMTask_DecrementDueDate_UnitTests.m
│   ├── TTMTask_DecrementThresholdDate_UnitTests.m
│   ├── TTMTask_DueDate_UnitTests.m
│   ├── TTMTask_DueState_UnitTests.m
│   ├── TTMTask_IncreasePriority_UnitTests.m
│   ├── TTMTask_IncrementDueDate_UnitTests.m
│   ├── TTMTask_IncrementThresholdDate_UnitTests.m
│   ├── TTMTask_Init_UnitTests.m
│   ├── TTMTask_IsCompleted_UnitTests.m
│   ├── TTMTask_IsHidden_UnitTests.m
│   ├── TTMTask_MarkComplete_UnitTests.m
│   ├── TTMTask_MarkIncomplete_UnitTests.m
│   ├── TTMTask_Postpone_UnitTests.m
│   ├── TTMTask_PrependText_UnitTests.m
│   ├── TTMTask_Priority_UnitTests.m
│   ├── TTMTask_Projects_UnitTests.m
│   ├── TTMTask_RemoveDueDate_UnitTests.m
│   ├── TTMTask_RemovePriority_UnitTests.m
│   ├── TTMTask_RemoveThresholdDate_UnitTests.m
│   ├── TTMTask_ReplaceText_UnitTests.m
│   ├── TTMTask_SetDueDate_UnitTests.m
│   ├── TTMTask_SetThresholdDate_UnitTests.m
│   ├── TTMTask_ThresholdDate_UnitTests.m
│   ├── TTMTask_ThresholdState_UnitTests.m
│   ├── TTMTask_ToggleCompletion_UnitTests.m
│   ├── TTMTasklistMetadata_UnitTests.m
│   ├── TodoTxtMacTests-Info.plist
│   └── en.lproj/
│       └── InfoPlist.strings
└── dsa_pub.pem
Download .txt
SYMBOL INDEX (4 symbols across 3 files)

FILE: TodoTxtMac/FontNameTransformer.h
  function interface (line 52) | interface FontNameTransformer : NSValueTransformer {

FILE: TodoTxtMac/TTMDocument.h
  type TTMTaskListSortType (line 61) | typedef enum : NSUInteger {

FILE: TodoTxtMac/TTMTask.h
  type TTMDueState (line 59) | typedef enum : NSUInteger {
  type TTMThresholdState (line 67) | typedef enum : NSUInteger {
Condensed preview — 266 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,599K chars).
[
  {
    "path": ".gitignore",
    "chars": 733,
    "preview": "# taken from http://blog.illuminex.com/2009/10/better-sample-gitignore-file-for-xcode.html\n\n# Mac OS X Finder and whatno"
  },
  {
    "path": "LICENSE.md",
    "chars": 1783,
    "preview": "TodoTxtMac: A Todo.txt todo manager for Mac OS X\n\n\n\n\nCopyright (C) 2014 Michael Descy\n\nThis program is free software: yo"
  },
  {
    "path": "README.md",
    "chars": 9961,
    "preview": "# TodoTxtMac\n\n# Overview\n\nTodoTxtMac is a minimalist, keyboard-driven to-do manager for Mac OS X that conforms to the to"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/SUAppcast.h",
    "chars": 590,
    "preview": "//\n//  SUAppcast.h\n//  Sparkle\n//\n//  Created by Andy Matuschak on 3/12/06.\n//  Copyright 2006 Andy Matuschak. All right"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/SUAppcastItem.h",
    "chars": 1536,
    "preview": "//\n//  SUAppcastItem.h\n//  Sparkle\n//\n//  Created by Andy Matuschak on 3/12/06.\n//  Copyright 2006 Andy Matuschak. All r"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/SUErrors.h",
    "chars": 1034,
    "preview": "//\n//  SUErrors.h\n//  Sparkle\n//\n//  Created by C.W. Betts on 10/13/14.\n//  Copyright (c) 2014 Sparkle Project. All righ"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/SUExport.h",
    "chars": 302,
    "preview": "//\n//  SUExport.h\n//  Sparkle\n//\n//  Created by Jake Petroules on 2014-08-23.\n//  Copyright (c) 2014 Sparkle Project. Al"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/SUStandardVersionComparator.h",
    "chars": 952,
    "preview": "//\n//  SUStandardVersionComparator.h\n//  Sparkle\n//\n//  Created by Andy Matuschak on 12/21/07.\n//  Copyright 2007 Andy M"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/SUUpdater.h",
    "chars": 12432,
    "preview": "//\n//  SUUpdater.h\n//  Sparkle\n//\n//  Created by Andy Matuschak on 1/4/06.\n//  Copyright 2006 Andy Matuschak. All rights"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/SUVersionComparisonProtocol.h",
    "chars": 703,
    "preview": "//\n//  SUVersionComparisonProtocol.h\n//  Sparkle\n//\n//  Created by Andy Matuschak on 12/21/07.\n//  Copyright 2007 Andy M"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/SUVersionDisplayProtocol.h",
    "chars": 577,
    "preview": "//\n//  SUVersionDisplayProtocol.h\n//  EyeTV\n//\n//  Created by Uli Kusterer on 08.12.09.\n//  Copyright 2009 Elgato System"
  },
  {
    "path": "Sparkle.framework/Versions/A/Headers/Sparkle.h",
    "chars": 626,
    "preview": "//\n//  Sparkle.h\n//  Sparkle\n//\n//  Created by Andy Matuschak on 3/16/06. (Modified by CDHW on 23/12/07)\n//  Copyright 2"
  },
  {
    "path": "Sparkle.framework/Versions/A/Modules/module.modulemap",
    "chars": 95,
    "preview": "framework module Sparkle {\n  umbrella header \"Sparkle.h\"\n\n  export *\n  module * { export * }\n}\n"
  },
  {
    "path": "Sparkle.framework/Versions/A/PrivateHeaders/SUUnarchiver.h",
    "chars": 941,
    "preview": "//\n//  SUUnarchiver.h\n//  Sparkle\n//\n//  Created by Andy Matuschak on 3/16/06.\n//  Copyright 2006 Andy Matuschak. All ri"
  },
  {
    "path": "Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/Info.plist",
    "chars": 1522,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Sparkle.framework/Versions/A/Resources/Autoupdate.app/Contents/PkgInfo",
    "chars": 8,
    "preview": "APPL????"
  },
  {
    "path": "Sparkle.framework/Versions/A/Resources/Info.plist",
    "chars": 1234,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "Sparkle.framework/Versions/A/Resources/SUModelTranslation.plist",
    "chars": 11858,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "TodoTxtMac/Base.lproj/MainMenu.xib",
    "chars": 38224,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "TodoTxtMac/Base.lproj/TTMDocument.xib",
    "chars": 24580,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3.0\" toolsVersion"
  },
  {
    "path": "TodoTxtMac/FontNameTransformer.h",
    "chars": 2665,
    "preview": "/*\n     File: FontNameTransformer.h\n Abstract: Value transformer that turns fonts into a human-readable string with the "
  },
  {
    "path": "TodoTxtMac/FontNameTransformer.m",
    "chars": 2998,
    "preview": "/*\n     File: FontNameTransformer.m\n Abstract: Value transformer that turns fonts into a human-readable string with the "
  },
  {
    "path": "TodoTxtMac/Images.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 1300,
    "preview": "{\n  \"images\" : [\n    {\n      \"size\" : \"16x16\",\n      \"idiom\" : \"mac\",\n      \"filename\" : \"icon_16x16.png\",\n      \"scale\""
  },
  {
    "path": "TodoTxtMac/NSDate+RelativeDates.h",
    "chars": 2347,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2016 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/NSDate+RelativeDates.m",
    "chars": 3324,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.h",
    "chars": 2697,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/NSMutableAttributableString+ColorRegExMatches.m",
    "chars": 2690,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/NSUserDefaults+myColorSupport.h",
    "chars": 377,
    "preview": "// This code is lifted from Apple's Developer Documenation.\n// Source: https://developer.apple.com/library/mac/documenta"
  },
  {
    "path": "TodoTxtMac/NSUserDefaults+myColorSupport.m",
    "chars": 697,
    "preview": "// This code is lifted from Apple's Developer Documenation.\n// Source: https://developer.apple.com/library/mac/documenta"
  },
  {
    "path": "TodoTxtMac/RegExCategories.h",
    "chars": 11362,
    "preview": "//\n//  RegExCategories.h\n//\n//  https://github.com/bendytree/Objective-C-RegEx-Categories\n//\n//\n//  The MIT License (MIT"
  },
  {
    "path": "TodoTxtMac/RegExCategories.m",
    "chars": 9192,
    "preview": "//\n//  RegExCategories.m\n//\n//  https://github.com/bendytree/Objective-C-RegEx-Categories\n//\n//\n//  The MIT License (MIT"
  },
  {
    "path": "TodoTxtMac/RelativeDates.strings",
    "chars": 568,
    "preview": "/* Fri */\n\"Fri\" = \"Fri\";\n\n/* Friday */\n\"Friday\" = \"Friday\";\n\n/* Mon */\n\"Mon\" = \"Mon\";\n\n/* Monday */\n\"Monday\" = \"Monday\";"
  },
  {
    "path": "TodoTxtMac/TTMAppController.h",
    "chars": 5244,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMAppController.m",
    "chars": 10306,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMAppDelegate.h",
    "chars": 2213,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMAppDelegate.m",
    "chars": 3389,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMDateUtility.h",
    "chars": 5409,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMDateUtility.m",
    "chars": 8931,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMDocument.h",
    "chars": 18291,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMDocument.m",
    "chars": 67365,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMDocumentStatusBarText.h",
    "chars": 4900,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMDocumentStatusBarText.m",
    "chars": 9438,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMFieldEditor.h",
    "chars": 2984,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMFieldEditor.m",
    "chars": 9514,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMFilterPredicates.h",
    "chars": 6230,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMFilterPredicates.m",
    "chars": 6610,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMFilters.xib",
    "chars": 526690,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "TodoTxtMac/TTMFiltersController.h",
    "chars": 3097,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMFiltersController.m",
    "chars": 4586,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMFindReplace.xib",
    "chars": 5966,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorCompletedRowTemplate.h",
    "chars": 2241,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorCompletedRowTemplate.m",
    "chars": 5046,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorDateRowTemplate.h",
    "chars": 2120,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorDateRowTemplate.m",
    "chars": 3290,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorDueRowTemplate.h",
    "chars": 2239,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorDueRowTemplate.m",
    "chars": 6137,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorHiddenRowTemplate.h",
    "chars": 2238,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorHiddenRowTemplate.m",
    "chars": 4779,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorTextRowTemplate.h",
    "chars": 2120,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2016 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorTextRowTemplate.m",
    "chars": 3752,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2016 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorThresholdRowTemplate.h",
    "chars": 2251,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPredicateEditorThresholdRowTemplate.m",
    "chars": 7055,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPreferences.xib",
    "chars": 185366,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "TodoTxtMac/TTMPreferencesController.h",
    "chars": 4962,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMPreferencesController.m",
    "chars": 5947,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTableView.h",
    "chars": 3158,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTableView.m",
    "chars": 8980,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTableViewDelegate.h",
    "chars": 2238,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTableViewDelegate.m",
    "chars": 6077,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTask.h",
    "chars": 13975,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTask.m",
    "chars": 31826,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTasklistMetadata.h",
    "chars": 3895,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTasklistMetadata.m",
    "chars": 5722,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMac/TTMTasklistMetadata.xib",
    "chars": 150871,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.Cocoa.XIB\" version=\"3"
  },
  {
    "path": "TodoTxtMac/TodoTxtMac-Info.plist",
    "chars": 1969,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "TodoTxtMac/TodoTxtMac-Prefix.pch",
    "chars": 172,
    "preview": "//\n//  Prefix header\n//\n//  The contents of this file are implicitly included at the beginning of every source file.\n//\n"
  },
  {
    "path": "TodoTxtMac/TodoTxtMac.entitlements",
    "chars": 181,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "TodoTxtMac/en.lproj/Credits.rtf",
    "chars": 7495,
    "preview": "{\\rtf1\\ansi\\ansicpg1252\\cocoartf1404\\cocoasubrtf340\n{\\fonttbl\\f0\\fswiss\\fcharset0 Helvetica;\\f1\\fmodern\\fcharset0 Courie"
  },
  {
    "path": "TodoTxtMac/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "TodoTxtMac/main.m",
    "chars": 247,
    "preview": "//\n//  main.m\n//  TodoTxtMac\n//\n//  Created by Michael Descy on 2/18/14.\n//  Copyright (c) 2014 Michael Descy. All right"
  },
  {
    "path": "TodoTxtMac.xcodeproj/project.pbxproj",
    "chars": 61750,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "TodoTxtMac.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 155,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:TodoTxtMac.xcod"
  },
  {
    "path": "TodoTxtMac.xcodeproj/project.xcworkspace/xcshareddata/TodoTxtMac.xccheckout",
    "chars": 1489,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "TodoTxtMacTests/TTMDateUtility_UnitTests.m",
    "chars": 5024,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_AppendText_UnitTests.m",
    "chars": 3277,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_CompletionDate_UnitTests.m",
    "chars": 5872,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_Contexts_UnitTests.m",
    "chars": 3733,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_CreationDate_UnitTests.m",
    "chars": 6129,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_DecreasePriority_UnitTests.m",
    "chars": 4093,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_DecrementDueDate_UnitTests.m",
    "chars": 6361,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_DecrementThresholdDate_UnitTests.m",
    "chars": 3656,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_DueDate_UnitTests.m",
    "chars": 4360,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_DueState_UnitTests.m",
    "chars": 3745,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_IncreasePriority_UnitTests.m",
    "chars": 4093,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_IncrementDueDate_UnitTests.m",
    "chars": 6361,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_IncrementThresholdDate_UnitTests.m",
    "chars": 3652,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_Init_UnitTests.m",
    "chars": 4618,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_IsCompleted_UnitTests.m",
    "chars": 5037,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_IsHidden_UnitTests.m",
    "chars": 3634,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2016 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_MarkComplete_UnitTests.m",
    "chars": 3434,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_MarkIncomplete_UnitTests.m",
    "chars": 3101,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_Postpone_UnitTests.m",
    "chars": 6248,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_PrependText_UnitTests.m",
    "chars": 5030,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_Priority_UnitTests.m",
    "chars": 4214,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_Projects_UnitTests.m",
    "chars": 3733,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_RemoveDueDate_UnitTests.m",
    "chars": 4719,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_RemovePriority_UnitTests.m",
    "chars": 3179,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_RemoveThresholdDate_UnitTests.m",
    "chars": 4859,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_ReplaceText_UnitTests.m",
    "chars": 3219,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_SetDueDate_UnitTests.m",
    "chars": 4959,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_SetThresholdDate_UnitTests.m",
    "chars": 4788,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_ThresholdDate_UnitTests.m",
    "chars": 4486,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_ThresholdState_UnitTests.m",
    "chars": 4872,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTask_ToggleCompletion_UnitTests.m",
    "chars": 3156,
    "preview": "/**\n * @author Michael Descy\n * @copyright 2014-2015 Michael Descy\n * @discussion Dual-licensed under the GNU General Pu"
  },
  {
    "path": "TodoTxtMacTests/TTMTasklistMetadata_UnitTests.m",
    "chars": 4178,
    "preview": "//\n//  TTMMetadataTests.m\n//  TodoTxtMac\n//\n//  Created by Michael Descy on 8/9/14.\n//  Copyright (c) 2014 Michael Descy"
  },
  {
    "path": "TodoTxtMacTests/TodoTxtMacTests-Info.plist",
    "chars": 674,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "TodoTxtMacTests/en.lproj/InfoPlist.strings",
    "chars": 45,
    "preview": "/* Localized versions of Info.plist keys */\n\n"
  },
  {
    "path": "dsa_pub.pem",
    "chars": 1178,
    "preview": "-----BEGIN PUBLIC KEY-----\nMIIDOjCCAi0GByqGSM44BAEwggIgAoIBAQDhCUQCiF8i1StxL9w/t3t7H8hYn19U\ncpzRmdTCL3w84xFpYSrmTSUoa/7l"
  }
]

// ... and 148 more files (download for full content)

About this extraction

This page contains the full source code of the mjdescy/TodoTxtMac GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 266 files (1.5 MB), approximately 272.6k tokens, and a symbol index with 4 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!