DiaryException このページをアンテナに追加 RSSフィード Twitter

2010-10-24(日)

[][]Google ChromeAppleScript操作する

Google Chromeはver.7以降でAppleScript対応している。正確に書くと、Google ChromeプロセスにAppleEventを送ることが出来るようになった。

AppleScriptAppleScriptエディタを使って書いて実行するか、エディタで書いてosascriptコマンドで実行することが出来る。

つまり、他のアプリケーションやshellからGoogle Chrome操作する、Google Chrome情報を取得することが可能になった。

例えば、Google Chrome内で選択したテキストをそのままEmacsバッファに挿入したい場合、(AppleScriptを使わなければ、Google Chromeテキストを選択→Command-c→Emacsに移動→(kill-ringとpasteboardが連動していることを前提にして)C-yとする必要があったが)

Google Chromeテキストを選択して、

f:id:LaclefYoshi:20101024104951p:image

Emacs

C-u M-! osascript -e 'tell application "Google Chrome" to get copy selection of active tab of window 1' ; pbpaste

f:id:LaclefYoshi:20101024104949p:image

で出来るようになった。

f:id:LaclefYoshi:20101024104950p:image

ちなみに、vimで同じことをするには、

:r! osascript -e 'tell application "Google Chrome" to get copy selection of active tab of window 1' ; pbpaste

選択テキストEmacsバッファにそのまま挿入するのではなく、加工して挿入したい場合、例えば、前に作ったGoogle翻訳コマンドラインツールを使えば、

C-u M-! osascript -e 'tell application "Google Chrome" to get copy selection of active tab of window 1' ; pbpaste | transrator

で選択したテキスト翻訳文章が挿入される。

f:id:LaclefYoshi:20101024114020p:image



AppleScriptからGoogle Chromeに対して何が出来るかは、AppleScriptエディタGoogle ChromeD&Dすれば(もしくはAppleScriptエディタの[ファイル]-[用語説明を開く]からGoogle Chromeを選択すれば)、コマンド一覧と説明が見える。

f:id:LaclefYoshi:20101024110635p:image f:id:LaclefYoshi:20101024110636p:image

幾つかのコマンドAppleScriptで使ってみる。

-- Google Chromeの1つ目のウィンドウのプロパティを取得
tell application "Google Chrome"
 get properties of window 1
end tell
------------------------------
-- 結果
{zoomed:true, miniaturized:false, name:"\"applescript\" commands - Google 検索", active tab:tab id 132 of window id 4 of application "Google Chrome", mode:"normal", miniaturizable:true, class:window, closeable:true, resizable:true, visible:true, zoomable:true, id:4, bounds:{50, 22, 1213, 796}, index:1, active tab index:13}
-- 1つ目のウィンドウの5つ目のタブのプロパティを取得
tell application "Google Chrome"
 get properties of tab 5 of window 1
end tell
------------------------------
-- 結果
{name:"dojo/regexp - DojoCampus - Docs", URL:"http://docs.dojocampus.org/dojo/regexp", id:13, class:tab, loading:false}
-- タブに対するコマンドの一部
tell application "Google Chrome"
 view source of active tab of window 1  -- ソースを表示
 save active tab of window 1  -- 保存
 print active tab of window 1  -- 印刷
 reload active tab of window 1  -- 再読み込み
 go back active tab of window 1  -- 戻る
 go forward active tab of window 1  -- 進む
 copy selection of active tab of window 1  -- 選択したテキストをpasteboardへコピー
 paste selection active tab of window 1  -- pasteboard内のテキストをタブに(テキストエリアにフォーカスがある場合はそのエリアに)貼りつけ
end tell

コマンドを組み合わせることで、Google Chrome操作自動化出来る。

tell application "Google Chrome"
 set aWin to make new window with properties {mode:"incognito"}
 -- シークレットモードでウィンドウを作る; 通常モードは {mode:"normal"}
 tell aWin
  set newTab to make new tab with properties {URL:"http://www.facebook.com/"}
  -- Facebookを新しいタブで開く
  tell active tab
   repeat  -- ページのロードを待つためのループ
    set curStat to loading
    if curStat = false then exit repeat
    delay 0.1
   end repeat
  end tell
 end tell
end tell

AppleScriptコードアプリケーションとして保存出来るので、作ったアプリケーションアイコンダブルクリックしてGoogle Chrome自動作業をさせる、ということも出来る。

追記: Google Chromeを操作するAppleScriptの中にJavaScriptを書く - DiaryException

2010-10-16(土)

[]Google Translate(翻訳)コマンドラインツール

Google ChromeにはError 404 (Not Found)!!1を入れ、FirefoxThunderbirdにはAdd-ons for Firefoxを入れて、英語の長文はさっさとGoogle Translateに投げて、大体の文脈を掴むことにしている。一昔前よりは遥かに「読める」日本語文章が返ってくるから、本当に便利になったと思う。

しかし、weechatなど、ターミナル上のソフトウェアによって表示される英文に対して、Google Translateへの適切なショートカットが無かった。

そこで、標準入力から入力した文章をGoogle Translateを通し、翻訳された文章を標準出力に出力するツールを作ることにした。ほとんどは英語日本語で用いるだろうが、オプション入力言語と出力言語を指定出来ればなお良いと考えた。

Java(あるいはScalaClojureなど)だとGoogle Code Archive - Long-term storage for Google Code Project Hosting.があるし、Pythonならurllibとurllib2とjsonを使えば20数行で書ける。


ちょっと頭の体操がてら、Haskellで書いてみた。

HTTP通信のためにhttp packageJSON処理のためにjson packageをcabalでインストールした。他のライブラリMacPortsからインストールしたHaskell Platformに標準搭載されている。

まず使用例。

$ ghc --make translator.hs
$ ./translator -fja -ten  # -fまたは--from=で入力言語を指定, -tまたは--to=で出力言語を指定
クリエイティブ・コモンズとは、クリエイティブ・コモンズ・ライセンス(CCライセンス)を提供している国際的非営利組織とそのプロジェクトの総称です。
# <- C-dを押す
Creative Commons license Creative Commons (CC license) is a general term for an international nonprofit organization and the project has been provided.

$ ./translator  # オプションを省略した場合は-fen -tja
Creative Commons is a nonprofit corporation dedicated to making it easier for people to share and build upon the work of others, consistent with the rules of copyright. 
クリエイティブコモンズは、簡単に人々が共有し、他の作品、著作権のルールと一致する時にビルドすることに専念非営利法人です。

$ cat document.txt | ./translator
# (出力省略)
$ ./translator < document.txt
# (出力省略)

$ ./translator -fes -tja  # Google Translate対応言語は勿論対応
Alguna de estas condiciones puede no aplicarse si se obtiene el permiso del titular de los derechos de autor
あなたが著作権の所有者から許可を得ると、これらの条件は免除することができます

コードを以下に掲載する。ちょっと長いので、no titleにも掲載した。

-- A Command-line Tool for Google Translate
-- Copyright : (c) SAEKI Yoshiyasu
-- License   : MIT-style license <http://www.opensource.org/licenses/mit-license.php>
-- last updated: 2010/10/16

import Network.URI
import Data.List
import Network.HTTP
import Text.JSON
import System
import System.Console.GetOpt
import Data.Maybe (fromMaybe)

urlencode :: String -> String
urlencode s = escapeURIString isAlphaNum s
              where
                isAlphaNum c = elem c (['0'..'9'] ++ ['A'..'Z'] ++ ['a'..'z'])

mkParams :: [(String, String)] -> String
mkParams sss = (intercalate "&") $ map pair sss
               where
                 pair e = (urlencode $ fst e) ++ "=" ++ (urlencode $ snd e)

type URL = String

mkGtUrl :: Options -> String -> URL
mkGtUrl optlist text = baseurl ++ (mkParams params)
            where
              baseurl = "http://ajax.googleapis.com/ajax/services/language/translate?"
              params = [("v", "1.0"), ("langpair", fl ++ "|" ++ tl), ("q", text)]
              (Just fl) = froml optlist
              (Just tl) = tol optlist

getHTTPContent :: URL -> IO String
getHTTPContent url = (simpleHTTP $ insertHeader HdrReferer myUrl $ getRequest url)
                     >>= getResponseBody
                         where myUrl = "http://d.hatena.ne.jp/LaclefYoshi/"

toJV :: String -> JSValue
toJV content = let Ok value = decodeStrict content
               in value

getTranslatedtext :: JSValue -> String
getTranslatedtext (JSObject v) = let Ok (JSObject rd) = valFromObj "responseData" v
                                 in let Ok tt = valFromObj "translatedText" rd
                                    in fromJSString tt

data Options = Options {froml :: Maybe String,
                        tol   :: Maybe String} deriving Show

defaultOptions :: Options
defaultOptions = Options {froml  = Just "en", tol = Just "ja"}

options :: [OptDescr (Options -> Options)]
options =
    [ Option ['f'] ["from"]
        (OptArg ((\f opts -> opts { froml = Just f }) . fromMaybe "en") "lang") "FROM",
      Option ['t'] ["to"]
        (OptArg ((\t opts -> opts { tol = Just t }) . fromMaybe "ja") "lang") "TO" ]

compilerOpts :: [String] -> IO (Options, [String])
compilerOpts argv =
    case getOpt Permute options argv of
      (o,n,[]  ) -> return (foldl (flip id) defaultOptions o, n)
      (_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))
        where header = "Usage: PROGRAM [OPTION...] files..."

main :: IO ()
main = do
  argv <- getArgs
  (opts, optvalues) <- compilerOpts argv
  text <- getContents
  content <- getHTTPContent $ mkGtUrl opts text
  putStrLn $ getTranslatedtext $ toJV content

getOptの使い方はライブラリドキュメントコピペ。"Real World Haskell"だと28.8.4に解説がある。

リファラの設定は、Google Cloud Translation API Documentation  |  Translation API  |  Google Cloudで必ず設定しろとあるので、このブログURLを設定してある。

相変わらず、Haskellコーディングは手探り状態だ。

2010-10-07(木)

[]jquery-presentationで発表中にフォントサイズを変える

S5Slidyなど、プレゼンテーションスライドを(HTML/CSS/JS記述して)Webブラウザ上で表示するソフトウェアが幾つかあるが、最近Google Code Archive - Long-term storage for Google Code Project Hosting.を使っている。

プロジェクタ(外部ディスプレイ)でWebブラウザ上のプレゼンテーションスライドをフルスクリーン表示すると、アスペクト比の違いか、解像度の違いか、PCで表示した状態と異なる状態でスクリーン上に投影されることがある。よくある。

これらのソフトウェアは文字サイズが決め打ちか、windowサイズを読んで適当な文字サイズに設定しており、「文字が画面からはみ出ないように」などということは考慮されていない。従って、画面(スクリーン)に適した文字サイズというのは人が確認し設定する必要がある。ていうか、プロプレゼンタなら事前に確認してスライドがちゃんと写るか確認するべきであり、本番でこんなことで困っているようでは素人

兎に角、本番(発表)中にフォントサイズを変えられるようにした。[b]キィでフォントサイズを大きく(bigger)、[s]キィでフォントサイズを小さく(smaller)する。倍率は60%から120%の間で、5%刻みで変えられる。

//////////////////////////////////////////////////////////
// Change the font-size for jquery-presentation         //
//     : http://code.google.com/p/jquery-presentation/  //
//////////////////////////////////////////////////////////

var nowFontsize = 100;  // 100%
var minFontsize = 60;   // 60%
var maxFontsize = 120;  // 120%
var stepFontSize = 5;

$(document).ready(
    function(){
        $.keyDownObserver.observe(
            {
                key: 66,  // b
                fn: $.proxy(bigger, $.presentation.slideManager)
            }
        );
        $.keyDownObserver.observe(
            {
                key: 83,  // s
                fn: $.proxy(smaller, $.presentation.slideManager)
            }
        );
    }
);

function bigger(){
    if(nowFontsize < maxFontsize) {
        nowFontsize += stepFontSize;
        $("body").css("font-size", nowFontsize + "%");
    }
}

function smaller() {
    if(nowFontsize > minFontsize) {
        nowFontsize -= stepFontSize;
        $("body").css("font-size", nowFontsize + "%");
    }
}

jquery.presentation.jsの中身を見て、適当にそれっぽいところを抜き出して、それっぽく追加しただけ。

これを適当jsファイル(changefontsize.js)に書いて、htmlファイル内でjquery.presentation.jsの後に読み込ませる。

<link rel="stylesheet" type="text/css" href="css/common.css" media="screen">
<link rel="stylesheet" type="text/css" href="css/zoomooz.css" media="screen" />
<script type="text/javascript" src="js/jquery.js"></script>
<script type="text/javascript" src="js/jquery.presentation.js"></script>
<script type="text/javascript" src="js/changefontsize.js"></script> <!-- here -->
<script type="text/javascript" src="js/jquery.zoomooz.js"></script>
<script type="text/javascript" src="js/sylvester.js"></script>

jquery-presentationに必須ではないが、画像や特定要素を恰好良く見せるためにZoomooz.jsプレゼンテーションスライドの中で使っている。

2005 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2006 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2007 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2008 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2009 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2010 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2011 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2012 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2013 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2014 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2015 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2016 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |
2017 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 |