Skip to content

Instantly share code, notes, and snippets.

@glfruit
Created January 20, 2016 13:44
Show Gist options
  • Save glfruit/6a17ab63ed8271f9d61e to your computer and use it in GitHub Desktop.
Save glfruit/6a17ab63ed8271f9d61e to your computer and use it in GitHub Desktop.
A modified version of nvTagNavigator's script that can handle unicode correctly
# nvTagFinder - Brett Terpstra 2013
#
# Creates a list of tags with links to their associated files in Markdown as a new nvALT note
# Requires "Store as plain text" to be enabled
# Configure default extension and the path to notes folder below
require 'uri'
require 'shellwords'
if ARGV.length == 2
note_ext = ARGV[1]
notes_dir = ARGV[0]
else
note_ext = %x{defaults read com.brettterpstra.nvtagnavigator notesext}.strip
notes_dir = %x{defaults read com.brettterpstra.nvtagnavigator notesdir}.strip
end
if note_ext =~ /does not exist$/ or note_ext.nil? or notes_dir =~ /does not exist$/ or notes_dir.nil?
puts "The note extension and/or notes folder are not defined"
Process.exit
end
out_dir = File.expand_path("~/Library/Application Support/nvALT")
mmd = "/Applications/nvALT.app/Contents/Resources/multimarkdown"
Dir.chdir(File.expand_path(notes_dir))
collected_tags = {}
file_types = ["md","taskpaper","txt"]
note_ext.split(" ").each do |ext|
file_types.push ext unless file_types.include? ext
end
Dir.glob("*.{#{file_types.join(',')}}").each do |file|
# $stderr.puts File.basename(file)
cmd = %Q{mdls -raw -name kMDItemOMUserTags #{Shellwords.escape(file)}}
tags_raw = %x{#{cmd}}.gsub(/\((.*)\)/m,"\\1")
# convert \Uxxxx into characters
tags_raw = tags_raw.gsub(%r{\\U(\h{4})}) {
$1.to_i(16).chr('UTF-8')
}
p "tags_raw: #{tags_raw}"
tags = tags_raw.split("\n").map! {|tag|
tag.gsub(/[,"\n]/m,'').strip.downcase
}.delete_if { |tag|
tag =~ /^(\s*|null)$/
}
tags.each {|tag|
if collected_tags.key? tag
collected_tags[tag].push file
else
collected_tags[tag] = [file]
end
}
end
output = ""
collected_tags.sort.each do |tag, files|
output += "* ### #{tag.gsub(/#/,"\\#")}\n".force_encoding("UTF-8")
files.each do |file|
note_name = File.basename(file,File.extname(file))
escaped = URI::escape(note_name,"?!()[]`#*\" ").force_encoding("UTF-8")
output += %Q{ * [#{note_name}](nvalt://find/#{escaped})\n}
end
end
puts "Output: #{output.force_encoding('utf-8')}"
# Uncomment below to pop the Markdown into your clipboard instead of a note
# puts %x{echo #{Shellwords.escape(output.gsub(/#/,"\\#"))}|pbcopy}
# exit
header =<<ENDHEADER
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>nvTags</title>
<style>h1{text-align:center;background:#333;color:#ddd;padding:5px 0;border-radius:5px}h3{margin:0;padding:0;font-size:16px;padding:8px 10px}ul{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;list-style-type:none;margin:0;padding:0}ul>li{font-size:21px;font-weight:300;background:#dfdfdf;margin:8px 0;cursor:pointer;border-radius:10px}ul>li>ul{margin:0}ul ul li{margin:2px 0;padding:0;background:none}ul ul a{display:block;padding:5px 10px;text-decoration:none;font-weight:300;background:#ededed;border-top:solid 1px #fff;border-bottom:solid 1px rgba(40,40,40,.1);color:#5294a0!important;font-size:16px;-webkit-transition:background-color .2s ease-in-out}ul ul a:hover{background:#fafafa;color:#0099b4!important;border-top:solid 1px #eee;box-shadow:0 -2px 4px rgba(0,0,0,.02) inset}ul ul li:first-of-type a{border-top:none;-webkit-border-top-left-radius:7px;-webkit-border-top-right-radius:7px;margin-top:10px}ul ul li:last-of-type a{border-bottom:none;-webkit-border-bottom-left-radius:7px;-webkit-border-bottom-right-radius:7px;margin-bottom:10px}</style>
</head>
<body>
<div id="wrapper">
<div markdown="0"><input type="text" id="typeahead"></div>
ENDHEADER
footer =<<ENDFOOTER
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script>(function(c){c('ul:first-of-type li ul').each(function(){c(this).css('height',c(this).height()+"px")});String.prototype.score=function(o,u){u=u||0;if(o.length===0){return 0.9}if(o.length>this.length){return 0}for(var r=o.length;r>0;r--){var i=o.substring(0,r);var q=this.indexOf(i);if(q<0){continue}if(q+o.length>this.length+u){continue}var j=this.substring(q+i.length);var s=null;if(r>=o.length){s=""}else{s=o.substring(r)}var t=j.score(s,u+q);if(t>0){var w=this.length-j.length;if(q!==0){var v=0;var p=this.charCodeAt(q-1);if(p===32||p===9){for(v=(q-2);v>=0;v--){p=this.charCodeAt(v);w-=((p===32||p===9)?1:0.15)}}else{w-=q}}w+=t*j.length;w/=this.length;return w}}return 0};c.expr[":"].Contains=function(e,f,d){return(e.textContent||e.innerText||"").toUpperCase().indexOf(d[3].toUpperCase())>=0};var b=(function(){var d=0;return function(f,e){clearTimeout(d);d=setTimeout(f,e)}})();var a=false;c.fn.liveUpdate=function(){list=c("#wrapper ul:first-of-type");if(list.length){var f=list.find("h3"),d=f.map(function(){return this.innerHTML.toLowerCase().replace(/\\n+/g,"").replace(/(^\s*|\s*$)/g,"")});c("#typeahead").on("keypress keyup",function(g){if(!a){a=true}b(function(){e()},200)}).on("keydown",function(g){if(g.keyCode==8){if(c("#typeahead").val().length===0){c("#typeahead").keyup()}else{f.each(function(){c(this).closest("li").show()})}}})}return this;function e(){var g=c.trim(c("#typeahead").val().toLowerCase().replace(/\s+/g,"")),h=[];if(!g||g==""){f.show()}else{d.each(function(j){var k=this.score(g);if(k>0.7){c(f[j]).closest("li").show()}else{c(f[j]).closest("li").fadeOut(200)}})}a=false}};c.fn.reverse=[].reverse;c("ul>li").find("ul").hide();c("h3").click(function(e){var d=c(this).parent("li").find("ul");if(d.is(":visible")){d.slideUp("fast")}else{d.slideDown("fast")}});c("#wrapper > ul:first-of-type").liveUpdate();c("#typeahead").focus()})(jQuery);</script>
</body>
</html>
ENDFOOTER
target = File.join(File.expand_path(out_dir),"nvTags.html")
File.open(target,'w') do |f|
f.puts header
f.puts %x{echo #{Shellwords.shellescape(output)}|#{mmd}}
f.puts footer
end
# print File.join(File.expand_path(out_dir),"nvTags.html")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment