MacRuby Plugin

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

  

Thanks for posting the code! However, I’m curious - what exactly does it do? Because there’s no MacRuby on my machine and I’m not yet convinced that I should install it :wink: