Created
November 5, 2016 13:26
-
-
Save vaiorabbit/69743316138258a2a18f9de8c6dcf526 to your computer and use it in GitHub Desktop.
Returns the definition of given word via Dictionary Services of macOS. (Install Ruby-FFI in advance)
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
# -*- coding: utf-8 -*- | |
# Usage : $ macOSDict.rb [word_to_look_up] | |
require 'ffi' | |
module MacOSDict | |
extend FFI::Library | |
# /System/Library/Frameworks/CoreFoundation.framework/Headers/CFBase.h | |
class CFRange < FFI::Struct | |
layout :location, :int64, | |
:length, :int64 | |
end | |
KCFStringEncodingUTF8 = 0x08000100 | |
APIEntry = Struct.new( :api_name, :api_args, :api_retval ) | |
def self.load_lib(output_error = true) | |
libpath = [ | |
"/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation", | |
"/System/Library/Frameworks/CoreServices.framework/Frameworks/DictionaryServices.framework/DictionaryServices", | |
] | |
ffi_lib(libpath[0]) | |
ffi_lib(libpath[1]) | |
@@api_signature = [ | |
APIEntry.new( :CFStringGetCStringPtr, [:pointer, :uint32], :pointer ), | |
APIEntry.new( :CFStringCreateWithCString, [:pointer, :pointer, :uint32], :pointer ), | |
APIEntry.new( :CFStringGetLength, [:pointer], :int64 ), | |
APIEntry.new( :CFStringGetBytes, [:pointer], :int64 ), | |
APIEntry.new( :CFStringGetCharacterAtIndex, [:pointer, :int64], :uint16 ), | |
APIEntry.new( :CFStringGetCString, [:pointer, :pointer, :int64, :uint32], :uint8 ), | |
APIEntry.new( :CFStringGetBytes, [:pointer, CFRange.by_value, :uint32, :uint8, :uint8, :pointer, :int64, :pointer], :int64 ), | |
APIEntry.new( :DCSGetTermRangeInString, [:pointer, :pointer, :int64], CFRange.by_value ), | |
APIEntry.new( :DCSCopyTextDefinition, [:pointer, :pointer, CFRange.by_value], :pointer ), | |
] | |
@@api_signature.each do |sig| | |
begin | |
attach_function( sig.api_name, sig.api_args, sig.api_retval ) | |
rescue FFI::NotFoundError | |
$stderr.puts("[Warning] Failed to import #{sig}.") if output_error | |
end | |
end | |
end | |
end | |
include MacOSDict | |
if __FILE__ == $0 | |
MacOSDict.load_lib() | |
query = ARGV[0] | |
term = CFStringCreateWithCString(nil, query, KCFStringEncodingUTF8) | |
term_range = DCSGetTermRangeInString(nil, term, 0) | |
def_text = DCSCopyTextDefinition(nil, term, term_range) | |
if def_text.null? == false | |
def_range = CFRange.new | |
def_range[:location] = 0 | |
def_range[:length] = CFStringGetLength(def_text) | |
usedBufLen = ' ' * 8 | |
CFStringGetBytes(def_text, def_range, KCFStringEncodingUTF8, 0, 1, nil, 0, usedBufLen) | |
result = ' ' * (usedBufLen.unpack("L")[0] + 1) | |
CFStringGetCString(def_text, result, result.length, KCFStringEncodingUTF8) | |
puts result | |
end | |
end | |
# Reference: | |
# /System/Library/Frameworks/CoreFoundation.framework/Headers/ | |
# - CFBase.h | |
# - CFString.h | |
# /System/Library/Frameworks/CoreServices.framework/Frameworks/DictionaryServices.framework/Headers | |
# - DictionaryServices.h |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment