QuickQuestion

The qq script and related extensions are designed to keep an archive of files with questions as the filename and answers as the content. It works well with Notational Velocity and nvALT, but can function as an archive of knowledge with nothing but a Mac and a command line. Scripts are included for Quicksilver, LaunchBar and Alfred, as well as a command line tool.

The story behind the script is: I forget everything. I forget what I was working on last night. I forget where I left important things. I forget how I solved a major problem and have to work it out again next time it comes up. I forget where I saved the perfect settings I found for h.264 compression. You get the picture. So I’ve started building an archive of plain text files with questions and answers, and a system which makes it easy to add new knowledge at any time. The question format makes it easy to query, even when I don’t remember the answer at all.

The system is very simple. A bunch of plain text files, each titled with one question and containing one answer. Searching and sorting is handled my the mdfind Spotlight interface with scripts and extensions that focus the search to a narrow scope with predefined options. The knowledgebase that’s built is bulletproof and portable, scriptable and easily searchable. Plus, it works the same way as Notational Velocity, so they make a great pair.

I use it with nvALT and sync to Simplenote and Dropbox, which means I can enter new questions and their answers from any mobile device or remote computer, in addition to being able to use the command line tool, Quicksilver actions, LaunchBar actions and Alfred extensions. It keeps me sane.

Installation

Command line
Put the qq script into a folder in your path and make it executable with chmod a+x /path/to/qq. Edit the script to set the location of your notes folder and the extension you use. You may want to set a different preferred “question” prefix if you already have one (or don’t want filenames that need constant escaping).
Quicksilver
Move the two .scpt files into ~/Library/Application Support/Quicksilver/Actions/. These scripts require that the above command line script is in place and need to be edited with the proper full path to the script.
LaunchBar
Move the two .scpt files into ~/Library/Application Support/LaunchBar/Actions/. These scripts require that the above command line script is in place and need to be edited with the proper full path to the script.
Alfred
The Alfred extensions are standalone and do note require the qq script to be installed. Simply import the extensions into Alfred and the qq and qa commands will be available. Once imported, there are several configuration variables that need to be set in the top of the script.
Notational Velocity/nvALT
By nature, you don’t need anything special to use this system with NV. You just need to save your notes to plain text files if you want them to be accessible to mdfind and other system tools.
To get simple command line access to the question in your NV folder, set up the configuration in the qq script above to point to your NV notes folder. This will allow you to run speedy queries confined to just that directory, and enter notes quickly from other sources. Notes entered from the command line or LaunchBar/Alfred will show up instantly in your NV notes list.

CONFIGURATION

Configuration is done via environment variables:

QQ_NOTES_DIR - Path to Markdown files
QQ_NOTES_EXT - Extension of answer files (default md)
QQ_NOTES_PRE - Prefix of question files (default ??)
QQ_EDITOR    - Text editor to use (default $EDITOR)
QQ_USE_FZF   - If fzf is available, it will be used by default. Set this 
               to false to override

Example:

export QQ_NOTES_DIR="/Users/ttscoff/Dropbox/Notes"
export QQ_NOTES_EXT="md"

Usage

Command line
Add questions and answers using qq -a "Question" "Answer", e.g. qq "What is the answer to life, the universe and everything?" "42". If -a is specified without any additional arguments, qq will enter interactive mode and ask you for the question and the answer individually, accepting input from STDIN.
Ask a question using qq fragmented question, e.g. qq meaning universe. See the Querying section for more information on composing fragmented queries.
Quicksilver
Add a question and answer by launching Quicksilver and entering a string in the format “question: answer”, e.g. “what is the meaning of life, the universe and everything: 42” (activate text entry with the “’” key). Press tab, select the “Quick Answer” action and hit Enter.
Ask a question by typing launching Quicksilver and entering a fragmented query (activate text entry with the “’” key). Press tab, select the “Quick Question” action and hit Enter.
LaunchBar
Add a question and answer by launching LaunchBar and typing “qa”. Select the “Quick Answer” action and hit Space. Then type a string in the format “question: answer”, e.g. “what is the meaning of life, the universe and everything: 42”.
Ask a question by typing “qq” and selecting the “Quick Question” action. Hit space and type a fragmented query.
Alfred
To add a question and answer to your archive, open Alfred and type “qa”. Enter the question and answer in the format “question: answer”, e.g. “qa is there anybody out there?: nope”.
To query your archive, type “qq” and enter a fragmented query.
Notational Velocity/nvALT
Notes will be prefixed with the string specified in the configuration (default “??”). You can start a search with the prefix and follow it with a fragmented query to find the question (and answer) you’re looking for. Add new questions and answers by typing the prefix and the question in the search field, press enter to create a new note, and type the answer and any additional meta.

Composing questions

Ask yourself what question the search for this answer began with. Will that be the question you ask again when you’ve forgotten the answer a year (or month) later? Think about how you, personally, would phrase the question and shape it around keywords that you’re pretty sure you would repeat.

Keep your questions in a natural language format, but avoid contractions and use “who, when, where, what, how and why” as much as possible. These words make it easy to sort out different types of questions about the same subject.

Querying

When querying, only use operative terms to get the best results. “Where did I leave my glasses” will return poor results if the question you labeled it with was “Where did I put my glasses”. Instead, query “where glasses” and you’ll find the note instantly.

Running qq -l at the command line with no arguments will list all of the questions and their answers in your archive. This can be handy for using with grep to parse out pieces of questions and/or answers that you couldn’t find otherwise.

Additional meta

You can add additional meta within the contents of the file to help in locating the answer later by using the format @(meta information). Anything within the parenthesis will be included in search, but the whole tag will be excluded from results in the qq script and the LaunchBar/Alfred actions.

An example of this would be a question like “What brand of cleaner did I use during the move?” The answer you gave was a cleaning solution you were really impressed with. A year later the only thing you may remember to ask is “cleaner,” but you might not even remember that was the term you used. So you add “@(solution cleaning favorite)” to the answer. Now you can search for “favorite cleaning” or “cleaning solution” and still get the question you were looking for. It’s similar to using tags, but you can be more verbose without cluttering up your pool of existing tags. In the example case, you can also use just the root or part of a word, e.g. qq fav clean to expand matching possibilities.

Copy to clipboard

If your answer includes a command, url or other piece that you probably want to grab, you can surround it with @copy(part to copy) and the contents of the tag will be copied to the clipboard when the question is answered. The ‘@copy(‘ and ‘)’ parts will be stripped from the answer given, but its contents will remain inline.

If you add one or more @open() tags, the contents will be passed to the open command with the -g flag (open in background). You can use this to add related urls to the query. It’s not a perfect system because if you ask a broad question and get 20 answers, each with one or more urls, they’ll all open. But it’s handy once in a while.

Redacting answers

If you’re using Quicksilver, LaunchBar or Alfred it’s assumed that you can locate the question file and open it in an editor of choice easily enough. It’s even simpler if your questions are stored in Notational Velocity/nvALT as you can edit them at the same time you search for them.

From the command line you can use the -e argument to open the first result for the following query in the editor you specified in the configuration (mate by default). It expects a command-line tool, not an OS X application name. Most editors have these available.

Changelog

Click to expand

2.1.9

2023-09-07 11:02

NEW

  • Add –templates-c to get a completion-compatible list of available templates

2.1.8

2023-05-31 11:58

FIXED

  • Colors.rb error when code is integer

2.1.7

2023-05-29 12:59

FIXED

  • Handle variable replacements on lines containing colons outside of variable

2.1.6

2023-05-29 12:42

FIXED

  • Remove empty undefined variables with no default

2.1.5

2023-04-12 15:13

FIXED

  • Allow tilde in path to editor

2.1.4

2023-03-07 12:52

NEW

  • A theme file is automatically created where you can change the default output of any color that Howzit outputs. They can be 2-3 digit ANSI escape codes, or ‘#XXXXXX’ RGB hex codes

2.1.3

2023-03-07 11:21

FIXED

  • Annoying warning about color template format string having too many arguments

2.1.2

2023-03-07 10:24

IMPROVED

  • Merge metadata into named variables so they’re also available as ${NAME}

2.1.1

2023-03-07 09:47

FIXED

  • Allow variables names to contain numbers and underscores

2.1.0

2023-03-07 09:24

NEW

  • Use TOPIC_TITLE (var1, var2) to have access to ${var1} ${var2} in text and scripts, populated with positional variables on the command line
  • Add a default (fallback) value to any variable placeholder with ${var_name:default value}

2.0.34

2023-01-15 13:32

FIXED

  • Fail to partial match include commands after running fzf

2.0.33

2023-01-15 13:26

2.0.32

2023-01-15 10:46

IMPROVED

  • When using fzf chooser, make matching exact to avoid running multiple topics

2.0.31

2022-08-31 07:17

FIXED

  • Color template formatting of task output

2.0.30

2022-08-31 07:15

FIXED

  • Formatting of –help and –version commands

2.0.29

2022-08-30 04:20

NEW

  • –yes flag will answer yes to all prompts when executing
  • –force flag will continue executing directives after an error

IMPROVED

  • A non-zero exit status on a run directive will stop processing additional directives
  • A little extra output formatting, more descriptive results logging

2.0.28

2022-08-29 18:42

IMPROVED

  • If a topic runs multiple directives, stop processing them if one returns a non-zero exit status

2.0.27

2022-08-23 12:25

IMPROVED

  • Code cleanup

2.0.26

2022-08-23 11:36

IMPROVED

  • Add ctrl-a/d bindings to fzf menu for select/deselect all

2.0.25

2022-08-09 12:46

FIXED

  • Template metadata inheritence

2.0.24

2022-08-09 09:04

FIXED

  • Avoid reading upstream files multiple times

2.0.23

2022-08-09 05:51

FIXED

  • –grep function regression

2.0.22

2022-08-08 13:49

IMPROVED

  • Paginate output of –templates

FIXED

  • –templates attempting to create new build note
  • Fix handling of paths when the same as note_file

2.0.21

2022-08-08 13:16

IMPROVED

  • Use os-agnostic copy function for –hook
  • Rename link title for –hook

2.0.20

2022-08-08 11:38

NEW

  • –hook command for macOS to copy a link to the build note to clipboard

FIXED

  • Error on –edit-config
  • Fzf preview empty

2.0.19

2022-08-08 06:18

IMPROVED

  • Sort options in help output

2.0.18

2022-08-08 03:48

NEW

  • Use –ask to require confirmation of all tasks when running a topic

2.0.17

2022-08-07 06:09

2.0.16

2022-08-07 06:05

NEW

  • –edit-template NAME will open a template in your editor, offering to create it if missing

FIXED

  • If –show-code is given (or :show_all_code: is set to true), show content of @directives instead of title

2.0.15

2022-08-05 17:16

IMPROVED

  • -R can take an argument to filter results
  • Show a topic preview when using fzf to select from available topics
  • Paginate help output
  • Refactor Topic.run

FIXED

  • Invalid options for more pager
  • Error running grep command
  • Show method not accepting paginate option

2.0.14

2022-08-05 13:24

FIXED

  • Travis CI fixes

2.0.13

2022-08-05 13:19

IMPROVED

  • Add tests for more ruby versions via Docker

2.0.12

2022-08-05 11:27

IMPROVED

  • Show how many tasks will be included when requesting confirmation for an include? directive

2.0.11

2022-08-05 11:21

IMPROVED

  • Update fish completions with all current command line options

2.0.10

2022-08-05 08:17

IMPROVED

  • Provide more helpful feedback if no content is found in build note
  • Confirm whether the user wants to create a new note when one isn’t found

2.0.9

2022-08-05 07:29

IMPROVED

  • Avoid error trace on interrupt
  • Better stty settings for y/n prompt
  • Better coloring of default options in dialogs

FIXED

  • Encoding issues with older ruby versions
  • Globbing for build notes was picking up files that contained “build” but not at the beginning of the filename

2.0.8

2022-08-04 13:28

FIXED

  • Bugfixes

2.0.7

2022-08-04 13:04

NEW

  • –debug flag (shortcut for :log_level: 0)

IMPROVED

  • Console output now gets log levels, so :log_level: config option and –quiet/verbose have more utility

2.0.6

2022-08-04 11:08

2.0.5

2022-08-04 10:50

NEW

  • Make any task optional when running by adding a ? (@open?(…))
  • Optional tasks default to yes when you hit enter, invert by using a ! (@open?!(…)) to make default “no”

FIXED

  • Replace escaped newlines in task list output so that they don’t trigger a newline in the shell

2.0.4

2022-08-04 06:25

IMPROVED

  • Ask to open new buildnote for editing after creation

FIXED

  • Loop when creating new buildnote

2.0.3

2022-08-04 05:31

IMPROVED

  • General code cleanup
  • Attempt at os agnostic @copy command, hopefully works on Windows and Linux systems

FIXED

  • Not displaying action if title is missing

2.0.2

2022-08-03 18:26

IMPROVED

  • If a title is provided after an @command, display it instead of the contents when viewing

2.0.1

2022-08-03 12:46

FIXED

  • Failure to create new notes file when one isn’t found

2.0.0

2022-08-03 12:37

FIXED

  • Positional arguments not rendering in tasks
  • Fix degradation where arguments are empty

1.2.19

2022-08-03 12:18

FIXED

  • –config-get returning non-default options

1.2.18

2022-08-03 12:13

FIXED

  • Unwritable content property

1.2.17

2022-08-03 12:10

FIXED

  • Variables in topics not being replaced with metadata
  • Allow default response in yes/no prompt

1.2.16

2022-08-03 11:41

IMPROVED

  • Complete code refactoring

FIXED

  • Multiple includes of upstream files when templates are specified

1.2.15

2022-08-02 11:59

NEW

  • Option to set :header_format: to block for alternate topic title appearance

FIXED

  • Missing spacing around topic titles when displaying multiple topics

1.2.14

2022-08-02 11:01

NEW

  • Config option and flag to determine how to handle multiple results (first, best, all, choose)
  • –config-get and –config-set flags for working with config options

IMPROVED

  • Allow multiple selections when using fzf
  • Clean up newlines in output

1.2.13

2022-08-01 20:50

1.2.12

2022-08-01 16:23

IMPROVED

  • Replace ANSI escape codes with color template system
  • When @including an external file, if the file doesn’t contain any level 2+ headers, import it as plain text.

1.2.11

2022-08-01 08:23

IMPROVED

  • Code cleanup and refactoring

1.2.10

2022-08-01 07:45

FIXED

  • Headline formatting when iTerm markers are inserted

1.2.8

2022-08-01 07:01

FIXED

  • Frozen string error

1.2.6

2022-08-01 06:09

NEW

  • Use @before…@end and @after…@end to specify prerequisites and a post-run message. Topics with @before will require y/n verification before running

FIXED

  • ITerm markers weren’t being inserted when paging was off

1.2.3

2022-07-31 14:20

IMPROVED

  • Don’t include a topic multiple times in one display
  • Don’t execute nested topics more than once
  • Indicate nested includes in headers
  • Code cleanup

1.2.2

2022-07-31 08:56

  • Add -F option to pager setup (quit if less than one screen)

1.2.1

2022-07-31 05:12

  • Add handling for delta pager to not clear screen on exit

1.2.0

2022-07-31 04:59

  • Add grep feature, searches topic/content for pattern and displays matches (selection menu if multiple matches)

1.1.27

2022-01-17 11:45

NEW

  • Use fzf for menus if available
  • “@run() TITLE” will show TITLE instead of command when listing runnable topics
  • @include(FILENAME) will import an external file if the path exists

1.1.26

  • Fix for error in interactive build notes creation

1.1.25

  • Hide run block contents by default
  • :show_all_code: config setting to include run block contents
  • –show-code flag to display run block contents at runtime
  • Modify include display

1.1.24

  • Use ~/.config/howzit/ignore.yaml to ignore patterns when scanning for build notes
  • Use required and optional keys in templates to request that metadata be defined when importing
  • Allow templates to include other templates

1.1.23

  • Add flags to allow content to stay onscreen after exiting pager (less and bat)

1.1.21

  • Merge directive and block handling so execution order is sequential

1.1.20

  • Template functionality for including common tasks/topics

1.1.19

  • Add --upstream option to traverse up parent directories for additional build notes

1.1.15

  • Code refactoring/cleanup
  • Rename “sections” to “topics”
  • If no match found for topic search, only show error (:show_all_on_error: false option)

1.1.14

  • Fix removal of non-alphanumeric characters from titles
  • -s/–select option to display a menu of all available topics
  • Allow arguments to be passed after -- for variable substitution
  • Allow –matching TYPE to match first non-ambigous keyword match

1.1.13

  • –matching [fuzzy,beginswith,partial,exact] flag
  • –edit-config flag
  • sort flags in help

1.1.12

  • After consideration, remove full fuzzy matching. Too many positives for shorter strings.

1.1.11

  • Add full fuzzy matching for topic titles
  • Add @include(TOPIC) command to import another topic’s tasks

1.1.10

  • Add config file for default options

1.1.9

  • Use system instead of exec to allow multiple @run commands
  • Add code block runner

1.1.8

  • Add -e/--edit flag to open build notes in $EDITOR

1.1.7

  • Use exec for @run commands to allow interactive processes (e.g. vim)

1.1.6

  • Add option for outputting title with notes
  • Add option for outputting note title only

1.1.4

  • Fix for “topic not found” when run with no arguments

1.1.1

  • Reorganize and rename long output options
  • Fix wrapping long lines without spaces

1.1.0

  • Add -R switch for listing “runnable” topics
  • Add -T switch for completion-compatible listing of “runnable” topics
  • Add -L switch for completion-compatible listing of all topics

1.0.1

  • Allow topic matching within title, not just at start
  • Remove formatting of topic text for better compatibility with mdless/mdcat
  • Add @run() syntax to allow executable commands
  • Add @copy() syntax to copy text to clipboard
  • Add @url/@open() syntax to open urls/files, OS agnostic (hopefully)
  • Add support for mdless/mdcat
  • Add support for pager
  • Offer to create skeleton buildnotes if none found
  • Set iTerm 2 marks for navigation when paging is disabled
  • Wrap output with option to specify width (default 80, 0 to disable)

Speaking of QuickQuestion…

Related Projects