Created
January 25, 2012 15:05
-
-
Save ttscoff/1676667 to your computer and use it in GitHub Desktop.
Watch a Scrivener project for changes and update Marked.app
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
# scrivwatch.rb by Brett Terpstra, 2011 | |
# Modifications to merge into one file for Markdown viewing in Marked by BooneJS, 2012 | |
# Modified to use REXML and add titles by Brett Terpstra, 2012 <https://gist.github.com/1676667> | |
# | |
# Watch a Scrivener project for changes and update a preview file for Marked | |
# Usage: scrivwatch.rb /path/to/document.scriv | |
# <http://markedapp.com> | |
require 'fileutils' | |
require 'rexml/document' | |
debug = false | |
droplet = true | |
def check_running() | |
newpid = %x{ps ax|grep Marked|grep -v grep|awk '{print $1}'} | |
return newpid.empty? ? false : true | |
end | |
def get_children(ele,path,files,depth) | |
ele.elements.each('*/BinderItem') do |child| | |
# Ignore docs set to not include in compile | |
included = REXML::XPath.first( child, "MetaData/IncludeInCompile" ).text | |
if included == "Yes" | |
id = child.attributes["ID"] | |
# passing type, would eventually use to control header/title output | |
type = child.attributes["Type"] | |
title = child.elements.to_a[0].text | |
file = "#{path}/Files/Docs/#{id}.rtf" | |
filepath = File.exists?(file) ? file : false | |
files << { 'path' => filepath, 'title' => title, 'depth' => depth, 'type' => type } | |
end | |
get_children(child,path,files,depth+1) | |
end | |
end | |
# Take the path to the scrivener file and open the internal XML file. | |
def get_rtf_file_array(scrivpath) | |
scrivpath = File.expand_path(scrivpath) | |
scrivx = File.basename("#{scrivpath}", ".scriv") + ".scrivx" | |
scrivxpath = "#{scrivpath}/#{scrivx}" | |
# handle cases where the package has been renamed after creation | |
unless File.exists?(scrivxpath) | |
scrivxpath = %x{ls -1 #{scrivpath}/*.scrivx|head -n 1}.strip | |
end | |
files = [] | |
doc = REXML::Document.new File.new(scrivxpath) | |
doc.elements.each('ScrivenerProject/Binder/BinderItem') do |ele| | |
if ele.attributes['Type'] == "DraftFolder" | |
get_children(ele,scrivpath,files,1) | |
end | |
end | |
return files | |
end | |
trap("SIGINT") { exit } | |
unless droplet || debug | |
if (ARGV.length != 1 || ARGV[0] !~ /\.scriv\/?$/) | |
puts "Usage: scrivwatch.rb /path/to/document.scriv" | |
exit | |
end | |
end | |
if debug | |
path = File.expand_path("~/Dropbox/ScrivTest.scriv") | |
else | |
path = File.expand_path(ARGV[0].gsub(/\/$/,'')) | |
end | |
sw_name = path.gsub(/.*?\/([^\/]+)\.scriv$/,"\\1") | |
sw_target = File.expand_path("~/ScrivWatcher") | |
Dir.mkdir(sw_target) unless File.exists?(sw_target) | |
sw_note = "#{sw_target}/ScrivWatcher - #{sw_name}.md" | |
FileUtils.touch(sw_note) | |
%x{open -a Scrivener "#{path}" && open -a /Applications/Marked.app "#{sw_note}"} | |
first = true | |
while true do # repeat infinitely | |
unless check_running | |
puts "Marked quit, exiting" | |
exit | |
end | |
notetext = "" | |
files = get_rtf_file_array(path) | |
# track any file changes in folder | |
new_hash = files.collect {|f| [ f['path'], File.stat(f['path']).mtime.to_i ] if f['path'] } # create a hash of timestamps | |
hash ||= new_hash | |
diff_hash = new_hash - hash # check for changes | |
# tracking the xml file for ordering changes as well | |
new_xml_time = File.stat(path).mtime.to_i | |
xml_time ||= new_xml_time | |
diff_xml_time = new_xml_time - xml_time | |
unless first == false && diff_hash.empty? && diff_xml_time == 0 # if changes were found in the timestamps | |
first = false | |
hash = new_hash | |
xml_time = new_xml_time | |
# All attempts to pass more than 1 file to textutil failed. Do it one-at-a-time. | |
files.each{ |f| | |
p f if debug | |
note = f['path'] ? %x{/usr/bin/textutil -convert txt -stdout "#{f['path']}"} : '' | |
leader = "" | |
f['depth'].times { leader += "#" } unless f['depth'].nil? | |
notetext = notetext + "#{leader} #{f['title']}\n\n" + note + "\n\n" | |
} | |
# write the result to the preview file | |
watch_note = File.new("#{sw_note}",'w') | |
watch_note.puts notetext | |
watch_note.close | |
end | |
sleep 1 | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment