Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 1st, 2012  |  syntax: None  |  size: 5.58 KB  |  hits: 20  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #!/usr/bin/env ruby -wKU
  2.  
  3. # Adapted from Brett Terpstra’s original “Markdown to Evernote” service (http://brettterpstra.com/a-better-os-x-system-service-for-evernote-notes-with-multimarkdown/)
  4. # Martin Kopischke 2011 – License: Creative Commons Attribution Share-Alike (CC BY-SA) 3.0 Unported (http://creativecommons.org/licenses/by-sa/3.0/)
  5. # Changes:      – create only one Evernote note per (Multi)Markdown input passed (instead of one per line)
  6. #                       – do not choke on shell escape characters (use Tempfile instead of shell pipe for osascript)
  7. #                       – default to MultiMarkdown 3 executable (instead of MMD 2 Perl script)
  8. #                       – make smart typography processing optional (set SMARTY to 'false' to bypass processing;
  9. #                         note smart typography cannot be disabled in MMD 3.0 and 3.0.1
  10. #                       – handle both smart typography processing scripts (ie. SmartyPants.pl)
  11. #                         and (Multi)Markdown processor extensions (i.e. '--smart' and MMD's upcoming '--nosmart')
  12. #                       – handle both command line switches to (Multi)Markdown processor and separate smart typography processors
  13. #                       – restrict parsing for metadata (note title, tags, target notebook) to the metadata block as per MMD spec
  14. #                         note atx style 1st level headings will be parsed anywhere, as they terminate the metadata block anyway
  15. #                       – specify note title in metadata block MMD style, using 'Title: <name>' (not just as 1st level heading)
  16. #                       – specify target notebook in metadata block either with '= <name>' or MMD style, using 'Notebook: <name>'
  17. #                       – specify tags in metadata block either with '@ <tag list>' or MMD style, using 'Keywords: <tag list>'  
  18. #                       – correctly parse tag names with punctuation (no commas) and other “special” characters
  19. #                       – correctly assign multiple tags (instead of quietly failing)
  20. #                       – correctly parse all flavors of 1st level atx headings (not just those following the hash with a space)
  21. #                       – use localized date time stamp from AppleScript (instead of US formatted) as fallback note title
  22. #                       – use Evernote default notebook if none is indicated in input (instead of 'Unfiled')
  23. #                       – added minimal sanity checks (like make sure Markdown executable actually exists and is executable)
  24. #                       – runs on Ruby 1.8 and 1.9
  25. # To do:        – process settext 1st level headings
  26. #                       – ignore Markdown 1st level headings when a 'Title:' metadata line is found?
  27.  
  28. # Markdown executable path
  29. # – edit to match your install location if non-default
  30. # – pre-version 3 MMD script usually is '~/Application Support/MultiMarkDown/bin/MultiMarkDown.pl'
  31. MARKDOWN = '/usr/local/bin/multimarkdown'
  32. Process.exit unless File.executable?(MARKDOWN)
  33.  
  34. # Smart typography (aka SmartyPants) switch
  35. SMARTY = true
  36. # – Smart typography processing via MARKDOWN extension
  37. #   enable with '--smart' for PEG Markdown, disable using '--nosmart' in upcoming MMD version 3
  38. SMARTY_EXT_ON  = '--smart'
  39. SMARTY_EXT_OFF = '--nosmart'
  40. # – Separate smart typography processor (i.e. SmartyPants.pl)
  41. #   set to path to SmartyPants.pl (for classic Markdown and MMD pre-version 3, usually same dir as (Multi)MarkDown.pl)
  42. #   set to '' to use SMARTY_EXT instead
  43. SMARTY_PATH = ''
  44. if SMARTY && !SMARTY_PATH.empty? then Process.exit unless File.executable?(SMARTY_PATH) end
  45.  
  46. # utility function: escape double quotes and backslashes (for AppleScript)
  47. def escape(str)
  48.         str.to_s.gsub(/(?=["\\])/, '\\')
  49. end
  50.  
  51. # utility function: enclose string in double quotes
  52. def quote(str)
  53.         '"' << str.to_s << '"'
  54. end
  55.  
  56. # buffer
  57. input = ''
  58. # processed data
  59. contents = ''
  60. title = ''
  61. tags = ''
  62. notebook = ''
  63. # operation switches
  64. metadata = true
  65.  
  66. # parse for metadata and pass all non-metadata to input
  67. ARGF.each_line do |line|
  68.         case line
  69.         # note title (either MMD metadata 'Title' – must occur before the first blank line – or atx style 1st level heading)
  70.         when /^Title:\s.*?/
  71.                 if metadata then title = line[7..-1].strip else input << line end
  72.         # strip all 1st level headings as logically, note title is 1st level
  73.         when /^#[^#]+?/
  74.                 if title.empty? then title = line[line.index(/[^#]/)..-1].strip end
  75.         # note tags (either MMD metadata 'Keywords' or '@ <tag list>'; must occur before the first blank line)
  76.         when /^(Keywords:|@)\s.*?/
  77.                 if metadata then tags = line[line.index(/\s/)+1..-1].split(',').map {|tag| tag = tag.strip} else input << line end
  78.         # notebook (either MMD metadata 'Notebook' or '= <name>'; must occur before the first blank line)
  79.         when /^(Notebook:|=)\s.*?/
  80.                 if metadata then notebook = line[line.index(/\s/)+1..-1].strip else input << line end
  81.         # metadata block ends at first blank line
  82.         when /^\s?$/
  83.                 if metadata then metadata = false end
  84.                 input << line
  85.         # anything else is appended to input
  86.         else
  87.                 input << line
  88.         end
  89. end
  90.  
  91. # Markdown processing
  92. mmd_cmd =  "#{quote MARKDOWN}"
  93. mmd_cmd << if SMARTY_PATH.empty? then SMARTY ? " #{SMARTY_EXT_ON}" : " #{SMARTY_EXT_OFF}" else "|#{quote SMARTY_PATH}" end unless !SMARTY
  94.  
  95. IO.popen(mmd_cmd, 'r+') do |io|
  96.         input.each_line {|line| io << line}
  97.         io.close_write
  98.         io.each_line {|line| contents << line}
  99. end
  100.  
  101. # create note, using localized date and time stamp as fallback for title
  102. if title.empty? then title = %x{osascript -e 'get (current date) as text'}.chomp end
  103.  
  104. osa_cmd =  "tell application #{quote 'Evernote'} to create note with html #{quote escape contents}"
  105. osa_cmd << "  title #{quote escape title}"
  106. if tags.length  > 1 then osa_cmd << " tags #{'{' << tags.map {|tag| tag = quote escape tag}.join(",") << '}'}" end
  107. if tags.length == 1 then osa_cmd << " tags #{quote escape tags[0]}" end
  108. osa_cmd << " notebook #{quote escape notebook}" unless notebook.empty?
  109.  
  110. require 'tempfile'
  111. Tempfile.open('md2evernote') do |file|
  112.         file.puts osa_cmd
  113.         file.rewind
  114.         %x{osascript "#{file.path}"}
  115. end