Skip to content

Instantly share code, notes, and snippets.

@quad
Created November 1, 2010 14:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save quad/658243 to your computer and use it in GitHub Desktop.
Save quad/658243 to your computer and use it in GitHub Desktop.
Import a (my) Zim notebook to Simplenote
#!/usr/bin/env ruby
require 'json'
require 'Simplenote'
class ZimDirectory < Hash
class ZimException < Exception
end
attr_reader :dir
def initialize(directory)
raise "Not a directory" unless File.directory? directory
raise "Not a ZIM notebook" unless File.exist?(File.join(directory, 'notebook.zim'))
@dir = directory
load
end
def load
Dir[File.join(@dir, '**/*.txt')].each do |fn|
title = munge_filename fn
begin
body = load_note fn
rescue ZimException => e
body = File.read fn
end
title, self[title] = munge_note title, body
end
end
private
def munge_filename filename
filename = filename[@dir.length..-1].gsub(/_+/, ' ').chomp('.txt')
File.split(filename).tap { |ts| ts.shift if ts[0] == '.' }.join ' : '
end
def munge_note title, body
lines = body.split "\n"
# Strip header, if duplicated.
header_title = /====== (.*) ======/.match(lines[0])
if header_title && header_title[1] == title.split(' : ')[-1]
lines.shift
lines.shift while lines[0].empty?
end
# Kill Tomboy timestamp trailers.
lines.pop while lines[-1].include? '(in Tomboy):'
[title, lines.map(&:chomp).join("\n")]
end
HEADER_SEP = ': '
def load_note filename
File.open filename do |f|
headers = {}
f.each do |l|
l.chomp!
break if l.empty? || !l.include?(HEADER_SEP)
k, v = l.split HEADER_SEP
headers[k] = v.chomp
end
raise ZimException.new 'Not a Zim wiki file' if headers['Content-Type'] != 'text/x-zim-wiki'
f.read
end
end
end
class UploadLog < Array
def initialize(zim, &block)
@filename = File.join(zim.dir, "#{$0}.log")
self.replace(JSON.load(File.read @filename)) if File.exist? @filename
begin
yield self
ensure
save
end
end
def save
File.open @filename, 'w' do |f|
f << self.to_json
end
end
end
zims = $*.map { |dn| ZimDirectory.new dn }
api = Simplenote.new ENV['SIMPLENOTE_EMAIL'], ENV['SIMPLENOTE_PASSWORD']
zims.each do |z|
UploadLog.new z do |log|
z.each_pair do |title, body|
next if log.include? title
puts "Uploading #{title}..."
api.createNote "#{title}\n\n#{body}"
log << title
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment