During the recent months I’ve been working hard to turn Devonthink into a more powerful AI-environment. Two or three years ago something similar had been tried with RubyCocoa. But back at these times the Scripting Bridge was creating a lot of troubles.
Now with MacRuby and pre-compiled AppleScript amazing things become possible. E.g.: analyze data within Devonthink, visualize them and store the visualization back in Devonthink.
It’s really powerful!
Expect more to come. Meanwhile a tasty piece of code and a “thank you Devon-Technologies” for such a cool application:
… and for code literates: yes this code is also turning Devonthink databases themselves into persistent MacRuby script databases and environments.
#!/usr/local/bin/macruby
framework "Cocoa"
framework "Foundation"
require 'hotcocoa/graphics'
include HotCocoa
include Graphics
class AppleScript
def initialize (src, raise_err_p = true)
@script = NSAppleScript.alloc.initWithSource(src)
@errinfo = Pointer.new_with_type('^@')
@script.compileAndReturnError(@errinfo)
#@script = nil if handle_error(@errinfo, raise_err_p)
end
def execute (raise_err_p = false)
@errinfo = Pointer.new_with_type('^@')
result = @script.executeAndReturnError(@errinfo)
#handle_error(@errinfo, raise_err_p)
return result
end
def source
@script.source.to_s
end
def error?
return nil if @errinfo.ocnil?
return (errmsg_of @errinfo)
end
private
def handle_error (errinfo, raise_err_p)
return false if errinfo.ocnil?
if raise_err_p then
raise "AppleScriptError: #{errmsg_of errinfo}"
else
$stderr.puts( errmsg_of(errinfo) )
end
return true
end
def errmsg_of (errinfo)
errinfo.objectForKey('NSAppleScriptErrorMessage').to_s
end
end
class AEList
include Enumerable
def initialize (aedesc)
@aedesc = aedesc
end
def each
@aedesc.numberOfItems.times do |index|
yield @aedesc.descriptorAtIndex( index + 1 )
end
return self
end
end
class DEVONthink
attr_reader :dir
def set( path, obj)
ref = path.split("/").to_a
loc_path = ref[1..(ref.length-2)].join("/")
script = AppleScript.new %{
tell application "DEVONthink Pro"
set this_wiki to create location "#{loc_path}"
set this_wikipath to "/#{ref.join('/')}"
if not (exists record at this_wikipath) then
create record with {aliases:{"WikiBlog", "DevonThink Pro", "Semantic Web"}, name:"#{ref.last}", type:txt, plain text:"#{obj}"} in this_wiki
else
set wiki_item to get record at this_wikipath
set plain text of wiki_item to "#{obj}"
end if
end tell
}
result = script.execute
end
def get( path)
ref = path.split("/").to_a
loc_path = ref[1..(ref.length-2)].join("/")
script = AppleScript.new %{
tell application "DEVONthink Pro"
set this_wiki to create location "#{loc_path}"
if "#{ref[1]}" is equal to "/" or "#{ref[1]}" is equal to "" then
return false
else
set this_wikipath to "/#{ref.join('/')}"
set wiki_item to get record at this_wikipath
set wiki_text to plain text of wiki_item
return wiki_text
end if
end tell
}
result = script.execute.stringValue.to_s.toeuc
end
def doScript( path, *args)
ref = path.split("/").to_a
loc_path = ref[1..(ref.length-2)].join("/")
method_name = ref.last
script = AppleScript.new %{
tell application "DEVONthink Pro"
set this_wiki to create location "#{loc_path}"
set this_wikipath to "/#{ref.join('/')}"
set wiki_item to get record at this_wikipath
set wiki_text to plain text of wiki_item
return wiki_text
end tell
}
result = script.execute.stringValue.to_s.toeuc
eval(result)
send(method_name, *args)
end
def directory?(dir)
script = AppleScript.new %{
tell application "DEVONthink Pro"
try
set resultRecord to get record at "#{dir}" in "bwin"
return type of resultRecord
if type of resultRecord is equal to "group" then
return true as string
else
return false as string
end if
on error errText number errNum
return false as string
end try
end tell
}
result = script.execute.stringValue.to_s.toeuc
if result == 'DTgr' then true else false end
end
def initialize path, opts={}
@dir = path
end
def DEVONthink.[]( path)
new( path)
end
alias []= set
alias [] get
private
end
db = DEVONthink.new('')
if __FILE__ == $0 then
$stderr.puts "executing applescript ..."
# AppleScript - operating on images from within DEVONthink Pro
script = AppleScript.new %{
tell application "DEVONthink Pro"
set resultRecord to get record at ¬
"permthink/graphics/particule.png" in "r3search"
set resultdata to data of resultRecord
return resultdata
end tell
}
# execute and get result as AEDescriptor
result = script.execute
img = result.data
puts img.class
bits = NSBitmapImageRep.alloc.initWithData(img)
#puts img.isValid # NSPNGFileType
outfile = "devonthink_image.png"
#tiffdata = bits.TIFFRepresentation
pngdata = NSData.new
pngdata = bits.representationUsingType(NSPNGFileType, properties: nil)
#tiffdata.writeToFile outfile, atomically:false
pngdata.writeToFile outfile, atomically:false
OUTFILE = 'devonthink_img_direct.png'
canvas = Canvas.for_image(:size => [1920,1200], :filename => OUTFILE)
canvas.background(Color.white)
canvas.font('Tahoma')
canvas.fontsize(64)
canvas.fill(Color.white)
canvas.stroke(Color.white)
hotimg = Image.new(img)
puts hotimg.class
canvas.draw(hotimg,0,0)
canvas.text("Straight from DEVONthink Pro Office",50,400)
canvas.save
script2 = AppleScript.new %{
tell application "DEVONthink Pro"
set myloc to create location ¬
"/root/myitem" in "/"
create record with {name:"devon_image",type:picture, path:"/Users/stereocle/Documents/r3search.dtBase2/Files.noindex/rb/1/devonthink_img_direct.png"} in myloc
end tell
}
script2.execute
`open #{OUTFILE}`
end