NOTE: swiftformatについてのメモその3

支援スクリプトにはバグの原因がわからないのでエラー処理を入れて致命的な被害は回避するようにした。

フォーマットして文字列の長さが0ならばエラー扱いにした。

ソースコードは以下の通り。

#!/usr/bin/osascript

use framework "Foundation"
use framework "AppKit"
use scripting additions

-- 定数定義したい
property NSString : a reference to current application's NSString
property NSPasteboard : a reference to current application's NSPasteboard
property NSPasteboardTypeString : a reference to current application's NSPasteboardTypeString

tell application "Xcode"

    activate
  -- エラー処理 1個もドキュメントがない
  if (count of documents) is 0 then
    display notification "ファイルが指定されてないです"
    beep
    return
  end if


  -- ドキュメントファイルへのパスを取得したい
  -- 方法は現在XCodeで最も前面に出ているWindowのタイトルを取得し、そのタイトル名から
  -- ドキュメントを特定し、特定したドキュメントからファイルパスを取得する
  -- AppleScriptの文字列とNSStringを行ったり来たりしてるのは単純に私のAppleScriptの技術不足

  -- 最前面のwidnowを取得
  set mainWindow to window 1

  -- 最前面のWindowのタイトルを取得
  set mainWindowTitle to mainWindow's name

  -- Windowのタイトル文字列を区切り文字列で分解する。NSStringに変換して便利なメソッドを使う
  set theWindowTitle to NSString's stringWithString:mainWindowTitle
  set theWordList to theWindowTitle's componentsSeparatedByString:" — "


  -- 末尾がEditedの場合は編集中なので後ろから2番目がドキュメント名と仮定する
  -- それ以外は末尾がドキュメント名と仮定する
  if ((item -1 of theWordList) as string is "Edited") then
    set theDocumentName to (item -2 of theWordList) as string
  else
    set theDocumentName to (item -1 of theWordList) as string
  end if


  -- 名前が一致するdocumentを探し出す
  set theCurrentDocument to document 1 whose name ends with theDocumentName

  -- エラー処理
  if theCurrentDocument is -1 then
    display notification "そんなドキュメントはないです"
    beep
    return
  end if


  -- ファイルパスを取り出す
  set theCurrentDocumentPath to path of theCurrentDocument

  -- エラー処理
  if theCurrentDocumentPath is "" then
    display notification "ファイルに結び付けられていないDocumentです"
    beep
    return
  end if

  -- 拡張子とファイルがあるディレクトリへのパスを取り出す
  set theFilePathString to NSString's stringWithString:theCurrentDocumentPath
  set theExtension to theFilePathString's pathExtension as string
  set theDirectoryPath to theFilePathString's stringByDeletingLastPathComponent as string
  set theFileNameString to theFilePathString's lastPathComponent as string

  -- エラー処理
  if theExtension is not "swift" then
    display notification "拡張子がswiftではないです"
    beep
    return
  end if


  -- 既存のペーストボードデータを破壊しないようにデータの保存
  set savedClipboard to the clipboard

  set thePasteboard to NSPasteboard's generalPasteboard()
  thePasteboard's clearContents()
  thePasteboard's setString:(theCurrentDocument's text) forType:NSPasteboardTypeString

  -- unix shell スクリプトを使うのはcurrent directoryの設定ファイルを使わせるため
  -- 標準入出力を使うだけだと設定ファイルを無視するのでstdinpathでファイル名を渡してます
  set theOutput to do shell script "cd " & theDirectoryPath & "; pbpaste -Prefer txt | /opt/homebrew/bin/swiftformat stdin --stdinpath " & theFileNameString & " | pbcopy"

    -- エラー処理
  set thePBString to thePasteboard's stringForType:(NSPasteboardTypeString)
  if thePBString as string is "" then
    display notification "うまく変換できなかったです"
    beep
    -- 既存のペーストボードデータを破壊しないようにデータの復帰
    set the clipboard to savedClipboard
    return
  end if

  -- キーコマンドは送信しているが動作が安定しない
  tell application "System Events"
    tell process "Xcode"
      keystroke "a" using command down -- select all
      keystroke "v" using {command down, option down, shift down} -- cmd opt shift paste スタイルを維持してペースト
      delay 0.5 -- clipbardの内容を同期させるに必要らしい
    end tell
  end tell

  -- 既存のペーストボードデータを破壊しないようにデータの復帰
  set the clipboard to savedClipboard

end tell

Comments

comments powered by Disqus