├── scripts ├── EN_Tag_Groups.applescript ├── en-multi-tag.applescript ├── add_text_to_note_titles.applescript └── en_templates.applescript ├── Rakefile └── README.md /scripts/EN_Tag_Groups.applescript: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtuckerkellogg/evernote_applescript_utils/HEAD/scripts/EN_Tag_Groups.applescript -------------------------------------------------------------------------------- /scripts/en-multi-tag.applescript: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtuckerkellogg/evernote_applescript_utils/HEAD/scripts/en-multi-tag.applescript -------------------------------------------------------------------------------- /scripts/add_text_to_note_titles.applescript: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gtuckerkellogg/evernote_applescript_utils/HEAD/scripts/add_text_to_note_titles.applescript -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # -*- Mode: Ruby -*- 2 | require 'rake/clean' 3 | require 'fileutils' 4 | 5 | DESTDIR = File.join(ENV['HOME'], 'Library', 'Scripts') 6 | 7 | SRC = FileList['scripts/*.applescript'] 8 | SCPTSDIR = 'build' 9 | SCPTS = SRC.collect { |s| 10 | File.join(SCPTSDIR, s.sub(/scripts\/(.+)\.applescript$/, '\1.app')) 11 | } 12 | CLEAN.include(SCPTS) 13 | CLEAN.include(SCPTSDIR) 14 | 15 | verbose true 16 | 17 | # Create directories for the build output 18 | SCPTS.each do |s| 19 | directory File.dirname(s) 20 | end 21 | directory DESTDIR 22 | 23 | rule '.app' => lambda { |scpt| find_source(scpt) } do |t| 24 | # Make sure the directory exists 25 | Rake::Task[File.dirname(t.name)].invoke 26 | # Compile execute-only (-x) 27 | sh "osacompile -x -o '#{t.name}' '#{t.source}'" 28 | end 29 | 30 | # We want to build into a parallel directory structure, so this is used to go 31 | # find the applescript 32 | def find_source(scpt) 33 | base = File.basename(scpt, '.app') 34 | SRC.find { |s| File.basename(s, '.applescript') == base } 35 | end 36 | 37 | desc 'Compile the scripts as Applications' 38 | task :compile => SCPTS do 39 | end 40 | 41 | desc "Install scripts to #{DESTDIR}." 42 | task :install => [:compile] do 43 | Rake::Task[DESTDIR].invoke 44 | SCPTS.each do |s| 45 | # Strip off SCPTSDIR, append to DESTDIR 46 | d = File.join(DESTDIR, s.split(File::Separator)[1..-1]) 47 | # Make sure the directory exists 48 | directory File.dirname(d) 49 | Rake::Task[d].invoke 50 | puts "cp #{s} #{d}" if verbose 51 | FileUtils.cp_r(s, d) 52 | end 53 | end 54 | 55 | desc "Install scripts to #{DESTDIR} and clean up." 56 | task :installclean => [:install, :clean] do 57 | end 58 | 59 | task :default do 60 | puts "run one of the following:" 61 | sh "rake -T" 62 | end 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AppleScript Utils for Evernote 2 | ============================== 3 | 4 | This is just a set of simple AppleScripts that I use to make Evernote 5 | on my Mac run more smoothly. 6 | 7 | The scripts 8 | ----------- 9 | 10 | ### Tag multiple notes `en-multi-tag.applescript` 11 | 12 | 13 | Allows tagging multiple notes with multiple tags, like the Ctrl-Alt-T keyboard shortcut on the Windows client. 14 | 15 | 16 | ### Create notes from templates `en_templates.applescript` 17 | 18 | Allows creation of notes from templates. Any notes with a specified 19 | tag (default `template`) and in a specified folder (default `meta`) 20 | 21 | ### Add text to multiple note titles `add_text_to_note_titles.applescript` 22 | 23 | Some people use keywords within note titles in addition to tags. This 24 | script will add arbitrary text to the titles of all selected notes. 25 | The text can be added to the beginning or the end of the title. 26 | 27 | ### Tag multiple notes using "Tag Groups" `EN_Tag_Groups.applescript` 28 | 29 | There are (at least) two camps within the Evernote user community 30 | concerning the best way to tag notes. Some people use a *lot* of tags, 31 | with a high level of specificity. Others (like me) use broader tags, 32 | but combine them to achieve specific search results. Still others use 33 | low specificity tags and not very many of those, which I can't see 34 | much use of. 35 | 36 | For those of us who use broad tag categories, it can be useful to 37 | ensure that the same tags are assigned to notes as they come in (say, 38 | notes associated with a project). This script will help do that. The 39 | first time it is run, it asks for a group name, and then lets you 40 | assign a set of tags to that group. It will then (and in future runs) 41 | allow you to assign those tags to a set of notes. It's like running 42 | the multi-tag script above several times. 43 | 44 | Because this script creates some variables to persist over multiple 45 | sessions, it will not work if run as a script from Automator. It must 46 | be run as an *Application* from Automator. 47 | 48 | Installation and setup 49 | ---------------------- 50 | 51 | Just copying these scripts to a place where you can use them will work 52 | at its most basic level. However, if you want to get them to work as 53 | shortcut keys within Evernote, you need to 54 | 55 | 1. Save each script as an Application 56 | 57 | You can do this by opening a Terminal and typing "rake". The 58 | applications will all be in the `build` folder. 59 | 60 | 2. Create a service using Automator for each Application 61 | 62 | 3. Associate the name of the service with a keyboard shortcut 63 | 64 | Instead of 2 and 3, you could just use TextExpander or your favorite 65 | keyboard shortcut approach. The only advantage with using Services is 66 | that they will appear under the *Evernote->Services* menu. 67 | 68 | A trivial gist for org-mode users 69 | ---------- 70 | 71 | For folks who use Emacs org-mode, I have a trivial 72 | [AppleScript gist](https://gist.github.com/1790180) which will copy an 73 | Evernote note link to a form used by org. You may be wondering why 74 | this README is written in Markdown and not in Org. Truly no good 75 | reason. 76 | 77 | Bugs and Limitations 78 | --------------------- 79 | 80 | There are probably bugs. Some of them are probaby mine. 81 | Anyway, let me know if you see bugs. 82 | 83 | ### Why save these scripts as Applications instead of running AppleScript services? 84 | 85 | Scripts run from Automator by a "run AppleScript" service pasted in to 86 | the Automator window sometimes have undocumented limitations, even 87 | though they work fine when run directly. This has been reported by a 88 | variety of AppleScript users and developers. The workaround to get 89 | keyboard shortcuts and working "Services" menu pulldowns is to save 90 | them as Applications, as described above, and have the service run the 91 | Application. 92 | 93 | Acknowledgements 94 | ----------------- 95 | 96 | Justin Lancy's [veritrope](http:/www.veritrope.com) is the best source 97 | for Evernote AppleScripts, and is where I got familiar with the 98 | problems others were having. In particular the simple sort routine I 99 | use is from Justin. I'd put all my scripts directly on Veitrope, but 100 | if I don't use git I'm lost. So they are here 101 | -------------------------------------------------------------------------------- /scripts/en_templates.applescript: -------------------------------------------------------------------------------- 1 | (* -*- Mode: Applescript -*- 2 | # Templates in Evernote (Mac version) 3 | # gtuckerkellogg@gmail.com (inspired by http://veritrope.com/code/evernote-new-note-based-on-template/) 4 | # No guarantees. It works for me; use at your own risk 5 | 6 | #------------ INSTALLATION ----------------- 7 | # 8 | # Put this in a Run AppleScript container in Automator and associate with Evernote 9 | 10 | #-------------THREE CONFIGURATION VARIABLES ---------- 11 | 12 | # 1. One notebook (by default, named "~meta") contains your template notes 13 | # 2. One tag (by default, "templates") holds your templates 14 | # 3. One notebook (by default, named "_inbox/in") will be used to place your new notes based on templates 15 | 16 | # Change these to whatever you like. The notebooks must exist in order for the script to run. 17 | # Any notes in the tag notebook tagged accordingly will be considered note templates 18 | 19 | #------------ USAGE --------------- 20 | # If you have this script installed as an Automator service, find it in Evernote->Services 21 | # menu. A dialog will appear allowing you to choose from your list of templates. New 22 | # notes will be created based on the templates, preserving tags (removing the template tag itself) 23 | # and creating a date-stamped title based on the template note title. 24 | 25 | *) 26 | 27 | global template_notebook 28 | global template_tag 29 | global new_note_notebook 30 | 31 | set template_notebook to "~meta" # this is the Notebook where templates are stored 32 | set template_tag to "template" # this is how templates are tagged 33 | set new_note_notebook to "_inbox/in" # this is where new notes created from templates are placed 34 | 35 | ---------------- NO CONFIGURATION IS NEEDED BELOW THIS LINE -------------------- 36 | 37 | if check_notebook_existence() then 38 | set template_titles to get_template_titles() 39 | if template_titles is equal to {} then 40 | none_found() 41 | else 42 | set template_name to pick_template from template_titles 43 | if template_name is not equal to {} then 44 | create_note_using_template from template_name 45 | end if 46 | end if 47 | end if 48 | 49 | tell application "System Events" to set frontmost of process "Evernote" to true 50 | 51 | 52 | ---------------- SUBROUTINES ----------- 53 | on get_template_titles() 54 | set template_titles to {} 55 | tell application "Evernote" 56 | set template_list to find notes "notebook:\"" & template_notebook & "\" tag:" & template_tag 57 | repeat with my_note in template_list 58 | set template_titles to template_titles & {title of my_note} 59 | end repeat 60 | end tell 61 | return template_titles 62 | end get_template_titles 63 | 64 | 65 | on pick_template from template_list 66 | choose from list template_list 67 | if result is not false then 68 | set template_title to result 69 | else 70 | set template_title to {} 71 | end if 72 | end pick_template 73 | 74 | 75 | on create_new_note_title from template_title 76 | set {year:y, month:m, day:d} to (current date) # extract elements of the date for the title 77 | set new_note_title to template_title & " --- " & m & " " & d & ", " & y as string # this will be the title of your new note 78 | return new_note_title 79 | end create_new_note_title 80 | 81 | 82 | on create_note_using_template from template_title 83 | 84 | tell application "Evernote" 85 | set query_string to "notebook:\"" & template_notebook & "\" tag:\"" & template_tag & "\" inTitle:\"" & template_title & "\"" 86 | set template_list to find notes query_string 87 | set template_note to item 1 of template_list 88 | tell me to set new_note_title to create_new_note_title from template_title 89 | set template_content to HTML content of template_note 90 | set new_note to ¬ 91 | create note title new_note_title with html template_content ¬ 92 | notebook new_note_notebook 93 | set the_tags to (the tags of template_note) 94 | assign the_tags to new_note 95 | repeat with T in the_tags 96 | if (name of T) is equal to template_tag then 97 | unassign T from new_note 98 | end if 99 | end repeat 100 | count (every item of the_tags) 101 | open note window with new_note 102 | end tell 103 | end create_note_using_template 104 | 105 | 106 | on check_notebook_existence() 107 | tell application "Evernote" 108 | try 109 | get the first notebook whose name is equal to new_note_notebook 110 | on error 111 | display dialog "The notebook for new notes: \"" & new_note_notebook & "\" does not exist" 112 | return false 113 | end try 114 | try 115 | get the first notebook whose name is equal to template_notebook 116 | on error 117 | display dialog "The notebook for templates: \"" & template_notebook & "\" does not exist" 118 | return false 119 | end try 120 | end tell 121 | return true 122 | end check_notebook_existence 123 | 124 | 125 | on none_found() 126 | display dialog ("No templates found") ¬ 127 | & ("in notebook \"" & template_notebook & "\"" & return & return) ¬ 128 | & ("with tag \"" & template_tag & "\"") 129 | end none_found 130 | 131 | 132 | --------------------------------------------------------------------------------