スポンサーサイト

Tags :
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

AppleScriptのシンタックスをハイライトしたHTMLを生成するWebフォームを作ってみた

AppleScriptの構文を色分けして表示させるためのHTMLを生成するWebフォームをJavaScriptで作ってみました。まだまだ対応しきれてない構文とかあると思いますが。

Syntax Highlighting for AppleScript

実用性を考えると、HTMLを生成するフォームではなくて、『SyntaxHighlighter』とか『GeSHi』みたいにblogに設置しておいて、例えば<pre>要素のclassを指定してやれば勝手にハイライトするようなのが良いんですが、まずは構文の色付けする部分をマトモに動かす事から…みたいな感じで。まあ一回やってみたかったんです。

『GeSHi』なんかはAppleScriptにも対応してるんですが、色分け出来る予約語も多くないし、スクリプト中に他の言語が混ざってたりすると表示がおかしくなってしまい、今ひとつ完全ではない感じでした。

フォームの上側のテキストエリアに、スクリプトエディタからコピーしたコードをペーストして『Highlight!』ボタンを押すと、下側のテキストエリアに『<span class="hoge">~</span>』の形で区切られたHTMLが表示され、さらにその下が実際に色分けされた表示になります。AppleScriptのコードをコピペ出来るように、行番号抜きのHTMLも生成出来ます。

ハイライト表示のために、以下のcssを追加する必要があります
.applescript {
	font-size: 11px;
	width: inherit;
	overflow: scroll;
}

/* 行番号ありの場合はol要素 */
/* 行番号なしの場合はdiv要素のclass名 */    
.ash_highlighted {
	white-space: nowrap;
	color: #999;
	background-color: #f8f8f8;
	list-style-position: outside;
	list-style-type:decimal;
}

/* 行番号なしの場合のdiv要素調整用 */
div.ash_highlighted {
	padding-left: 1.5em;
	padding-top: 1em;
	padding-bottom: 1em
}

span.ash_reserved { color: #33c; } /* 予約語 */
span.ash_variable { color: #383; } /* 変数名 */
span.ash_handler { color: #383; } /* ハンドラ */
span.ash_quoted { color: #c3c; } /* クォートされた文字列 */
span.ash_symbol	{ color: #000; } /* 記号類 */
span.ash_normal	{ color: #000; } /* 上記以外の数字など */
span.ash_comment { color: #757; } /* コメント */

/* 行番号ありの場合のコード部分との境界 */
.applescript li { border-left: solid 1px #ccc; padding-left: 1em; }

/* 奇数行の背景色 */
li.odd { background-color: #fff; }

生成されたHTMLをblogに貼り付けるとこんな感じになります。
  1. property work_folder : "Images for Web" as Unicode text --保存先のフォルダ名(デスクトップに作成) 
  2. property jpeg_quality : 10 as integer --JPEGの画質(0-12) 
  3. on open drop
  4.     tell application "Finder"
  5.         if not (exists folder work_folder of desktop) then
  6.             make new folder with properties {name:work_folder} at desktop
  7.         end if
  8.         set dest_path to ((path to desktop folder) as Unicode text) & work_folder
  9.         set img_size to text returned of (display dialog "生成する画像の長辺のサイズ(ピクセル数)を入力。" default answer "") as integer
  10.     end tell
  11.     
  12.     (*ディスプレイプロファイル取得*)
  13.     tell application "ColorSyncScripting"
  14.         set profile_name to name of display profile of display 1
  15.     end tell
  16.     
  17.     repeat with theFile in drop
  18.         tell application "Adobe Photoshop CS2"
  19.             open theFile showing dialogs never
  20.             set theDoc to current document
  21.             tell theDoc
  22.                 if width > height then
  23.                     resize image width img_size as pixels resolution 72 resample method bicubic
  24.                 else
  25.                     resize image height img_size as pixels resolution 72 resample method bicubic
  26.                 end if
  27.                 change mode to RGB
  28.                 convert to profile profile_name intent relative colorimetric with blackpoint compensation and dithering
  29.                 set save_opts to {class:JPEG save options, embed color profile:false, quality:jpeg_quality}
  30.                 set new_name to my replaceExtension(name of theDoc, "jpg") as Unicode text
  31.                 set dest_file to dest_path & ":" & new_name
  32.                 save in file dest_file as JPEG with options save_opts appending no extension with copying
  33.                 close without saving
  34.             end tell
  35.         end tell
  36.     end repeat
  37. end open
  38. (* 拡張子を変更したファイル名を返す 簡易版 *)
  39. on replaceExtension(fName, new_ext)
  40.     tell application "Finder"
  41.         set base_name to (do shell script "echo " & quoted form of fName & " | sed 's/\.[^.]*$//'") as Unicode text
  42.         return base_name & "." & new_ext
  43.     end tell
  44. end replaceExtension

XML等の文字参照を通常の文字列に戻すAppleScript

■4/7追記 こちらのエントリにもっとシンプルなのがあります。
Webで利用される様々な文字列エンコードを扱うためのAppleScriptいろいろ


『&amp;』や『&#12345;』といった文字参照を含む文字列を通常の文字列に戻すAppleScript。

Twitterなんかの海外のWebサービスのRSSや、APIで取得出来るXMLの日本語部分が数値文字参照で返ってくるものがありますが、それを AppleScriptで扱うにはどうしたら良いか…やり方を軽く探してみたんですが見付けられなかったので自分で書きました。OSAXとかありそうですけど、とりあえず素の状態でやりたかったんで。

何が何でもAppleScriptで処理しないといけない場面はそれほど無いとは思いますが。

スクリプトの要になる、文字を変換する部分は最近かじり始めたpythonを使ってます。あと、これは以前ぴよまるさんが文字列を処理するのにpythonを使ってられたのをヒントにしました。

このスクリプトを実行すると、復元された文字列が表示されます。

1文字ずつdo shell scriptで変換して行くので処理はやや遅いです。数文字まとめてpythonに渡すようにした方が良かったですね。整形が面倒ですけど。

『&amp;』等を1つだけ引数で渡して変換した文字を返す部分だけ関数化しました。

■2/15追記■
気になった部分を若干修正

■3/3追記■
MacOSX10.5のAppleScript2.0だと、Unicode textのidプロパティ使えばもっと素直に変換できますね

■動作確認■
MacOSX10.4.11
property bslashChr : ASCII character (128)

--my_stringsに処理する文字参照を含んだ文字列を入れておく
set my_strings to "&amp;amp;&#31561;&#12398;&#23455;&#20307;&#21442;&#29031;&#12420;&amp;#12345;&#12392;&#12356;&#12387;&#12383;&#25968;&#20516;&#25991;&#23383;&#21442;&#29031;&#12434;&#36890;&#24120;&#12398;&#25991;&#23383;&#12395;&#22793;&#25563;&#12375;&#12414;&#12377;&#12290;" as Unicode text

--my_stringsの文字列を{"a","b","c","&amp;","&#12345;"}のようなリストに分解
set chr_list to {}
set chrRef to "" as Unicode text
set flg to false
repeat with cnt from 1 to (count of my_strings)
    set chr to item cnt of my_strings
    if chr is "&" and (item (cnt + 1) of my_strings is not "&") and flg is false then
        set flg to true
        set chrRef to chr
    else
        if flg is true then
            if chr is ";" then
                set end of chr_list to chrRef & ";"
                set flg to false
                set chrRef to ""
            else
                set chrRef to chrRef & chr
            end if
        else
            set end of chr_list to chr
        end if
    end if
end repeat

--リストの要素を1つずつ変換してmy_textに追加していく。変換出来ないものはそのまま文字として追加
set my_text to "" as Unicode text
repeat with chr in chr_list
    set returned_chr to my decodeCharacterReferences(chr)
    if not returned_chr is false then set chr to returned_chr
    set my_text to my_text & chr
end repeat

display dialog my_text


(*
    実体参照および数値文字参照を『1文字ずつ』変換
    &#および;を付けたまま引数として渡す
    文字コードは16bit以下 10進表記限定(&#01234;の表記)
    XMLの仕様で定義されている 「&amp;」 , 「&lt;」 , 「&gt;」 , 「&quot;」 , 「&apos;」 を変換出来る事は確認
*)
on decodeCharacterReferences(chrRef)
    if chrRef starts with "&#" and item -1 of chrRef is ";" then
        set chrRef to (items 3 thru ((count of chrRef) - 1) of chrRef)
        try
            set scpt to "python -c 'print unichr(eval(\"" & chrRef & "\")).encode(\"utf-8\")' "
            return do shell script scpt
        on error
            return false
        end try
    else if chrRef starts with "&" and item -1 of chrRef is ";" then
        if chrRef is "&apos;" then return "'" --&apos;はhtmlentitydefsモジュールのname2codepointに定義されてない?
        set chrRef to (items 2 thru ((count of chrRef) - 1) of chrRef)
        try
            set scpt to "python -c 'import htmlentitydefs; print unicode(\"" & bslashChr & bslashChr & "u%04x\" % htmlentitydefs.name2codepoint[\"" & chrRef & "\"],\"Unicode-Escape\").encode(\"utf-8\")'"
            return do shell script scpt
        on error
            return false
        end try
    end if
    return false
end decodeCharacterReferences

Photoshopで画像のサムネイルを作成し一覧のHTMLを書き出すAppleScript

ドロップしたフォルダの中にある画像ファイルのサムネイルをPhotoshopを使って作成し、それを一覧表示するHTMLを生成してファイルに書き出すAppleScript。

生成されたHTMLをブラウザで表示するとこんな感じになります。


サムネイルの生成には、Photoshopを使う以外にもOS Xに付属のImageEvents(sips)やFinkでインストールしたImageMagickも試して見たんですが、ImageEvents(sips)はEPSが扱えないのでダメだったり(pstopdfコマンドで一旦PDFに変換する方法もありますが時間が掛かりすぎるので却下)、ImageMagickはサイズの大きい画像を処理する時やたら時間が掛かったりエラーで落ちてしまったりで、結局Photoshopでやるのが無難でした。EPSを処理する場合はImageMagickの方が速かったような気がします。

なんでこれを作ったかと言うと、ウチの職場ではDVDに画像をバックアップしたあとAppleScriptを使ってWebベースのアプリに注番やら品名を登録してるんですが、どうせなら画像の一覧が見れた方が良いなと思い、サムネイルを作成する部分を作ってみたわけです。で、生成したHTMLをWebアプリに登録する注番にリンクしたり、サーバにアップロードする処理も付け加えていこうかなと。まあやってみたかっただけなんですけど。

■使い方
サムネイルのフォルダとHTMLを保存するディレクトリの部分と、(* サムネイルの生成 *)部分の使用するPhotoshopのバージョンを適宜書き換え、アプリケーションとして保存し、画像が入ったフォルダをドロップします。
ドロップしたフォルダ単位でHTMLが生成されます。(スクリプト中ではドロップされたフォルダを"Job"として扱ってます)

■動作確認
MacOSX10.4.11 & PhotoshopCS3
MacOSX10.3.9 & PhotoshopCS2
--作業用ディレクトリのパス。※要書き換え※
property work_dir : "Macintosh HD:Users:USERNAME:Desktop:Works"

--サムネイルの長辺のピクセル数
property thumb_size : 120

property html_top : "<html>
<head>
<meta http-equiv=\"Content-Type\" content=\"text/html; charset=x-sjis\">
<style type=\"text/css\">
body { background: #ccc; margin-top: 30px; }
#container { width: 85%; margin-left: auto; margin-right: auto; }
table { border-collapse: collapse; color: #333; background: #fff; font-size: 0.8em; }
td { padding: 5px; text-align: center; width: 120px; border: #aaa solid 1px; }
</style>
</head>
<body><div id=\"container\">
"
property html_bottom : "
</table></div></body>
</html>"
global target_list
global job_num
on open drop
	set start_time to current date
	set html_top to html_top as text
	set html_bottom to html_bottom as text
	set job_num to 1
	tell application "Finder"
		repeat with this_job in drop
			set target_list to {}
			
			(* JobごとのHTMLファイルとサムネイルを保存するフォルダを作成 *)
			set html_filename to "thumb_" & job_num & ".html"
			set html_fileRef to (make file with properties {name:html_filename} at work_dir) as alias
			open for access html_fileRef with write permission
			set title_html to "<p style=\"{font-weight: bold; font size: 1.5em;}\">[" & name of this_job & "] : の画像一覧</p>" & return as text
			write html_top & title_html & "<table>" & return to html_fileRef
			set dest_dir to "thumb_" & job_num as Unicode text
			make new folder with properties {name:dest_dir} at work_dir
			if kind of this_job is "フォルダ" then
				set job_contents to every item of this_job
			else
				set job_contents to this_job as list
			end if
			
			(* Jobに含まれるアイテムをリストに格納*)
			repeat with theItem in job_contents
				my set_itemsToList(theItem, target_list)
			end repeat
			
			(* リスト中のファイルを処理*)
			set img_n to 1
			set col_n to 0
			repeat with theFile in target_list
				set html_tbody to "" as text
				if my is_imageFile(theFile) is true then --画像ファイルの場合のみ処理する
					set fName to name of theFile as Unicode text
					set thumb_name to "job" & job_num & "-" & img_n & ".jpg"
					set thumb_path to (work_dir & ":" & dest_dir & ":" & thumb_name)
					my create_thumb(theFile, thumb_path)
					if col_n is 0 then
						set html_tbody to html_tbody & "<tr>" & return
					else
						if col_n is 5 then
							set html_tbody to html_tbody & "</tr>" & return
							set col_n to 0
						end if
					end if
					set html_tbody to html_tbody & "<td><img src=\"" & dest_dir & "/" & thumb_name & "\">" & "<br>" & fName & "</td>" & return as text
					write html_tbody to html_fileRef
					set img_n to img_n + 1
					set col_n to col_n + 1
				end if
			end repeat
			
			(* 仕上げ *)
			repeat 5 - col_n times --列の残りのコラムを<td>で埋める
				write "<td> </td>" to html_fileRef
			end repeat
			write html_bottom to html_fileRef
			close access html_fileRef
			set job_num to job_num + 1
		end repeat
		activate me
		beep
		display dialog "終了しました。" & return & "処理時間 : " & ((current date) - start_time) & "秒"
	end tell
end open


(* サムネイルの生成 *)
on create_thumb(tgt_file, dest_file)
	tell application "Adobe Photoshop CS4"
		activate
		open tgt_file showing dialogs never
		set theDoc to current document
		tell theDoc
			if width > height then
				resize image width thumb_size as pixels resolution 72 resample method bicubic
			else
				resize image height thumb_size as pixels resolution 72 resample method bicubic
			end if
			change mode to RGB
			convert to profile "sRGB IEC61966-2.1" intent relative colorimetric with blackpoint compensation and dithering
			set save_opts to {class:JPEG save options, embed color profile:false, quality:10}
			save in file dest_file as JPEG with options save_opts appending no extension with copying
			close without saving
		end tell
	end tell
end create_thumb


(* アイテムを再帰的にリストに格納 *)
on set_itemsToList(thePath, target_list)
	tell application "Finder"
		if not kind of thePath is "フォルダ" then
			set end of target_list to thePath as alias
		else
			set theFolders to every folder of thePath
			repeat with aFolder in theFolders
				my set_itemsToList(aFolder, target_list)
			end repeat
			set theFiles to every file of thePath
			repeat with aFile in theFiles
				set end of target_list to aFile as alias
			end repeat
		end if
	end tell
end set_itemsToList


(* 画像かどうかを判別 *)
on is_imageFile(theFile)
	tell application "Finder"
		set fPath to POSIX path of theFile as Unicode text
		if kind of theFile is "Adobe Photoshop ファイル" or kind of theFile is "Adobe Photoshop EPS ファイル" then
			return true
		else
			try
				set fType to 2nd word of (do shell script "sips -g all " & quoted form of fPath & " | grep format")
				if fType is "psd" or fType is "tiff" or fType is "jpeg" or fType is "gif" or fType is "png" then return true
			on error
				return false
			end try
		end if
		return false
	end tell
end is_imageFile

ドラッグ&ドロップでFC2ブログに画像をアップロードするAppleScriptその3

■追記
このエントリのスクリプトは、FC2Blogがリニューアルで仕様変更されたため動作しなくなっています。
リニューアル後のFC2Blogに対応した改良版は、下記のエントリで公開しています。
ドラッグ&ドロップでFC2ブログに複数の画像をまとめてアップロードするAppleScript その4
■追記ここまで


以前書いた、ドラッグ&ドロップでFC2ブログのサーバに画像をまとめてアップロードするAppleScriptですが、思いのほか反響があったのでちょっとだけ書き直しました。

変更点として
・以前のスクリプトではパスワード入力ミスなどでログインに失敗しても単に何も起こらないだけだったのを、今回はエラーメッセージを表示するようにした
・アップロード中は『くるくる』が表示されてアップロード処理中だとわかるようにした
・サーバから受け取ったCookieを、ホームディレクトリ下の 『ライブラリ/Cookies/fc2uploader_cookie.txt』として保存するようにした

使い方
・まずこのスクリプトをスクリプトエディタにコピペして、最初の行の<管理画面のURL>と、その下の<ユーザ名>の部分を書き換える
・そのスクリプトを『アプリケーション』として保存
・保存したスクリプトのアイコンに、アップロードしたい画像をまとめてドラッグ&ドロップ
・パスワードを聞いてくるので入力
・しばらく待つ
・『終了しました』のダイアログが表示されれば完了

FC2ブログにアップロード出来ない種類のファイル(.psdや.xlsなど)をアップロードしようとしても、エラーなどは表示されず、ただ何もアップロードされずに終了します。FC2ブログの管理画面の作りに依存してるので、リニューアルなどで変更されてしまうと動かなくなってしまうため、最低限の機能だけにしました。一応、以前作った『多機能版』もありますが。

property myURL : "<管理画面のURL>"
--"<ブログのURL>/admin.php"を入れる

property myID : "<ユーザ名>"
--FC2ブログのユーザ名を入れる

property msg1 : "管理画面のパスワードを入力" as Unicode text
property msg2 : "終了しました。" as Unicode text
property msg3 : "ログインに失敗しました。" as Unicode text
property cookiePath : " ~/Library/Cookies/fc2uploader_cookie.txt" ----保存するcookieのパス

on open drop
    activate me
    set myPass to text returned of (display dialog msg1 default answer "")
    
    ----ログイン処理&Cookie保存
    set loginScript to "curl -d \"id=" & myID & "&pass=" & myPass & "&mode=admin\" -c " & cookiePath & " -L " & myURL & " | tail -n 100"
    set response_login to do shell script loginScript as string
    
    ----パスワードの入力フォームがレスポンスに含まれていた場合、ログイン失敗と判定
    if response_login contains "input type=\"password\"" then
        beep
        display dialog msg3 with icon 0 buttons "OK" default button 1
        error number -128
    end if
    
    ----メインループ
    repeat with theFile in drop
        tell application "Finder"
            set fPath to POSIX path of theFile as Unicode text
            set uploadScript to "curl -b " & cookiePath & " -F \"upfile=@" & fPath & "\" -F  mode=upload -L " & myURL
            do shell script uploadScript
        end tell
    end repeat
    beep
    display dialog msg2 default button 1 buttons "OK"
end open

PhotoshopCS2用AppleScriptドロップレット小ネタ2つ

仕事で入り用だったので書いたやつ。

『RGB画像にラベルを付ける』
そのまんま。sipsがEPSに対応しててくれればわざわざPhotoshopで開かなくても良いんだけど。
■6/25修整■
on open drop
    repeat with theFile in drop
        tell application "Adobe Photoshop CS2"
            open theFile
            set theDoc to current document
            if mode of theDoc is RGB then
                tell application "Finder"
                    set label index of theFile to 2
                end tell
            end if
            close theDoc
        end tell
    end repeat
    activate me
    beep
    display dialog "Finished."
end open


『レイヤもしくはアルファチャンネルのある画像をフォルダにまとめる』
ドロップした画像にレイヤもしくはアルファチャンネルがあれば、画像と同じフォルダ内の『has layers & alpha channels』の中にまとまります。
on open drop
    repeat with theFile in drop
        
        tell application "Finder"
            if (kind of theFile is "Adobe Photoshop ファイル") or (name of theFile contains ".psd") then
                set fPath to parent of theFile
            
                if not (exists folder "has layers & alpha channels" of fPath) then
                    make folder with properties {name:"has layers & alpha channels"} at fPath
                end if
            
                tell application "Adobe Photoshop CS2"
                    open theFile
                    set theDoc to current document
                    set docMode to mode of theDoc
                    if docMode is CMYK then
                        set cNum to 4
                    else if docMode is RGB then
                        set cNum to 3
                    else
                        set cNum to 0
                    end if
                    set numLayer to (count of art layers of theDoc) as string
                    set numAlpha to (count of channels of theDoc) as string
                    close theDoc
                end tell
            
                if (numLayer > 1) or ((numAlpha > cNum) and (cNum is not 0)) then
                    move theFile to folder "has layers & alpha channels" of fPath
                end if
            end if
        end tell
    end repeat
    activate me
    beep
    display dialog "Finished."
end open
Profile
choco
Author : choco

印刷・製版の現場を経て、広告制作会社でPhotoshopを使ったビジュアル制作を担当。

→現在は車載機器開発ベンダにて、組み込み3Dデータ作成やUIデザインなどを行っています。

Categories
Favorites


Search
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。