Archive for the 'mi' Category

2017/01/27 ASOCの美しい書き方?

AppleScriptからCocoaの機能を呼び出すことができるようになり、AppleScript本来の簡潔な記述はしにくくなりました。

ASOCの記述方法について、どのようなアプローチが可能かをまとめてみました。

(1)は、ふだん書いているやり方です。一番安全で確実にAppleScriptの処理系に解釈されるので、トラブル回避のためにこの書き方をしています。ただし、1行がものすごく長くなるので、本Blogに掲載したときの「見た目」がよろしくありません(エディタの上では問題ないのですが、、、)

(2)は、Xcode上のAppleScriptでよくやる書き方です。インデントを基本としたAppleScriptらしいスタイルにはなっているものの、書かなくてはならない情報が多く、やや面倒と感じます。

(3)は、(2)でインデントの段数の増えすぎたことに対する改良とでも呼ぶべきものでしょうか。「its」を毎回書く必要があることに対し、抵抗感があるかないかが問題でしょう。

(4)は、Script Debugger 6のテンプレートに入っていた記述で、なかなかいい手だと思います(Xcode上でもやっていましたが)。ただ、プログラムが長く複雑になると冒頭のProperty宣言部分がどんどん長くなるという問題もあります。

サンプルとして書くのであれば、(4)あたりを検討すべきなんでしょう。

AppleScript名:(1)quick style
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4412

set a to (current application’s NSString’s stringWithString:“aaaaa”) as string
–>  ”aaaaa”

★Click Here to Open This Script 

AppleScript名:(2)xcode style
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4412

tell current application
  tell class “NSString”
    set a to (its stringWithString:“aaaaa”) as string
  end tell
end tell
–>  ”aaaaa”

★Click Here to Open This Script 

AppleScript名:(3)layer style
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4412

tell current application’s NSString
  set a to (its stringWithString:“aaaa”) as string
end tell
–>  ”aaaa”

★Click Here to Open This Script 

AppleScript名:(4)mark alldritt style
use AppleScript version “2.4″
use framework “Foundation”
use scripting additions
–http://piyocast.com/as/archives/4412

property NSString : a reference to current application’s NSString

set a to (NSString’s stringWithString:“aaaa”) as string
–>  ”aaaa”

★Click Here to Open This Script 

実際に(4)のスタイルで書いてみたら、NSMakeRangeやNSMaxRangeなどのObjective-Cのメソッドでない部分を同じスタイルに統一できなくて(current application’sを省略できなくて)、化けきれていない感じが、、、、

あとは、スクリプトエディタ上だとほとんど構文要素の変化に乏しく、メリハリがない(構文要素カラーリングの効果がなく)ので書く方にとって読みにくくなるような気がします。

macOS標準搭載のスクリプトエディタでは、Cocoaのclass名もmethod名も同じ色で表示されてしまいますが、ASObjC Explorer 4やScript Debugger 6ではmethod名を別の色で表示する機能が実装されているため、やはりそうしたツールがないと辛い感じです。

mi.png

AppleScript名:テキストエディタ「mi」で選択中のテキストからHTMLタグを外して逆順に並べなおす
– Created 2017-01-27 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
–http://piyocast.com/as/archives/4412

property NSString : a reference to current application’s NSString
property NSAttributedString : a reference to current application’s NSAttributedString
property NSArray : a reference to current application’s NSArray
property NSMutableArray : a reference to current application’s NSMutableArray
property NSUTF16StringEncoding : a reference to current application’s NSUTF16StringEncoding

tell application “mi”
  tell document 1
    set aText to selection
  end tell
end tell

–選択部分のテキストからHTMLのタグを外す
set anNSString to NSString’s stringWithString:aText
set theData to anNSString’s dataUsingEncoding:(NSUTF16StringEncoding)
set styledString to NSAttributedString’s alloc()’s initWithHTML:theData documentAttributes:(missing value)
set plainText to (styledString’s |string|())

–テキストを行ごとにparseしてNSArrayに
set anArray to NSMutableArray’s alloc()’s init()
set aRange to current application’s NSMakeRange(0, plainText’s |length|())

repeat while aRange’s |length|() > 0
  set subRange to plainText’s lineRangeForRange:(current application’s NSMakeRange(aRange’s location(), 0))
  
  
–行が改行コードまで取得されるので、改行コードを除外するように微調整
  
copy subRange to tmpRange
  
set tmpRange’s |length| to ((subRange’s |length|()) - 1) –微調整
  
set aLine to plainText’s substringWithRange:tmpRange
  
anArray’s addObject:aLine
  
  
set aRange’s location to (current application’s NSMaxRange(subRange))
  
set aRange’s |length| to ((aRange’s |length|()) - (subRange’s |length|()))
end repeat

–NSArrayを逆順に(reverse order array)
set outArray to (anArray’s reverseObjectEnumerator())’s allObjects()

–NSArray to string with line delimiter
set outStr to retStrFromArrayWithDelimiter(outArray, return) of me

–リストを指定デリミタをはさんでテキスト化
on retStrFromArrayWithDelimiter(aList, aDelim)
  set anArray to NSArray’s arrayWithArray:aList
  
set aRes to anArray’s componentsJoinedByString:aDelim
  
return aRes as text
end retStrFromArrayWithDelimiter

★Click Here to Open This Script 

2013/03/17 miで文字置換v2

Macのテキストエディタ「mi」でオープン中のテキストファイルの文字置換を行うAppleScriptのサンプルです。

miの新しいバージョン3.0betaが出たので、AppleScript系の機能をチェックしていたところ……以前に掲載したmiの文字置換ルーチンの内容を見て、

  「何を無駄な処理をしているんだろう?」

と気付き、書き換えたものです。

mi1.png

mi2.png

以前に掲載したものは、1行ごとに取り出して、行ごとに置換していました(←バカ)。AppleScriptのtext item delimiterの性質を考えると、大量のデータを一気に置換するように組まないとスピードが出ないわけで……データを小分けにして置換してもぜんぜん意味がありません。

たぶん、テキストの行数が増えれば増えるほど所要時間が変わってくるはずです。

mi 3.0betaについては、まだまだ作成途上という印象で……AppleScript系の機能についても、まだ各種オブジェクトからのプロパティを取得できないとか、大幅に刷新されたGUIに対するオブジェクトの定義があるんだかないんだか分らなかったり、というところです。

miのライバルは、フリー配布されていながら機能豊富なTextWraglerだと思います。

差分表示機能を強化しているあたり、このTextWranglerやらJeditやらを意識していると思いますが、最近Windowsから移行してきたユーザーが必要としていると思われるCP932のテキストのサポートあたりで差別化すべきではないかと。

スクリプト名:miで文字置換v2
script spd
  property inList : missing value
  
property outList : missing value
end script

set targStr to “ぴよ” –置換対象文字列
set repStr to “ぷよ” –置換後文字列

set inList of spd to {}
set outList of spd to {}

–最前面のドキュメントから本文を取得
tell application “mi”
  tell document 1
    set (inList of spd) to content
  end tell
end tell

–置換処理
set (outList of spd) to repChar((inList of spd), targStr, repStr) of me

–最前面のドキュメント本文に置換結果を戻す
tell application “mi”
  tell document 1
    set content to (outList of spd)
  end tell
end tell

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

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

2013/02/03 miで文字置換

国産テキストエディタ「mi」でAppleScript経由で文字置換を行うサンプルです。

miのAppleScript用語辞書をAppleScriptエディタでひらいて見ると、とても特徴的な内容であることが見てとれます。

miの用語辞書には、WindowやDocument、そしてその下部構造であるparagraphやwordを読み書きしたり、選択中の箇所を読み書きするためのオブジェクトしか定義されていません。コマンドの定義はほとんどありません。

mi3.png

AppleScriptをよく知らない方が、miで文字置換を行うために、GUI Scriptingで延々とメニューから置換コマンドを呼び出して置換している例を見たことがありますが、そこまで努力しても残念なことに他のMac上では動かなかったとか。ダイアログの座標などを決め打ちで指定していたので、別のマシン上では動かないのは当然のことでしょう。

miのAppleScript用語辞書からいえることは、「置換は自分でやってね」ということ。値の取り出しと格納はできるので、あとは好きに処理してほしいということです。中途半端にダメダメな用語辞書を載せて使い物になっていないXcodeなどよりも、ずっと潔いと思います。

当然、AppleScriptによる文字置換ルーチンなどは当たり前のように作って日常的に使っていますので、ただそれを使うだけです。他の言語処理系を呼び出して処理してもよいでしょう。

実際、テキストエディタでわざわざ文字置換処理を行う必要などほとんどないのですが(AppleScript単独でファイルをオープンして置換して保存すればいい)、文字コードが不明な大量のテキストファイルをオープンして決められた文字コードで保存するため「だけ」に必要だといわれます。

だとすれば、オープンソースのテキストエディタの文字コード判定部分だけもってきて、AppleScriptObjCで機能を呼び出して使えばいいんじゃないかと思うのですが……。あとは、文字コード判定を行ってくれるOSAXを見つけてきて、OSAXの命令を使ってファイルの読み書きをするとか。

mi1.png

▲実行前の状態

mi2.png

▲実行後の状態

スクリプト名:miで文字置換
script spd
  property inList : missing value
  
property outList : missing value
end script

set targStr to “ぴよ” –置換対象文字列
set repStr to “ぷよ” –置換後文字列

set inList of spd to {}
set outList of spd to {}

–最前面のドキュメントから本文を取得
tell application “mi”
  tell document 1
    set (inList of spd) to every paragraph
  end tell
end tell

–置換処理
repeat with i in (inList of spd)
  set j to contents of i
  
set jj to repChar(j, targStr, repStr) of me
  
set the end of (outList of spd) to jj
end repeat

–最前面のドキュメント本文に置換結果を戻す
tell application “mi”
  tell document 1
    set pCount to count every paragraph
    
repeat with i from 1 to pCount
      set j to content of item i of (outList of spd)
      
set content of paragraph i to j
    end repeat
  end tell
end tell

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

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

2011/12/21 miで選択中の内容をファイルに書き出してperlのプログラムとしてterminalで実行 v2

miの最前面のドキュメント上で選択中のテキストをファイルに書き出して、perlのプログラムとしてTerminalで実行するAppleScriptのバグ修正版です。

最初のバージョンでは、改行コードがCRの状態で書き出されていたため、改行コードをLFに置換してから実行するようにしました。

初版では、選択範囲にコメント行が含まれているとエラーになっていたりしましたが、このバージョンではそういうことはありません。

スクリプト名:miで選択中の内容をファイルに書き出してperlのプログラムとしてterminalで実行 v2
tell application “mi”
  tell front document
    set this_data to selection
    
    
–エラー対策
    
if this_data = “” then
      display dialog “文字列が何も選択されていません” buttons {“OK”} default button 1 with icon 1 with title “エラー”
      
return
    end if
    
    
set this_data to this_data as Unicode text
    
  end tell
end tell

–改行コードがCRになっている部分をLFに置換(v2で追加)
set this_data to repChar(this_data, ASCII character 13, ASCII character 10) of me

set tmpPath to path to temporary items from user domain
set fStr to (do shell script “date +%Y%m%d%H%M%S”) & “.pl”
set fPath to (tmpPath as string) & fStr

write_to_fileUTF8(this_data, fPath, false) of me
do shell script “sync”

set sText to “perl -w “ & quoted form of POSIX path of fPath
doComInTerminalWindow(sText) of me

on doComInTerminalWindow(aCMD)
  tell application “Terminal”
    set wCount to count (every window whose visible is true)
    
    
– By wayne melrose
    
– Re: New window in Terminal.app
    
    
if wCount = 0 then
      –ウィンドウが1枚も表示されていない場合
      
do script aCMD
    else
      –すでにウィンドウが表示されている場合
      
do script aCMD in front window
    end if
  end tell
end doComInTerminalWindow

–ファイルの追記ルーチン「write_to_file」
–追記データ、追記対象ファイル、boolean(trueで追記)
on write_to_fileUTF8(this_data, target_file, append_data)
  try
    set the target_file to the target_file as text
    
set the open_target_file to open for access file target_file with write permission
    
if append_data is false then set eof of the open_target_file to 0
    
write this_data to the open_target_file as «class utf8» starting at eof
    
close access the open_target_file
    
return true
  on error error_message
    try
      close access file target_file
    end try
    
return error_message
  end try
end write_to_fileUTF8

–文字置換ルーチン
on repChar(origText, targStr, repStr)
  set {txdl, AppleScript’s text item delimiters} to {AppleScript’s text item delimiters, targStr}
  
set temp to text items of origText
  
set AppleScript’s text item delimiters to repStr
  
set res to temp as text
  
set AppleScript’s text item delimiters to txdl
  
return res
end repChar

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

2009/01/21 miで選択中のテキストを取得する

Mac OS X用テキストエディタ「mi」のAppleScript命令体系、オブジェクト体系は、非常に手堅くオーソドックスなものです。派手な命令はありませんが、安心できる内容です。
(more…)