Archive for the 'Diary++X' Category

2010/08/10 特定月のDiary++の業務日誌の内容をExcel用Tab区切りテキストとして書き出す

2009/11/03 Diary++X v1.1以降で日付を指定して日記アーティクルを作成

Diary++X v1.1で、日記アーティクル作成時にオブジェクトへの参照が返ってくるようになったことを受けて、ID指定ではなく日記作成日を指定するAppleScriptサンプルです。

サンプルでは2009年11月4日を指定して日記アーティクルを作成していますが、このときDiary++Xのカレンダービュー上で2009年11月4日を選択した状態でもエラーになりません(IDを指定して「D 2009-11-04 1」で作成した場合にはエラーになります)。

Diary++Xにおいては、この形式で指定するのが「定石」ということになるのでしょう。

スクリプト名:Diary++Xで日付を指定して日記アーティクルを作成
set curDateStr to "2009.11.4"
set curDate to date curDateStr

tell application "Diary++X"
  set newArticle to make new article with properties {diary date:curDate}
  
tell newArticle
    set text contents to "つくってみた"
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/11/03 Diary++Xのバージョン1.1が登場

Diary++Xのバージョン1.1が登場していました。AppleScript系の機能で多数のバグ修正が行われています。AppleScript用語辞書上の変更点はありません。

最も特徴的なのは、make new articleの結果として作成したarticleへの参照を返してくるようになった、ということですが……一方で、「カレンダー上で現在選択中の日付(まだ何もarticleが存在していない日付)に対して新規アーティクルを、

tell application “Diary++X”
make new article with properties {id:”D 2009-11-04 1″}
end tell

のようにして作成しようとすると、

error ”Diary++X でエラーが起きました:AppleEvent のハンドラで誤りが起きました。” number -10000

と、エラーになるところは相変わらずです。

dia1.jpg

カレンダービュー上の選択日付が、新規アーティクルの作成対象日ではないように操作しておかないとエラーになります。あるいは、アーティクル作成時に、

make new article with properties {diary date:date “2009.11.4″}

のように、IDではなく「日付」で指定するのが安全策といえるでしょう。

2009/09/19 Diary++Xで最近の日記本文をもとに今日の日記を新規作成する v3

Diary++X 1.0.3用にこのAppleScriptを書いて使ってみたものの、実際に使ってみるとだんだん問題点が見えてきました。

たとえば、9月19日の日記(たいていは仕事の内容やアイデアなどをまとめたもの)を書こうとして、このAppleScriptを実行。Script Menuに入れておいてメニューから実行することになるわけですが、その時にDiary++Xのカレンダービューで9月19日を選択した状態だと、なぜか「D 2009-9-19 1」ではなく、「D 2009-9-19 2」というエントリができてしまいます。

作ろうとしたエントリのIDが勝手にアプリケーション側の都合で変わってしまうのであれば、以前に指摘したように、

set newArticle to (make new article)
tell newArticle
 –何かの命令
end

のように、作成時にエントリへの参照を返すべきです。参照は返さないわ、指定したIDでエントリを作れないわでは話になりません。

ただ、文句を言っているばかりでは話にならないので、アプリケーションの挙動(バグの度合い)を見ながら、解決方法を模索することになります(Adobeのアプリケーションのバグの多さには辟易するばかり。本当にあの会社は出荷前にチェックをしているのか疑問です)。

この現象は、ユーザーがGUIからカレンダービュー上の9月19日のセルを選択した瞬間に、Diary++Xがこっそり「D 2009-0-19 1」というエントリを(ないしょで)確保。この日付に対してユーザーからのキーボード入力が行われた場合に備えておくようにしているのではないか? このため、エントリのIDにズレが生じるのではないか、と推測しました。

そこで、「D 2009-0-19 1」というエントリを作成する前に、この「9月19日」以外のどこか別の日付のエントリを選択した状態を作り出しておき、その後で「D 2009-0-19 1」を作成してやれば問題はないのではないか? と考え、その通りにAppleScriptを修正。

結果は、想像どおり。このバージョン3で、無事に直近の日記をもとに本日の日記エントリを作成するという構想を満たすものとなりました。

かように、AppleScriptでアプリケーションをコントロールするということは、そのアプリケーションの機能や方向性を理解し、挙動のクセを把握したうえで、実際にプログラムを書いて実行してはきちんと動くかどうか確認を行うという……ひじょうに地味で地道な作業の繰り返しが要求されます。

ただ、それをひたすら積み上げていくと、トンでもないことができるようになってみたりするものです。

スクリプト名:Diary++Xで最近の日記本文をもとに今日の日記を新規作成する v3
今日のアーティクルが存在しているかどうかチェック
set todaysDate to do shell script “date +%Y-%m-%d”
set anArticleID to (”D ” & todaysDate & ” 1″)
set aRes to retExsists(anArticleID) of me
if aRes = true then
  すでに今日の日記が存在したら処理終了
  
display dialogすでに本日の日記が存在するので処理を中断しますbuttons {”OK”} default button 1 with icon 1
  
return
end if

今日の日記が存在しない場合(想定しているパターン)
set decCount to 1
set curDate to current date

過去にさかのぼって日記の記事を検索(ただし100日前まで)
repeat
  set curDateTmp to curDate - decCount * days
  
  
set aYear to year of curDateTmp
  
set aMonth to month of curDateTmp as number
  
set aDate to day of curDateTmp
  
  
set aYearStr to retZeroPaddingText(aYear, 4) of me
  
set aMonthStr to retZeroPaddingText(aMonth, 2) of me
  
set aDateStr to retZeroPaddingText(aDate, 2) of me
  
  
set todaysDateTmp to aYearStr & “-” & aMonthStr & “-” & aDateStr
  
set anArticleIDTmp to (”D ” & todaysDateTmp & ” 1″)
  
set aRes to retExsists(anArticleIDTmp) of me
  
  
if aRes = true then exit repeat
  
  
set decCount to decCount + 1
  
if decCount = 100 then
    display dialog “100日さかのぼりましたが、過去の日記は存在しませんでした。buttons {”OK”} default button 1 with icon 1
    
return
  end if
end repeat

発見した直近の日記の本文をコピーして本日の日記を作成する
tell application “Diary++X”
  tell document 1
    
    
set current article to article id anArticleIDTmp ★ ここを付け足した ★
    
本日の日付がカレンダー上で選択されている状態で本日の日記をAS側から作成しようとすると、
    
–1番の記事がリザーブされてしまうためか、2番の記事が作成されてしまう(アプリ側のバグ)
    
これを回避するため、一時的に選択日付を今日以外の場所に移動させる。記事が存在さえして
    
いれば別に直近の記事でなくてもよい
    
    
    
直近のアーティクル本文をコピー    
    
tell article id anArticleIDTmp
      set oldContents to text contents
    end tell
    
    
今日の日記アーティクルを作成し、本文に一番近い過去のアーティクル本文を突っ込む
    
make new article
    
tell article id anArticleID
      set text contents to oldContents
    end tell
    
    
作成した日記を表示状態に
    
set current article to article id anArticleID
  end tell
end tell

指定IDのアーティクルが存在するかどうか調べて返す
on retExsists(anArticleID)
  tell application “Diary++X”
    tell document 1
      set dExists to (exists of article id anArticleID)
    end tell
  end tell
  
return dExists
end retExsists

数値にゼロパディングしたテキストを返す
on retZeroPaddingText(aNum, aLen)
  set tText to (”0000000000″ & aNum as text)
  
set tCount to length of tText
  
set resText to text (tCount - aLen + 1) thru tCount of tText
  
return resText
end retZeroPaddingText

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/09/16 Diary++Xで最近の日記本文をもとに今日の日記を新規作成する v2

Diary++ Xで最近の日記本文をもとに今日の日記を新規作成するAppleScriptのバグ修正版です。

日付をさかのぼる際に、current dateを保持する変数を更新してしまっていたので、その点を直しています。

スクリプト名:Diary++Xで機能の内容を今日の日記にコピーする v2
–今日のアーティクルが存在しているかどうかチェック
set todaysDate to do shell script "date +%Y-%m-%d"
set anArticleID to ("D " & todaysDate & " 1")
set aRes to retExsists(anArticleID) of me
if aRes = true then
  –すでに今日の日記が存在したら処理終了
  
display dialog "すでに本日の日記が存在するので処理を中断します" buttons {"OK"} default button 1 with icon 1
  
return
end if

–今日の日記が存在しない場合(想定しているパターン)
set decCount to 1
set curDate to current date

–過去にさかのぼって日記の記事を検索(ただし100日前まで)
repeat
  set curDateTmp to curDate - decCount * days
  
  
set aYear to year of curDateTmp
  
set aMonth to month of curDateTmp as number
  
set aDate to day of curDateTmp
  
  
set aYearStr to retZeroPaddingText(aYear, 4) of me
  
set aMonthStr to retZeroPaddingText(aMonth, 2) of me
  
set aDateStr to retZeroPaddingText(aDate, 2) of me
  
  
set todaysDateTmp to aYearStr & "-" & aMonthStr & "-" & aDateStr
  
set anArticleIDTmp to ("D " & todaysDateTmp & " 1")
  
set aRes to retExsists(anArticleIDTmp) of me
  
  
if aRes = true then exit repeat
  
  
set decCount to decCount + 1
  
if decCount = 100 then
    display dialog "100日さかのぼりましたが、過去の日記は存在しませんでした。" buttons {"OK"} default button 1 with icon 1
    
return
  end if
end repeat

–過去の日記の存在確認
tell application "Diary++X"
  tell document 1
    –ヒットした、一番近い過去のアーティクル本文をコピー
    
tell article id anArticleIDTmp
      set oldContents to text contents
    end tell
    
    
–今日の日記アーティクルを作成し、本文に一番近い過去のアーティクル本文を突っ込む
    
make new article
    
tell article id anArticleID
      set text contents to oldContents
    end tell
    
    
–作成した日記を表示状態に
    
set current article to article id anArticleID
  end tell
end tell

–指定IDのアーティクルが存在するかどうか調べて返す
on retExsists(anArticleID)
  tell application "Diary++X"
    tell document 1
      set dExists to (exists of article id anArticleID)
    end tell
  end tell
  
return dExists
end retExsists

–数値にゼロパディングしたテキストを返す
on retZeroPaddingText(aNum, aLen)
  set tText to ("0000000000" & aNum as text)
  
set tCount to length of tText
  
set resText to text (tCount - aLen + 1) thru tCount of tText
  
return resText
end retZeroPaddingText

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/09/16 Diary++Xで最近の日記本文をもとに今日の日記を新規作成する

Diary++ X バージョン1.0.3以降で、当日の日記アーティクルが存在しないことを確認し、存在しない場合には日付をさかのぼって一番最近書いた日記の内容をコピーして当日の日記記事にペーストします。

Diary++X上で日記なり業務記録をつけている場合に、毎日同じようなフォーマットの記述を行うようにしています。仕事の内容や個人的な調査内容、家庭で何をしたかなど……前日の内容をコピーして、当日の日記アーティクルとして自動的に作成してくれたら楽です。

そこで、本AppleScriptを作成してみました(所用時間15分ぐらい)。Script Menuに入れて使用することを前提にしています。

こうして、実戦レベルのAppleScriptを書いてみると、「make new article」を実行した結果として返ってきた値にtellしたいのにできないとか、Diary++Xのスクリプティング上の問題点が見えてきます。

set newArticle to (make new article)
tell newArticle
 –何かの命令
end

と、だいたいこんな書き方ができるのが一般的なアプリケーションの挙動ですが、これをDiary++Xで行うとエラーになります。このあたりの挙動がいまひとつ、といったところでしょうか。

スクリプト名:Diary++Xで機能の内容を今日の日記にコピーする
–今日のアーティクルが存在しているかどうかチェック
set todaysDate to do shell script "date +%Y-%m-%d"
set anArticleID to ("D " & todaysDate & " 1")
set aRes to retExsists(anArticleID) of me
if aRes = true then
  –すでに今日の日記が存在したら処理終了
  
display dialog "すでに本日の日記が存在するので処理を中断します" buttons {"OK"} default button 1 with icon 1
  
return
end if

–今日の日記が存在しない場合(想定しているパターン)
set decCount to 1
set curDate to current date

–過去にさかのぼって日記の記事を検索(ただし100日前まで)
repeat
  set curDate to curDate - decCount * days
  
  
set aYear to year of curDate
  
set aMonth to month of curDate as number
  
set aDate to day of curDate
  
  
set aYearStr to retZeroPaddingText(aYear, 4) of me
  
set aMonthStr to retZeroPaddingText(aMonth, 2) of me
  
set aDateStr to retZeroPaddingText(aDate, 2) of me
  
  
set todaysDateTmp to aYearStr & "-" & aMonthStr & "-" & aDateStr
  
set anArticleIDTmp to ("D " & todaysDateTmp & " 1")
  
set aRes to retExsists(anArticleIDTmp) of me
  
  
if aRes = true then exit repeat
  
  
set decCount to decCount + 1
  
if decCount = 100 then
    display dialog "100日さかのぼりましたが、過去の日記は存在しませんでした。" buttons {"OK"} default button 1 with icon 1
    
return
  end if
end repeat

–過去の日記の存在確認
tell application "Diary++X"
  tell document 1
    –ヒットした、一番近い過去のアーティクル本文をコピー
    
tell article id anArticleIDTmp
      set oldContents to text contents
    end tell
    
    
–今日の日記アーティクルを作成し、本文に一番近い過去のアーティクル本文を突っ込む
    
make new article
    
tell article id anArticleID
      set text contents to oldContents
    end tell
    
    
–作成した日記を表示状態に
    
set current article to article id anArticleID
  end tell
end tell

–指定IDのアーティクルが存在するかどうか調べて返す
on retExsists(anArticleID)
  tell application "Diary++X"
    tell document 1
      set dExists to (exists of article id anArticleID)
    end tell
  end tell
  
return dExists
end retExsists

–数値にゼロパディングしたテキストを返す
on retZeroPaddingText(aNum, aLen)
  set tText to ("0000000000" & aNum as text)
  
set tCount to length of tText
  
set resText to text (tCount - aLen + 1) thru tCount of tText
  
return resText
end retZeroPaddingText

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/09/14 Diary++X 1.0.3で指定カテゴリ内のアーティクルを取得する

Diary++X バージョン1.0.3が登場。AppleScript関連の命令が大幅に強化されました。

以前に指摘した点がほとんど修正されているのは「お見事」としかいいようがありません。脱帽です。

本AppleScriptでは、指定カテゴリ内のアーティクル(記事)の一覧を取得します。結果はリストで返ってきます。

スクリプト名:Diary++X 103で指定カテゴリ内のアーティクルを取得する
tell application "Diary++X"
  tell document 1
    tell category "履歴"
      set aList to every article
      
–> {article 1 of document "Diary++X" of application "Diary++X", article 2 of document "Diary++X" of application "Diary++X", (省略) }
    end tell
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/06/30 Diary++Xで指定カテゴリ内のアーティクルを取得する

Diary++Xで、指定カテゴリ内のアーティクルを取得するAppleScriptです。

指定のカテゴリ内に入っているアーティクルを取得するのに、指定カテゴリの「contained articles」という属性に対してアクセスする必要があります。このあたりに少々クセがあるのが気になりますが、そういうものだと思えば納得できるレベルでしょうか。

普通、こうした場合には「every article」で指定カテゴリ内に存在するアーティクルを取得することになるはずですが……おそらく、実装のしやすさからこのような仕様になったものでしょう。

AppleScriptの初心者がつまづくのが、こういうイレギュラーな実装を行っているアプリケーションに出くわした時です。実は、言語処理系そのものではなくアプリケーション側の対応に問題があるケースの方が多く……アプリケーション開発者がAppleScriptについて十分な知識を持っていないために起こるトラブルが多いといえます。

Diary++X作者のMikoさんは日本のアプリ開発者の中でもAppleScriptへの理解がある方ですが、まだ本アプリケーションの開発段階が初期段階であるために目下試行錯誤している状態なのでしょう。

スクリプト名:Diary++で指定カテゴリ内のアーティクルを取得する
tell application Diary++X
  tell document 1
    tell category 履歴
      set cList to every category
      
> {category “履歴:2009年6月29日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年5月1日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月30日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月29日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月28日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月27日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年4月26日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2009年1月21日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2007年10月29日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2007年1月9日” of category “履歴” of document “Diary++X” of application “Diary++X”, category “履歴:2006年9月3日” of category “履歴” of document “Diary++X” of application “Diary++X”}
      
      
tell first category
        set aList to contained articles
        
repeat with i in aList
          tell i
            set aType to type
            
log aType
          end tell
        end repeat
      end tell
    end tell
  end tell
end tell

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/06/29 Diary++Xでカテゴリ情報を取得

Diary++Xでカテゴリの情報を取得するAppleScriptです。

diary1.jpg

Diary++Xでは、Mail.appのように「受信/ML/Apple/AppleScript Users」といったように階層構造をそのまま指定することはできません。だいたい、MacJournalと同レベルの実装にとどまっている状態で、実用的なスクリプトを書くためにはカテゴリ階層へのアクセスの改善がポイントになるでしょうか。

ブックマークの機能も持っていますが、はたして「ブックマーク」という概念自体に意義があるのかどうかという点にも疑問が残ります。いっそ、ページの内容を取得してPDFでコンテンツそのものを保持しておいたほうが「Webページスクラップブック」として有効に利用できるのではないか……などと思うものです。

スクリプト名:Diary++でカテゴリ情報を取得
tell application "Diary++X"
  tell document 1
    set cList to every category
  end tell
end tell

> {category "日記" of document "Diary++X" of application "Diary++X", category "メモ" of document "Diary++X" of application "Diary++X", category "ブックマーク" of document "Diary++X" of application "Diary++X", category "履歴" of document "Diary++X" of application "Diary++X"}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/06/29 Diary++Xでドキュメントの情報を取得

Diary++Xでドキュメントの情報を取得するAppleScriptです。同梱のドキュメントによれば、Diary++Xは同時に1つのドキュメントだけを開けるようになっているとのこと。

さらに、ドキュメントのプロパティに「選択中のアーティクル」(current selected articles)があるのが注意点でしょうか。複数の選択アーティクルを許容し、リストで取得できるようになっています。

ただし、「選択中のカテゴリ」の情報を取得できるようにはなっておらず、このあたりに課題を残しているといえるでしょう。

スクリプト名:Diary++でドキュメントの情報を取得
tell application "Diary++X"
  tell document 1
    properties
  end tell
end tell
> {modified:false, class:document, current article:article -2.147483648E+9 of document "Diary++X" of application "Diary++X", current selected articles:{}, file:file "Cherry:Users:maro:Library:Application Support:Diary++X:", name:"Diary++X"}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/06/29 Diary++Xでアプリの情報を取得

バージョンアップしてAppleScript系の実装が修正されたDiary++X v1.02。AppleScript側からアーティクル(記事)への読み書きを行う前に特定の命令を実行する必要がなくなりました。

そんなDiary++Xでアプリケーションの情報を取得するAppleScriptです。Selectionの属性はApplicationではなくdocumentから取得するようになっているので、この階層で何か有用な情報が得られるとかいったことは特にないようです。

スクリプト名:Diary++でアプリの情報を取得
tell application "Diary++X"
  properties
end tell
> {frontmost:false, class:application, version:"0", name:"Diary++X"}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2009/04/29 Diary++Xで選択中の記事のプロパティを取得する

日記ソフト「Diary++X」で選択中の記事のプロパティを取得するAppleScriptです。

diary1.jpg

同ソフトは、AppleScript対応機能を重視し、プラグインとしてメニューからAppleScriptを呼び出せるようになっているほか、AppleScript記述のドキュメントを同梱。ドキュメントを読むことでScriptingが円滑に行えるようになっています。

……ただし、同ドキュメントを読まないかぎりDiari++Xの特殊な構造について知ることはできず、きわめてクセの強いソフトであると言うことも可能です。

主にarticleに対してアクセスすることになり、フィルタ参照なども使えるのですが、本文(contents)にアクセスする際にGUI側から変更されないようGUIとの排他制御を行う「open text contents」「close text contents」をわざわざアクセスの前後に実行しなくてはならないというのはダメすぎです(そんなダメな実装は世界広しといえどもこのソフトだけです)。

また、AppleScriptから日記やメモのフォルダ階層構造などにもアクセスしたくなりますが、その方面のオブジェクトは何も実装されていません。

スクリプト名:Diary++Xで選択中の記事のプロパティを取得する
tell application Diary++X
  tell document 1
    tell current article
      properties
    end tell
  end tell
end tell
> {label:0, text contents:”てすとの日記”, edited:true, id:”D 2009-04-29 2″, date created:missing value, name:”2009年4月29日水曜日 2″, selected text:”", dated:true, page:2, chapter name:missing value, class:article, title:”てすとだよ”, keywords:{}, diary date:date “2009年 4月 29日 水曜日 0:00:00 AM”, date modified:missing value}

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に