Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

タグ: 10.11savvy

指定フォルダ内のJPEGファイルのEXIFから撮影日付を取得してファイルの作成日付に反映させる v2

Posted on 5月 31, 2018 by Takaaki Naganoya

指定フォルダ内のすべてのJPEGファイルのEXIF情報から撮影日付を取得し、画像ファイルの作成日付に反映させるAppleScriptです。

写真.app(Photos.app)内で管理している大量の写真ファイルをいったんファイルに書き出して、DVD-Rにコピーして人に渡すときに、写真の作成日付が撮影日になっておらず、Finderなどのファイラー上で整理するのが大変でした。

ファイル書き出しなので仕方のないことですが、この仕様はいただけません。

かようにファイル作成日付が正しくない写真でも、EXIFに正しい撮影日付が保存されているケースが多い(ただし、完全にすべてではない)ため、EXIFの日付をAppleScriptで読み取ってファイル作成日付に反映させてみました。

写真.appなどのアプリケーションにインポートしてしまえばEXIF日付でソートされるので、あまり意味があるとも思えませんが、Finder上での写真整理のために実行してとりあえず走らせてみました。

AppleScript名:EXIFから撮影日付を取得してファイルの作成日付に反映させる v2
— Created 2018-05-30 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

script spd
  property fList : {}
end script

set renCount to 0

set (fList of spd) to {}

set aFolder to (choose folder)

set aDate to current date

set (fList of spd) to getFilePathList(aFolder, "JPG") of me

repeat with i in (fList of spd)
  set j to contents of i
  
chkCreationDateAsExif(j) of me
  
set renCount to renCount + 1
end repeat

set bDate to current date

return {bDate – aDate, renCount}

on chkCreationDateAsExif(aFile)
  tell application "Image Events"
    launch
    
set this_image to open (aFile as alias)
    
    
try
      tell this_image
        set aVal to (value of metadata tag "creation")
      end tell
    on error
      return
    end try
    
    
close this_image
  end tell
  
  
set a to current application’s NSString’s stringWithString:aVal
  
set {aDateStr, aTimeStr} to (a’s componentsSeparatedByString:" ") as list
  
set bDateStr to repChar(aDateStr, ":", "/") of me
  
set fullDate to date (bDateStr & " " & aTimeStr)
  
  
set aDic to current application’s NSMutableDictionary’s dictionaryWithObject:fullDate forKey:(current application’s NSFileModificationDate)
  
set aFM to current application’s NSFileManager’s defaultManager()’s setAttributes:aDic ofItemAtPath:(POSIX path of aFile) |error|:(missing value)
end chkCreationDateAsExif

–文字置換
on repChar(origText as string, targChar as string, repChar as string)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to targChar
  
set tmpList to text items of origText
  
set AppleScript’s text item delimiters to repChar
  
set retText to tmpList as string
  
set AppleScript’s text item delimiters to curDelim
  
return retText
end repChar

on getFilePathList(aFol, aExt)
  set aFol to current application’s |NSURL|’s fileURLWithPath:(POSIX path of aFol)
  
  
set aFM to current application’s NSFileManager’s defaultManager()
  
set urlArray to aFM’s contentsOfDirectoryAtURL:aFol includingPropertiesForKeys:{} options:(current application’s NSDirectoryEnumerationSkipsHiddenFiles) |error|:(missing value)
  
set thePred to current application’s NSPredicate’s predicateWithFormat:"pathExtension == [c]%@" argumentArray:{aExt}
  
set anArray to urlArray’s filteredArrayUsingPredicate:thePred
  
return anArray as list — URLs pre-10.11, files under 10.11
end getFilePathList

★Click Here to Open This Script 

Posted in exif file Image | Tagged 10.11savvy 10.12savvy 10.13savvy Image Events | Leave a comment

Finderファイルタグの設定や取得

Posted on 5月 29, 2018 by Takaaki Naganoya

指定ファイルのFinderタグを取得/設定/追加を行うAppleScriptです。

もともとはShane Stanleyが数年前に書いたScriptですが、Cocoaっぽいハンドラ記述だと慣れていないScripterには敷居が高いので、OLD Style AppleScript風のハンドラに書き換えたものです。

AppleScript名:Finderファイルタグの設定や取得
–Created By Shane Stanley
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property |NSURL| : a reference to current application’s |NSURL|
property NSOrderedSet : a reference to current application’s NSOrderedSet
property NSURLTagNamesKey : a reference to current application’s NSURLTagNamesKey

set anAlias to (choose file)
set aRes to getTagsForPath(anAlias) of me

— get the tags
on getTagsForPath(anAlias)
  set aURL to |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
  
set {theResult, theTags} to aURL’s getResourceValue:(reference) forKey:(NSURLTagNamesKey) |error|:(missing value)
  
if theTags = missing value then return {} — because when there are none, it returns missing value
  
return theTags as list
end getTagsForPath

— set the tags, replacing any existing
on setTagsForPath(tagList, anAlias)
  set aURL to |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
  
aURL’s setResourceValue:tagList forKey:(NSURLTagNamesKey) |error|:(missing value)
end setTagsForPath

— add to existing tags
on addTagsForPath(tagList, anAlias)
  set aURL to |NSURL|’s fileURLWithPath:(POSIX path of anAlias)
  
— get existing tags
  
set {theResult, theTags} to aURL’s getResourceValue:(reference) forKey:(NSURLTagNamesKey) |error|:(missing value)
  
if theTags ≠ missing value then — add new tags
    set tagList to (theTags as list) & tagList
    
set tagList to (NSOrderedSet’s orderedSetWithArray:tagList)’s allObjects() — delete any duplicates
  end if
  
aURL’s setResourceValue:tagList forKey:(NSURLTagNamesKey) |error|:(missing value)
end addTagsForPath

★Click Here to Open This Script 

Posted in file Tag | Tagged 10.11savvy 10.12savvy 10.13savvy Finder | Leave a comment

各TTSの名前とバージョン情報を取得

Posted on 5月 28, 2018 by Takaaki Naganoya

OSにインストールされている各TTS(Text To Speech)の名称一覧とバージョン情報を取得するAppleScriptです。

AppleScriptのsayコマンドには音声を指定する機能が用意されていますが、その一方でOSにインストールされているTTS音声の一覧を取得する機能がないため、このようにしてTTS音声名称を取得したり、対応言語(英語とか日本語とか)でしぼりこみを行なって指定言語のテキスト読み上げに必要なTTS音声が存在しているかといった判定を行います。

各TTS Voiceには、

{​​​​​​​VoiceName:”Vicki”, ​​​​​​​VoiceLocaleIdentifier:”en_US”, ​​​​​​​VoiceIndividuallySpokenCharacters:{{….}}, VoiceDemoText:”Isn’t it nice to have a computer that will talk to you?”, ​​​​​​​VoiceSupportedCharacters:{​​​​​​​​​{…}}, VoiceShowInFullListOnly:1, ​​​​​​​VoiceGender:”VoiceGenderFemale”, ​​​​​​​VoiceVersion:”3.6″, ​​​​​​​VoiceAge:35, ​​​​​​​VoiceIdentifier:”com.apple.speech.synthesis.voice.Vicki”, ​​​​​​​VoiceRelativeDesirability:5100, ​​​​​​​VoiceLanguage:”en-US”​​​​​}

のような属性情報があり、このVoiceNameとVoiceVersionを求めています。

Japanese TTS VoiceのOtoya v6.3.1とKyoko v6.3.1でも、あいかわらず「捥げる」「もげる」を正しく読み上げられない(「げる」、「もげ」になる)バグは治っていません(これを確認するのが本Scriptの目的です)。

AppleScript名:各TTSの名前とバージョン情報を取得
— Created 2015-08-25 by Takaaki Naganoya
— Modified 2015-08-26 by Shane Stanley, Takaaki Naganoya
— 2015 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

set v1Res to getVoiceNamesAndVers()
–>  {{"Agnes", "3.6"}, {"Albert", "3.6"}, {"Alex", "2.0.36"}, {"Alice", "6.1.1"}, {"Allison", "6.3.1"}, {"Alva", "6.1.1"}, {"Amelie", "6.1.1"}, {"Anna", "6.3.1"}, {"Audrey", "6.3.1"}, {"Ava", "6.3.1"}, {"Bad News", "3.6"}, {"Bahh", "3.6"}, {"Bells", "3.6"}, {"Boing", "3.6"}, {"Bruce", "3.6"}, {"Bubbles", "3.6"}, {"Carmit", "6.1.1"}, {"Cellos", "3.6"}, {"Damayanti", "6.1.1"}, {"Daniel", "6.3.1"}, {"Deranged", "3.6"}, {"Diego", "6.1.1"}, {"Ellen", "6.1.1"}, {"Emily", "2.0.3"}, {"Fiona", "6.1.1"}, {"Fred", "3.6"}, {"Good News", "3.6"}, {"Hysterical", "3.6"}, {"Ioana", "6.1.1"}, {"Jill", "2.0.3"}, {"Joana", "6.1.1"}, {"Jorge", "6.1.1"}, {"Juan", "6.1.1"}, {"Junior", "3.6"}, {"Kanya", "6.1.1"}, {"Karen", "6.3.1"}, {"Kate", "6.3.1"}, {"Kathy", "3.6"}, {"Kyoko", "6.3.1"}, {"Laura", "6.1.1"}, {"Lee", "6.3.1"}, {"Lekha", "6.1.1"}, {"Luca", "6.1.1"}, {"Luciana", "6.1.1"}, {"Maged", "6.1.1"}, {"Mariska", "6.1.1"}, {"Mei-Jia", "6.1.1"}, {"Melina", "6.1.1"}, {"Milena", "6.1.1"}, {"Moira", "6.1.1"}, {"Monica", "6.1.1"}, {"Nora", "6.1.1"}, {"Otoya", "6.3.1"}, {"Paulina", "6.1.1"}, {"Pipe Organ", "3.6"}, {"Princess", "3.6"}, {"Ralph", "3.6"}, {"Samantha", "6.3.1"}, {"Sara", "6.1.1"}, {"Satu", "6.1.1"}, {"Serena", "6.3.1"}, {"Sin-ji", "6.1.1"}, {"Tessa", "6.1.1"}, {"Thomas", "6.1.1"}, {"Ting-Ting", "6.3.1"}, {"Tom", "6.3.1"}, {"Trinoids", "3.6"}, {"Veena", "6.1.1"}, {"Vicki", "3.6"}, {"Victoria", "3.6"}, {"Whisper", "3.6"}, {"Xander", "6.1.1"}, {"Yelda", "6.1.1"}, {"Yuna", "6.3.1"}, {"Yuri", "6.1.1"}, {"Zarvox", "3.6"}, {"Zosia", "6.1.1"}, {"Zuzana", "6.1.1"}}

–Get TTS Voice names and versions
on getVoiceNamesAndVers()
  set aList to {}
  
  
set nameList to (current application’s NSSpeechSynthesizer’s availableVoices()) as list
  
repeat with i in nameList
    set j to contents of i
    
set aDic to ((current application’s NSSpeechSynthesizer’s attributesForVoice:j))
    
set aName to (aDic’s VoiceName) as string
    
set aVer to (aDic’s VoiceVersion) as string
    
set the end of aList to {aName, aVer}
  end repeat
  
  
return aList as list
end getVoiceNamesAndVers

★Click Here to Open This Script 

Posted in list System | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

現在のスライド上のshapeオブジェクトのうち一番上のものに他のものの幅をそろえる

Posted on 5月 27, 2018 by Takaaki Naganoya

Keynoteの現在のスライド上のshapeオブジェクトのうち、一番上のものに他のものの幅をそろえるAppleScriptです。

いっそ、Shapeオブジェクトのboundsをすべて取得して、横長か縦長かを計算し、自動で基準オブジェクトを上にするか左のものにするかを判定してもよいのですが、少しやりすぎな感じもするので、現状のままにしてあります。

AppleScript名:現在のスライド上のshapeオブジェクトのうち一番上のものに他のものの幅をそろえる
— Created 2018-05-25 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

tell application "Keynote"
  tell front document
    tell (current slide)
      — すべてのshapeオブジェクトの座標{x,y}を返す
      
set pList to position of every shape
      
      
— shapeオブジェクトの全座標を昇順ソートして最もX座標値が小さいものを返す
      
set mostLeftPos to first item of sort2DList(pList) of me
      
      
— 一番X座標値が小さい(=左にある)オブジェクトを特定
      
set mostLeftObj to first item of (every shape whose position is equal to mostLeftPos)
      
set mostLeftProp to properties of mostLeftObj
      
–> (*class:shape, opacity:100, parent:slide 5 of document id 253165F1-0596-4E72-B9E3-2AB6D6084125, reflection showing:false, background fill type:color fill, position:32, 160, object text:, width:56, rotation:0, reflection value:0, height:467, locked:false*)
      
      
set mostLeftHeight to height of mostLeftProp
      
set mostLeftWidth to width of mostLeftProp
      
      
— 「一番左」以外のshapeオブジェクトへの参照を取得して一気にオブジェクトのwidthをそろえる
      
set otherShape to a reference to (every shape whose position is not equal to mostLeftPos)
      
set width of otherShape to mostLeftWidth
    end tell
  end tell
end tell

on sort2DList(aList)
  load framework
  
set sortIndexes to {1} –Key Item id: begin from 0
  
set sortOrders to {true} –ascending = true
  
set sortTypes to {"compare:"}
  
set resList to (current application’s SMSForder’s subarraysIn:(aList) sortedByIndexes:sortIndexes ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list
  
return resList
end sort2DList

★Click Here to Open This Script 

Posted in Sort | Tagged 10.11savvy 10.12savvy 10.13savvy Keynote | Leave a comment

Finderで選択中のPDFを古い順に連結する v2

Posted on 5月 27, 2018 by Takaaki Naganoya

Finder上で選択中のファイルのうちPDFだけを作成日付で古い順に連結するAppleScriptです。

間違ってPDF以外のファイルを選択してしまった場合でも、それについては無視します。

こんな風にmacOS標準装備のScript Menuに入れて利用しています。

AppleScript名:Finderで選択中のPDFを古い順に連結する v2
— Created 2018-05-26 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "Quartz"

property |NSURL| : a reference to current application’s |NSURL|
property NSArray : a reference to current application’s NSArray
property NSPredicate : a reference to current application’s NSPredicate
property NSFileManager : a reference to current application’s NSFileManager
property NSURLPathKey : a reference to current application’s NSURLPathKey
property NSMutableArray : a reference to current application’s NSMutableArray
property NSSortDescriptor : a reference to current application’s NSSortDescriptor
property NSURLIsPackageKey : a reference to current application’s NSURLIsPackageKey
property NSURLIsDirectoryKey : a reference to current application’s NSURLIsDirectoryKey
property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey
property NSURLContentModificationDateKey : a reference to current application’s NSURLContentModificationDateKey
property NSDirectoryEnumerationSkipsHiddenFiles : a reference to current application’s NSDirectoryEnumerationSkipsHiddenFiles

–set inFiles to (choose file of type {"pdf"} with prompt "Choose your PDF files:" with multiple selections allowed)
tell application "Finder"
  set inFiles to selection as alias list
end tell

if inFiles = {} then return

–指定のAlias listのうちPDFのみ抽出
set filRes1 to filterAliasListByUTI(inFiles, "com.adobe.pdf") of me

–選択中のファイルのうちの1つから親フォルダを求め、出力先ファイルパスを組み立てる
set outPathTarg to POSIX path of (first item of filRes1)
set pathString to current application’s NSString’s stringWithString:outPathTarg
set newPath to (pathString’s stringByDeletingLastPathComponent()) as string
set destPosixPath to newPath & "/" & ((current application’s NSUUID’s UUID()’s UUIDString()) as string) & ".pdf"

combinePDFsAndSaveIt(filRes1, destPosixPath) of me

on combinePDFsAndSaveIt(inFiles, destPosixPath)
  set inFilesSorted to my filesInListSortFromOldToNew(inFiles)
  
  
— make URL of the first PDF
  
set inNSURL to current application’s |NSURL|’s fileURLWithPath:(POSIX path of item 1 of inFilesSorted)
  
set theDoc to current application’s PDFDocument’s alloc()’s initWithURL:inNSURL
  
  
— loop through the rest
  
set oldDocCount to theDoc’s pageCount()
  
set inFilesSorted to rest of inFilesSorted
  
  
repeat with aFile in inFilesSorted
    set inNSURL to (current application’s |NSURL|’s fileURLWithPath:(POSIX path of aFile))
    
set newDoc to (current application’s PDFDocument’s alloc()’s initWithURL:inNSURL)
    
    
set newDocCount to newDoc’s pageCount()
    
repeat with i from 1 to newDocCount
      set thePDFPage to (newDoc’s pageAtIndex:(i – 1)) — zero-based indexes
      (
theDoc’s insertPage:thePDFPage atIndex:oldDocCount)
      
set oldDocCount to oldDocCount + 1
    end repeat
    
  end repeat
  
  
set outNSURL to current application’s |NSURL|’s fileURLWithPath:destPosixPath
  (
theDoc’s writeToURL:outNSURL)
end combinePDFsAndSaveIt

on filesInListSortFromOldToNew(aliasList)
  set keysToRequest to {NSURLPathKey, NSURLIsPackageKey, NSURLIsDirectoryKey, NSURLContentModificationDateKey}
  
  
set valuesNSArray to NSMutableArray’s array()
  
repeat with i in aliasList
    set oneNSURL to (|NSURL|’s fileURLWithPath:(POSIX path of i))
    (
valuesNSArray’s addObject:(oneNSURL’s resourceValuesForKeys:keysToRequest |error|:(missing value)))
  end repeat
  
  
set theNSPredicate to NSPredicate’s predicateWithFormat_("%K == NO OR %K == YES", NSURLIsDirectoryKey, NSURLIsPackageKey)
  
set valuesNSArray to valuesNSArray’s filteredArrayUsingPredicate:theNSPredicate
  
  
set theDescriptor to NSSortDescriptor’s sortDescriptorWithKey:(NSURLContentModificationDateKey) ascending:true
  
set theSortedNSArray to valuesNSArray’s sortedArrayUsingDescriptors:{theDescriptor}
  
  
— extract just the paths and convert to an AppleScript list
  
return (theSortedNSArray’s valueForKey:(NSURLPathKey)) as list
end filesInListSortFromOldToNew

–Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す
on filterAliasListByUTI(aList, targUTI)
  set newList to {}
  
repeat with i in aList
    set j to POSIX path of i
    
set tmpUTI to my retUTIfromPath(j)
    
set utiRes to my filterUTIList({tmpUTI}, targUTI)
    
if utiRes is not equal to {} then
      set the end of newList to j
    end if
  end repeat
  
return newList
end filterAliasListByUTI

–指定のPOSIX pathのファイルのUTIを求める
on retUTIfromPath(aPOSIXPath)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath
  
set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value)
  
  
if theResult = true then
    return theValue as string
  else
    return theResult
  end if
end retUTIfromPath

–UTIリストが指定UTIに含まれているかどうか演算を行う
on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

★Click Here to Open This Script 

Posted in file PDF Sort UTI | Tagged 10.11savvy 10.12savvy 10.13savvy Finder | Leave a comment

Finderで選択中のファイルのうち、指定UTIに含まれるものを返す

Posted on 5月 26, 2018 by Takaaki Naganoya

Finder上で選択中のファイルのうち、指定UTIに含まれるもの(下位階層のUTIも含む)を返すAppleScriptです。

Finderでfileのkindを指定してフィルタ参照でしぼりこむ方法もありますが、ファイル数が増えると処理速度が大幅に低下するのと、UTIで指定できたほうが便利なので作っておきました。

AppleScript名:Finderで選択中のファイルのうち、指定UTIに含まれるものを返す
— Created 2018-05-26 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property NSURLTypeIdentifierKey : a reference to current application’s NSURLTypeIdentifierKey
property |NSURL| : a reference to current application’s |NSURL|
property NSPredicate : a reference to current application’s NSPredicate
property NSArray : a reference to current application’s NSArray

tell application "Finder"
  set aSel to selection as alias list
end tell
if aSel = {} then its return

set filRes1 to filterAliasListByUTI(aSel, "com.adobe.pdf") of me
–>  {​​​​​"/Users/me/Pictures/annotation_origin.pdf"​​​}

set filRes2 to filterAliasListByUTI(aSel, "public.image") of me
–>  {"/Users/me/Pictures/スクリーンショット 2017-11-06 20.05.30.png", "/Users/me/Pictures/スクリーンショット 2017-09-27 19.35.08.png", "/Users/me/Pictures/スクリーンショット 2017-09-27 19.33.53.png", "/Users/me/Pictures/スクリーンショット 2017-09-26 16.46.29.png"}

set filRes3 to filterAliasListByUTI(aSel, "public.item") of me
–>  {"/Users/me/Pictures/スクリーンショット 2017-11-06 20.05.30.png", "/Users/me/Pictures/annotation_origin.pdf", "/Users/me/Pictures/スクリーンショット 2017-09-27 19.35.08.png", "/Users/me/Pictures/スクリーンショット 2017-09-27 19.33.53.png", "/Users/me/Pictures/スクリーンショット 2017-09-26 16.46.29.png"}

–Alias listから指定UTIに含まれるものをPOSIX pathのリストで返す
on filterAliasListByUTI(aList, targUTI)
  set newList to {}
  
repeat with i in aList
    set j to POSIX path of i
    
set tmpUTI to my retUTIfromPath(j)
    
set utiRes to my filterUTIList({tmpUTI}, targUTI)
    
if utiRes is not equal to {} then
      set the end of newList to j
    end if
  end repeat
  
return newList
end filterAliasListByUTI

–指定のPOSIX pathのファイルのUTIを求める
on retUTIfromPath(aPOSIXPath)
  set aURL to |NSURL|’s fileURLWithPath:aPOSIXPath
  
set {theResult, theValue} to aURL’s getResourceValue:(reference) forKey:NSURLTypeIdentifierKey |error|:(missing value)
  
  
if theResult = true then
    return theValue as string
  else
    return theResult
  end if
end retUTIfromPath

–UTIリストが指定UTIに含まれているかどうか演算を行う
on filterUTIList(aUTIList, aUTIstr)
  set anArray to NSArray’s arrayWithArray:aUTIList
  
set aPred to NSPredicate’s predicateWithFormat_("SELF UTI-CONFORMS-TO %@", aUTIstr)
  
set bRes to (anArray’s filteredArrayUsingPredicate:aPred) as list
  
return bRes
end filterUTIList

★Click Here to Open This Script 

Posted in file UTI | Tagged 10.11savvy 10.12savvy 10.13savvy Finder | Leave a comment

現在のスライド上のshapeオブジェクトのうち一番左のものに他のものの高さをそろえる

Posted on 5月 25, 2018 by Takaaki Naganoya

Keynoteの現在のスライド上のshapeオブジェクトのうち、一番左のものに他のものの高さをそろえるAppleScriptです。

AppleScript名:現在のスライド上のshapeオブジェクトのうち一番左のものに他のものの高さをそろえる
— Created 2018-05-25 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

tell application "Keynote"
  tell front document
    tell (current slide)
      — すべてのshapeオブジェクトの座標{x,y}を返す
      
set pList to position of every shape
      
      
— shapeオブジェクトの全座標を昇順ソートして最もX座標値が小さいものを返す
      
set mostLeftPos to first item of sort2DList(pList) of me
      
      
— 一番X座標値が小さい(=左にある)オブジェクトを特定
      
set mostLeftObj to first item of (every shape whose position is equal to mostLeftPos)
      
set mostLeftProp to properties of mostLeftObj
      
–> (*class:shape, opacity:100, parent:slide 5 of document id 253165F1-0596-4E72-B9E3-2AB6D6084125, reflection showing:false, background fill type:color fill, position:32, 160, object text:, width:56, rotation:0, reflection value:0, height:467, locked:false*)
      
      
set mostLeftHeight to height of mostLeftProp
      
set mostLeftWidth to width of mostLeftProp
      
      
— 「一番左」以外のshapeオブジェクトへの参照を取得して一気にオブジェクトのHeightをそろえる
      
set otherShape to a reference to (every shape whose position is not equal to mostLeftPos)
      
set height of otherShape to mostLeftHeight
    end tell
  end tell
end tell

on sort2DList(aList)
  load framework
  
set sortIndexes to {0} –Key Item id: begin from 0
  
set sortOrders to {true} –ascending = true
  
set sortTypes to {"compare:"}
  
set resList to (current application’s SMSForder’s subarraysIn:(aList) sortedByIndexes:sortIndexes ascending:sortOrders sortTypes:sortTypes |error|:(missing value)) as list
  
return resList
end sort2DList

★Click Here to Open This Script 

Posted in Sort | Tagged 10.11savvy 10.12savvy 10.13savvy Keynote | Leave a comment

ディスプレイを回転させる

Posted on 5月 25, 2018 by Takaaki Naganoya

指定のディスプレイを回転(表示方向を変更)させるAppleScriptです。

–> Watch Demo Movie

ディスプレイの表示方向の変更には、fb-rotateというコマンドラインツールを用いています。

fb-rotateをバンドル内に内蔵して呼び出すことが多く、AppleScript Librariesとして呼び出してもよいでしょう。

–> AppleScript Bundle file with fb-rotate


▲0°(MacBook Air 11)


▲90°(MacBook Air 11)


▲180°(MacBook Air 11)


▲270°(MacBook Air 11)

AppleScript名:ディスプレイを回転させる
— Created 2016-03-11 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

–fb-rotate
–http://modbookish.lefora.com/topic/3513246/A-Unix-Utility-to-Change-the-Primary-Display-on-OSX/#.VuIe82OFlro

–ディスプレイの情報を取得(基本情報)
getDisplayList() of me
–> {{dispID:"0x4248387", dispWidth:1920, dispHeight:1200, mainD:true}, {dispID:"0x424b104", dispWidth:1920, dispHeight:1200, mainD:false}, {dispID:"0x1b557a25", dispWidth:1920, dispHeight:1080, mainD:false}}

–メインディスプレイを回転させる
rotateMainDisplayToDegree(0) of me –いったんこれを実行すると、構成によってはメインディスプレイが他のIDのものに変わる可能性がある

–ディスプレイの詳細情報を取得
getDisplayInformation() of me
–>  {​​​​​{​​​​​​​dispID:"0x4248387", ​​​​​​​dispWidth:1920, ​​​​​​​dispHeight:1200, ​​​​​​​dispX1:0, ​​​​​​​dispY1:0, ​​​​​​​dispX2:1920, ​​​​​​​dispY2:1200, ​​​​​​​mainD:true, ​​​​​​​rotationDegree:0, ​​​​​​​cousorExists:false​​​​​}, ​​​​​{​​​​​​​dispID:"0x424b104", ​​​​​​​dispWidth:1920, ​​​​​​​dispHeight:1200, ​​​​​​​dispX1:-1920, ​​​​​​​dispY1:0, ​​​​​​​dispX2:0, ​​​​​​​dispY2:1200, ​​​​​​​mainD:false, ​​​​​​​rotationDegree:0, ​​​​​​​cousorExists:true​​​​​}, ​​​​​{​​​​​​​dispID:"0x1b557a25", ​​​​​​​dispWidth:1080, ​​​​​​​dispHeight:1920, ​​​​​​​dispX1:1920, ​​​​​​​dispY1:-362, ​​​​​​​dispX2:3000, ​​​​​​​dispY2:1558, ​​​​​​​mainD:false, ​​​​​​​rotationDegree:270, ​​​​​​​cousorExists:false​​​​​}​​​}

on getDisplayInformation()
  set aPath to POSIX path of (path to me) & "Contents/Resources/fb-rotate"
  
try
    set aRes to (do shell script (quoted form of aPath) & " -i")
  on error
    return false
  end try
  
  
set aList to paragraphs of aRes
  
set aaList to contents of (items 2 thru -2 of aList)
  
  
set a to contents of last item of aList
  
set {b, c} to separateStrByAChar(a, ":") of me
  
set {b1, c1} to separateStrByAChar(c, ",") of me
  
set mouseX to returnNumberCharsOnly(b1) as number
  
set mouseY to returnNumberCharsOnly(c1) as number
  
  
set recList to {}
  
  
repeat with i in aaList
    set j to contents of i
    
    
–Parse Result by space character
    
set aStr to (current application’s NSString’s stringWithString:j)
    
set aLine to (aStr’s componentsSeparatedByString:" ")
    (
aLine’s removeObject:"")
    
set bList to aLine as list
    
–>  {​​​​​"3", ​​​​​"0x4248387", ​​​​​"1920×1200", ​​​​​"0", ​​​​​"0", ​​​​​"-1920", ​​​​​"-1200", ​​​​​"0", ​​​​​"[main]"​​​}
    
    
–Display ID
    
set anID to contents of item 2 of bList
    
    
–Resolution
    
set aResol to contents of item 3 of bList
    
set dParseRes to separateStrByACharAndReturnNumList(aResol, "x") of me
    
if dParseRes = "" then exit repeat –Error
    
copy dParseRes to {aWidth, aHeight}
    
    
–Display_Bounds
    
set dX1 to (contents of item 4 of bList) as number
    
set dY1 to (contents of item 5 of bList) as number
    
set dX2 to (contents of item 6 of bList) as number
    
set dY2 to (contents of item 7 of bList) as number
    
    
–Rotation
    
set aDeg to (contents of item 8 of bList) as number
    
    
–Mouse Cursor Detection
    
set mouseF to (dX1 ≤ mouseX) and (mouseX ≤ dX2) and (dY1 ≤ mouseY) and (mouseY ≤ dY2)
    
    
–Main Display (Menu)
    
set aMain to contents of last item of bList
    
if (contents of last item of bList) contains "main" then
      set aMainF to true
    else
      set aMainF to false
    end if
    
    
set the end of recList to {dispID:anID, dispWidth:aWidth, dispHeight:aHeight, dispX1:dX1, dispY1:dY1, dispX2:dX2, dispY2:dY2, mainD:aMainF, rotationDegree:aDeg, cousorExists:mouseF}
  end repeat
  
  
return recList
  
end getDisplayInformation

–指定IDのディスプレイを指定角度(0, 90, 180, 270のいずれか)に回転させる
on rotateADisplayToDegree(aDispID as string, aDegree as integer)
  if aDegree is not in {0, 90, 180, 270} then return false
  
set aPath to POSIX path of (path to me) & "Contents/Resources/fb-rotate"
  
try
    set aRes to (do shell script (quoted form of aPath) & " -d " & aDispID & " -r " & (aDegree as string))
  on error
    return false
  end try
end rotateADisplayToDegree

–メインディスプレイを指定角度(0, 90, 180, 270のいずれか)に回転させる
on rotateMainDisplayToDegree(aDegree as integer)
  if aDegree is not in {0, 90, 180, 270} then return false
  
set mainID to getMainDispID() of me
  
set aPath to POSIX path of (path to me) & "Contents/Resources/fb-rotate"
  
try
    set aRes to (do shell script (quoted form of aPath) & " -d " & mainID & " -r " & (aDegree as string))
  on error
    return false
  end try
end rotateMainDisplayToDegree

–メインディスプレイのIDを取得する
on getMainDispID()
  set dList to getDisplayList() of me
  
set dDict to current application’s NSArray’s arrayWithArray:dList
  
set aRes to filterRecListByLabel1(dDict, "mainD == true") of me
  
set aMainD to contents of first item of aRes
  
set mainID to dispID of aMainD
  
return mainID
end getMainDispID

–実行中のMacに接続されているディスプレイの一覧を取得する
on getDisplayList()
  set aPath to POSIX path of (path to me) & "Contents/Resources/fb-rotate"
  
try
    set aRes to (do shell script (quoted form of aPath) & " -l")
  on error
    return false
  end try
  
set aList to paragraphs of aRes
  
set aaList to contents of (items 2 thru -1 of aList)
  
  
set recList to {}
  
  
repeat with i in aaList
    set j to contents of i
    
set bList to words of j
    
set anID to contents of item 1 of bList
    
set aResol to contents of item 2 of bList
    
set dParseRes to separateStrByACharAndReturnNumList(aResol, "x") of me
    
if dParseRes = "" then exit repeat –Error
    
copy dParseRes to {aWidth, aHeight}
    
    
set aMain to contents of last item of bList
    
if j ends with "]" then
      set aMainF to true
    else
      set aMainF to false
    end if
    
set the end of recList to {dispID:anID, dispWidth:aWidth, dispHeight:aHeight, mainD:aMainF}
  end repeat
  
  
recList
end getDisplayList

–"1920×1200" といった文字列を"x"でparseしてパラメータを分ける。結果は文字列のリストで返す
on separateStrByAChar(aStr as string, aChar as string)
  if aStr does not contain aChar then return ""
  
if length of aChar is not equal to 1 then return ""
  
if aStr = "" or (length of aStr < 3) then return ""
  
set aPos to offset of aChar in aStr
  
set partA to text 1 thru (aPos – 1) of aStr
  
set partB to text (aPos + 1) thru -1 of aStr
  
return {partA, partB}
end separateStrByAChar

–"1920×1200" といった文字列を"x"でparseしてパラメータを分ける。結果は整数のリストで返す
on separateStrByACharAndReturnNumList(aStr as string, aChar as string)
  if aStr does not contain aChar then return ""
  
if length of aChar is not equal to 1 then return ""
  
if aStr = "" or (length of aStr < 3) then return ""
  
set aPos to offset of aChar in aStr
  
set partA to (text 1 thru (aPos – 1) of aStr) as number
  
set partB to (text (aPos + 1) thru -1 of aStr) as number
  
return {partA, partB}
end separateStrByACharAndReturnNumList

–リストに入れたレコードを、指定の属性ラベルの値で抽出
on filterRecListByLabel1(aRecList as list, aPredicate as string)
  set aArray to current application’s NSArray’s arrayWithArray:aRecList
  
set aPredicate to current application’s NSPredicate’s predicateWithFormat:aPredicate
  
set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate
  
set bList to filteredArray as list
  
return bList
end filterRecListByLabel1

–数字とプラスマイナスの符号のみ返す
on returnNumberCharsOnly(aStr)
  set anNSString to current application’s NSString’s stringWithString:aStr
  
set anNSString to anNSString’s stringByReplacingOccurrencesOfString:"[^0-9-+]" withString:"" options:(current application’s NSRegularExpressionSearch) range:{0, anNSString’s |length|()}
  
return anNSString as text
end returnNumberCharsOnly

★Click Here to Open This Script 

Posted in System | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

OS X 10.11.5+Safari 9.1.1以降で、新たなAS制限機能が増える

Posted on 5月 24, 2018 by Takaaki Naganoya

macOS 10.11.5+Safari 9.1.1以降で、新たなAppleScriptの制限機能が増えました。Safariに対してdo javascriptコマンドによるコマンド実行が可能でしたが、これがデフォルト設定では禁止状態になったということです。

macOS 10.12.x系では、macOS 10.12.6+Safari 11.1にて、macOS 10.13.x系ではmacOS 10.13.5+Safari 11.1.1上にて確認しています。

■デフォルトでdo javascriptコマンドによる制御がオフに

これ以前のmacOSではデフォルトでオンになっていたので、一回オンにする作業が必要になりました(管理者パスワード必要)。

・STEP1 「開発」メニューをオンに
Safariの「環境設定」>「詳細」で、「メニューバーに”開発”メニューを表示」をオンにします。これで、Safariのメニューバーに「開発」メニューが表示されます。

・STEP2 「開発」メニューから「AppleEventからのJavaScriptを許可」「スマート検索フィールドからのJavaScriptを許可」の2つの項目をオンに(管理者パスワード必要)

AppleScript名:最前面のウィンドウのタイトルを取得する
tell application "Safari"
  set aRes to do JavaScript "document.title;" in front document
  
display dialog aRes
end tell

★Click Here to Open This Script 


▲デフォルト状態


▲「開発」メニューからJavaScriptの実行を許可した状態

Posted in JavaScript Security | Tagged 10.11savvy 10.12savvy 10.13savvy Safari | Leave a comment

Contactsに登録してある自分の写真をPNGでデスクトップに保存する

Posted on 5月 24, 2018 by Takaaki Naganoya

住所録(Contacts.app)に登録してある自分の写真をPNG形式でデスクトップに保存するAppleScriptです。

住所録情報については、Contacts.appに直接アクセスして処理することも可能ですが、ここではAddressBook.frameworkを用いた方法をご紹介します。

AppleScript名:Contactsに登録してある自分の写真をPNGでデスクトップに保存する
— Created 2016-04-02 by Takaaki Naganoya
— 2016 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AddressBook"

set imgData to current application’s ABAddressBook’s sharedAddressBook()’s |me|()’s imageData()

set aDesktopPath to (current application’s NSProcessInfo’s processInfo()’s environment()’s objectForKey:("HOME"))’s stringByAppendingString:"/Desktop/"
set savePath to aDesktopPath’s stringByAppendingString:((current application’s NSUUID’s UUID()’s UUIDString())’s stringByAppendingString:".png")

saveTIFFDataAtPathAsPNG(imgData, savePath) of me

–NSImageを指定パスにPNG形式で保存
on saveTIFFDataAtPathAsPNG(anImage, outPath)
  –set imageRep to anImage’s TIFFRepresentation()
  
set aRawimg to current application’s NSBitmapImageRep’s imageRepWithData:anImage
  
set pathString to current application’s NSString’s stringWithString:outPath
  
set newPath to pathString’s stringByExpandingTildeInPath()
  
set myNewImageData to (aRawimg’s representationUsingType:(current application’s NSPNGFileType) |properties|:(missing value))
  
set aRes to (myNewImageData’s writeToFile:newPath atomically:true) as boolean
  
return aRes –成功ならtrue、失敗ならfalseが返る
end saveTIFFDataAtPathAsPNG

★Click Here to Open This Script 

Posted in System | Tagged 10.11savvy 10.12savvy 10.13savvy Contacts | Leave a comment

指定パスの所属するドライブ名を取得する v2

Posted on 5月 22, 2018 by Takaaki Naganoya

指定パスの所属するドライブ名を取得するAppleScriptです。

ドライブ名さえ求めてしまえば、Finderに問い合わせてそれが起動ドライブ(startup = true)かどうか確認できるため、起動ドライブ以外であれば外付けディスクやファイルサーバーであるかの判定も行えます。

AppleScript名:指定パスの所属するドライブ名を取得する v2
— Created 2017-09-03 by Takaaki Naganoya
— 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

property |NSURL| : a reference to current application’s |NSURL|
property NSURLVolumeNameKey : a reference to current application’s NSURLVolumeNameKey

set aPath to POSIX path of (choose folder)
set dRes to retDiskNameOfTheFolder(aPath) of me

on retDiskNameOfTheFolder(aPath)
  set aURL to |NSURL|’s fileURLWithPath:aPath
  
set aVlomeName to ""
  
set {aRes, driveName} to aURL’s getResourceValue:(reference) forKey:(NSURLVolumeNameKey) |error|:(missing value)
  
return driveName as string
end retDiskNameOfTheFolder

★Click Here to Open This Script 

Posted in drive File path | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

1箇所から別の箇所の方位を求める v2

Posted on 5月 12, 2018 by Takaaki Naganoya

任意の緯度・経度情報から、別の箇所の緯度・経度情報の「方位」を計算するAppleScriptです。

v1では、Satimage OSAXのインストールが必要でしたが、自前でObjective-Cで書いた「atan2だけを計算するフレームワーク」に置き換えたものです。

–> trigonometry.framework (To ~/Library/Frameworks/)

北を0として、西に向かうとマイナス、東に向かうとプラスの値で角度(方位)を返します。この手の計算に必須のatan2関数がAppleScriptに標準装備されていないため、atan2を呼び出すだけの簡単なCocoa FrameworkをObjective-Cで記述して、呼び出してみました。

→ のちにこれを、FrameworkもBdridgePlusも使わない、自前の関数計算ライブラリ「calcLibAS」を使って計算するように書き換えたサンプル「Calc direction from place A to B」を掲載しています

AppleScript名:1箇所から別の箇所の方位を求める v2
— Created 2018-05-10 by Takaaki Naganoya
— 2017-2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "trigonometry" –(for atan2 calculation)
use bPlus : script "BridgePlus" –https://www.macosxautomation.com/applescript/apps/BridgePlus.html

set coord1 to {latitude:35.73677496, longitude:139.63754457} –Nakamurabashi Sta.
set coord2 to {latitude:35.78839012, longitude:139.61241447} –Wakoshi Sta.
set dirRes1 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me
–>  -25.925429877542

set coord2 to {latitude:35.7227821, longitude:139.63860897} –Saginomiya Sta.
set dirRes2 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me
–>  175.649833487804

set coord2 to {latitude:35.73590542, longitude:139.62986745} –Fujimidai Sta.
set dirRes3 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me
–>  -96.385293928667

set coord2 to {latitude:35.73785024, longitude:139.65339321} –Nerima Sta.
set dirRes4 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me
–>  85.959474671834

set coord2 to {latitude:35.71026838, longitude:139.81215754} –Tokyo Sky Tree
set dirRes5 to calcDirectionBetweenTwoPlaces(coord1, coord2) of me
–>  96.826542737106

–位置情報1から位置情報2の方角を計算。北が0度
on calcDirectionBetweenTwoPlaces(coord1, coord2)
  load framework –BridgePlus
  
set deltaLong to (longitude of coord2) – (longitude of coord1)
  
set yComponent to bPlus’s sinValueOf:deltaLong
  
set xComponent to (bPlus’s cosValueOf:(latitude of coord1)) * (bPlus’s sinValueOf:(latitude of coord2)) – (bPlus’s sinValueOf:(latitude of coord1)) * (bPlus’s cosValueOf:(latitude of coord2)) * (bPlus’s cosValueOf:deltaLong)
  
  
set radians to (current application’s calcAtan2’s atan2Num:yComponent withNum:xComponent) as real
  
set degreeRes to (radToDeg(radians) of me)
  
  
return degreeRes
end calcDirectionBetweenTwoPlaces

on radToDeg(aRadian)
  return aRadian * (180 / pi)
end radToDeg

★Click Here to Open This Script 

Posted in geolocation | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

指定のリスト中の指定要素が占める割合をパーセントで返す

Posted on 5月 11, 2018 by Takaaki Naganoya

指定List中の指定要素が占める割合をパーセントの数値で返すAppleScriptです。

ローカルのiTunesライブラリに入っている楽曲のアーティスト名を集計して、各アーティストがiTunes Music Storeで販売している楽曲のうち、どの程度の割合でApple Musicでも配信しているかを調査するAppleScriptを作成するために作成したものです。

AppleScript名:指定のリスト中の指定要素が占める割合をパーセントで返す
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"

set aList to {false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, true, true, true, false, true, true, true, true, true, true, true, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true}

set tPercent to calcOneItemsPercent(aList, true) of me
–> 62 (%)

–true/falseで構成されるlistのうち、指定要素が占める割合を%で計算。小数点以下を四捨五入
on calcOneItemsPercent(aList, targItem)
  set aLen to length of aList
  
set theCountedSet to current application’s NSCountedSet’s alloc()’s initWithArray:aList
  
set tRes to (theCountedSet’s countForObject:targItem)
  
if tRes < 1 then return 0
  
set pRes to (tRes / aLen) * 100
  
return (round pRes rounding as taught in school)
end calcOneItemsPercent

★Click Here to Open This Script 

Posted in list Number | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

path control×2を作成 v2

Posted on 5月 10, 2018 by Takaaki Naganoya

Windowを作成して、その上に2つのNSPathControlを作成し、ドラッグ&ドロップでパス情報を取得するAppleScriptです。

–> Watch Demo Movie

パス情報をドラッグ&ドロップで受け付けるNSPathControlはXcode上でAppleScriptのアプリケーションを作成する場合にはよく使うGUI部品ですが、通常の(Script Editor上の)AppleScriptではあまり使っていませんでした。

AppleScriptでは、choose fileやchoose folderコマンドを複数回実行して複数のパス情報を取得するのが「いつものやり方」ですが、複数のフォルダを指定する場合で人為的なミスが許されない場合には、指定されたパス情報をあらためてダイアログで表示するなどの処理を入れていました。

受け付けた2つのパス情報は、とくにファイルであってもフォルダであってもかまわないのですが、Cocoaで取得したフォルダのPOSIX path情報は末尾にスラッシュがついていないため、AppleScriptのPOSIX pathとして使用する場合には末尾にスラッシュを補う必要があります。

AppleScript側からハンドラを強制的にMain Threadで実行しているため、Command-Control-Rで実行させる必要はありません。その一方で、Script Menuから呼び出した場合にはドラッグ&ドロップを受け付けることや、ボタンのクリックの受信ができません。

AppleScript名:path control×2を作成 v2
— Created 2018-05-09 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property windisp : false
property wController : false
property resList : {}

set aButtonMSG to "OK"
set aSliderValMSG to "処理対象フォルダと移動先の指定"

set paramList to {aButtonMSG, aSliderValMSG}

my performSelectorOnMainThread:"getPathControlValue:" withObject:paramList waitUntilDone:true
return my resList

on getPathControlValue:paramList
  copy paramList to {aButtonMSG, aSliderValMSG}
  
  
set timeOutSecs to 180 –タイムアウト時間
  
set (my windisp) to true — Window表示中フラグ
  
  
set aView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 600, 120))
  
  
–Labelをつくる
  
set a1TF to current application’s NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(20, 110, 80, 20))
  
set a2TF to current application’s NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(20, 70, 80, 20))
  
a1TF’s setEditable:false
  
a2TF’s setEditable:false
  
a1TF’s setStringValue:"処理対象:"
  
a2TF’s setStringValue:"移動後 :"
  
a1TF’s setDrawsBackground:false
  
a2TF’s setDrawsBackground:false
  
a1TF’s setBordered:false
  
a2TF’s setBordered:false
  
  
–Ppopup Buttonをつくる
  
set aPathControl to current application’s NSPathControl’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 110, 500, 20))
  
set bPathControl to current application’s NSPathControl’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 70, 500, 20))
  
  
aPathControl’s setBackgroundColor:(current application’s NSColor’s cyanColor())
  
bPathControl’s setBackgroundColor:(current application’s NSColor’s yellowColor())
  
  
set aHome to current application’s |NSURL|’s fileURLWithPath:(current application’s NSHomeDirectory())
  
aPathControl’s setURL:aHome
  
bPathControl’s setURL:aHome
  
  
–Buttonをつくる
  
set bButton to (current application’s NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(200, 10, 180, 40)))
  
bButton’s setButtonType:(current application’s NSMomentaryLightButton)
  
bButton’s setBezelStyle:(current application’s NSRoundedBezelStyle)
  
bButton’s setTitle:aButtonMSG
  
bButton’s setTarget:me
  
bButton’s setAction:("clicked:")
  
bButton’s setKeyEquivalent:(return)
  
  
aView’s addSubview:a1TF
  
aView’s addSubview:a2TF
  
  
aView’s addSubview:aPathControl
  
aView’s addSubview:bPathControl
  
aView’s addSubview:bButton
  
aView’s setNeedsDisplay:true
  
  
–NSWindowControllerを作ってみた
  
set aWin to (my makeWinWithView(aView, 600, 160, aSliderValMSG))
  
set wController to current application’s NSWindowController’s alloc()
  
wController’s initWithWindow:aWin
  
  
wController’s showWindow:me
  
  
set aCount to timeOutSecs * 10
  
  
set hitF to false
  
repeat aCount times
    if (my windisp) = false then
      set hitF to true
      
exit repeat
    end if
    
delay 0.1
    
set aCount to aCount – 1
  end repeat
  
  
my closeWin:aWin
  
  
if hitF = true then
    set s1Val to (aPathControl’s |URL|’s |path|()) as string
    
set s2Val to (bPathControl’s |URL|’s |path|()) as string
  else
    set {s1Val, s2Val} to {false, false}
  end if
  
  
set resList to {s1Val, s2Val}
  
end getPathControlValue:

on clicked:aSender
  set (my windisp) to false
end clicked:

–make Window for Display
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle)
  set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
set aBacking to current application’s NSTitledWindowMask
  
set aDefer to current application’s NSBackingStoreBuffered
  
  
— Window
  
set aWin to current application’s NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:false
  
aWin’s setLevel:(current application’s NSNormalWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
aWin’s setContentView:aView
  
  
return aWin
end makeWinWithView

–close win
on closeWin:aWindow
  repeat with n from 10 to 1 by -1
    (aWindow’s setAlphaValue:n / 10)
    
delay 0.02
  end repeat
  
aWindow’s |close|()
end closeWin:

★Click Here to Open This Script 

Posted in File path GUI | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

searchTreeKitを呼び出して1D List抽出

Posted on 5月 9, 2018 by Takaaki Naganoya

PJTernarySearchTreeをCocoa Framework化したsearchTreeKitを呼び出して、高速にテキスト検索を行う(はずの)AppleScriptです。

–> SearchTreeKit.framework (To ~/Library/Frameworks/)

普通に1DのNSArrayにテキストを入れて絞り込みを行うよりもスピード面でメリットがあるのかは実測していないのでなんともいえません。PJTernarySearchTreeは検索フィールドの入力履歴からの候補語の検索などに利用するために作られた部品のようです。

AppleScript名:SearchTreeKitのじっけん1(ファイル書き込み)
— Created 2018-05-08 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree

set savePath to POSIX path of (path to desktop) & (do shell script "uuidgen") & "_test.tree"

set aTree to current application’s PJTernarySearchTree’s alloc()’s init()
aTree’s insertString:"http://www.peakji.com"
aTree’s insertString:"http://www.peak-labs.com"
aTree’s insertString:"http://www.facebook.com"
aTree’s insertString:"http://www.face.com"
aTree’s insertString:"http://blog.foo.com"
aTree’s insertString:"http://blog.foo.com/bar"

aTree’s insertString:"http://chinese.hello.com/ぴよー"
aTree’s insertString:"http://chinese.hello.com/ぴよぴよー"

aTree’s saveTreeToFile:savePath

★Click Here to Open This Script 

AppleScript名:SearchTreeKitのじっけん2(ファイル読み込み)
— Created 2018-05-08 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree

set savePath to POSIX path of (choose file)

set aTree to current application’s PJTernarySearchTree’s treeWithFile:savePath

set aRetrieved to (aTree’s retrievePrefix:"http://" countLimit:0) as list
–return aRetrieved
–>  {"http://blog.foo.com", "http://blog.foo.com/bar", "http://chinese.hello.com/ぴよぴよー", "http://chinese.hello.com/ぴよー", "http://www.face.com", "http://www.facebook.com", "http://www.peak-labs.com", "http://www.peakji.com"}

set bRetrieved to (aTree’s retrievePrefix:"http://" countLimit:2) as list
–return bRetrieved
–>{"http://blog.foo.com", "http://blog.foo.com/bar"}

set cRetrieved to (aTree’s retrievePrefix:"http://www." countLimit:0) as list
–return cRetrieved
–>  {"http://www.face.com", "http://www.facebook.com", "http://www.peak-labs.com", "http://www.peakji.com"}

–Remove a string or object
aTree’s removeString:"http://www.face.com"
set dRetrieved to (aTree’s retrievePrefix:"http://www.fa." countLimit:0) as list
–>  {}

★Click Here to Open This Script 

AppleScript名:SearchTreeKitのじっけん3(オブジェクトの追加と検索)
— Created 2018-05-09 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "SearchTreeKit" –https://github.com/peakji/PJTernarySearchTree

set tagSearchTree to current application’s PJTernarySearchTree’s alloc()’s init()
tagSearchTree’s insertString:"abcd"
(
tagSearchTree’s retrievePrefix:"abc") as list
–>  {​​​​​"abcd"​​​}

tagSearchTree’s insertString:"def"
tagSearchTree’s insertString:"ghi"

tagSearchTree’s removeString:"abcd"

set aList to (tagSearchTree’s retrievePrefix:"") as list
–>  {"def", ​​​​​"ghi"​​​}

★Click Here to Open This Script 

Posted in list Text | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

atan2をFramework呼び出しで計算する

Posted on 5月 8, 2018 by Takaaki Naganoya

自作のCocoa Frameworkを呼び出してatan2の値を計算するAppleScriptです。

2点の緯度経度情報同士の方位(角度)を計算するatan2は、位置情報計算において割と重要な関数ですが、AppleScriptの標準状態では利用できません。

Satimage SoftwareのSatimage OSAX(フリー)をインストールすることでAppleScript中から利用できるようになりますが、これだけだといまひとつ不安なので、atan2を呼び出すだけの簡単なCocoa FrameworkをObjective-Cで記述して、呼び出してみました。

trigonometry.framework (To ~/Library/Frameworks)

Cocoa FrameworkとAppleScriptの間ではNSNumberでやりとりしますが、atan2の計算をObjective-C内で行うにはCGFloatで値を渡す必要がありました(maybe)。また、atan2の計算後に結果をCGFloatからNSNumberに変換。この計算結果をAppleScriptで受け取っています。

一応、両方の計算結果を付けあわせて0〜180度、0〜-180度の範囲で検算を行なったところ、同じ結果が得られました。

atan2の計算速度について、Satimage OSAXとFramework呼び出しで比較してみたところ(1万回ループで計測)、

  Satimage OSAX:0.0000224 sec
  Cocoa Framework:0.0000649 sec

と、OSAXよりもFramework呼び出しのほうが3倍時間がかかることがわかりました。ただし、1回あたりの所要時間がごくごく短いので、あまり問題にならないレベルでしょう。

Numbers.appの内部で利用している関数ライブラリ「cephes math library」をCocoa FrameworkにWrappingした「ObjectiveCephes」が存在しているものの、同ライブラリがCのライブラリであるためか、入出力をNSNumberで行うことができない仕様になっていました(処理速度を確保するため???)。このatan2の計算フレームワークと同様にパラメータをcastするようにすれば、cephes math libraryに含まれる各関数をAppleScriptから利用できることになるはずです。

AppleScript名:atan2をFramework呼び出しで計算する
— Created 2018-05-07 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "trigonometry" –By myself

set aNum to 10
set bNum to 20
set aList to {aNum, bNum}
set cNum to atan2 aList –SatImage OSAX
–>  0.463647609001

set dNum to (current application’s calcAtan2’s atan2Num:aNum withNum:bNum) as real
–>  0.463647609001

★Click Here to Open This Script 

AppleScript名:atan2をFramework呼び出しで計算する(検算)
— Created 2018-05-07 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "trigonometry" –By myself

set aNum to 0
set notMatchList to {}

repeat with bNum from 0 to 180
  set aList to {aNum, bNum}
  
set cNum to atan2 aList –SatImage OSAX
  
set dNum to (current application’s calcAtan2’s atan2Num:aNum withNum:bNum) as real
  
  
if cNum is not equal to dNum then
    set the end of notMatchList to {cNum, dNum}
  end if
end repeat

repeat with bNum from 0 to -180 by -1
  set aList to {aNum, bNum}
  
set cNum to atan2 aList –SatImage OSAX
  
set dNum to (current application’s calcAtan2’s atan2Num:aNum withNum:bNum) as real
  
  
if cNum is not equal to dNum then
    set the end of notMatchList to {cNum, dNum}
  end if
end repeat

return notMatchList

★Click Here to Open This Script 

Posted in Number | Tagged 10.11savvy 10.12savvy 10.13savvy | 1 Comment

Geofenceを付けつつReminder項目を追加

Posted on 5月 5, 2018 by Takaaki Naganoya

Reminders.app(リマインダー)に新規リマインド項目を作成し、Geofenceを設定するAppleScriptです。

Reminders.appのAppleScript用語辞書にはGeofence作成機能は用意されていないため、Cocoaの機能を利用して追加しました。

Geofenceは、指定の緯度・経度のポイントから半径xxxメートルの円の中に入る場合に発生するアラーム(Enter Alarm)、脱出する場合に発生するアラーム(Leave Alarm)の2種類を設定できます。

Mac上のReminders.app上で登録したこのリマインド項目がiCloud経由でiPhoneにシンクロされ、iPhoneを持って当該期間中に指定場所に行って半径200メートルの円の中から出るとアラームが表示されることになります。

AppleScript名:Geofenceを付けつつReminder項目を追加
— Created 2014-12-08 by Shane Stanley
— Modified 2015-09-24 by Takaaki Naganoya –Geofence Alarm
— Modified 2015-09-24 by Shane Stanley –Fix the way to Create the geofence alarm
— Modified 2015-09-24 by Takaaki Naganoya –change and test for El Capitan’s Enum bridging
–Reference:
–http://stackoverflow.com/questions/26903847/add-location-to-ekevent-ios-calendar
–http://timhibbard.com/blog/2013/01/03/how-to-create-remove-and-manage-geofence-reminders-in-ios-programmatically-with-xcode/
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "EventKit"

property EKAlarm : a reference to current application’s EKAlarm
property CLLocation : a reference to current application’s CLLocation
property EKEventStore : a reference to current application’s EKEventStore
property EKStructuredLocation : a reference to current application’s EKStructuredLocation
property EKEntityMaskReminder : a reference to current application’s EKEntityMaskReminder
property EKAlarmProximityEnter : a reference to current application’s EKAlarmProximityEnter
property EKAlarmProximityLeave : a reference to current application’s EKAlarmProximityLeave

–Start Date
set dSt to "2018/06/01 00:00:00"
set dateO1 to date dSt

–End Date
set dSt2 to "2018/08/01 00:00:00"
set dateO2 to date dSt2

tell application "Reminders"
  if not (exists list "test") then
    make new list with properties {name:"test"}
  end if
  
  
tell list "test"
    set aReminder to (make new reminder with properties {name:"Test1", body:"New Reminder", due date:dateO2, remind me date:dateO1, priority:9}) –priority 1:高、5:中、9:低、0:なし
    
set anID to id of aReminder
    
–> "x-apple-reminder://XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
  end tell
end tell

set theID to text 20 thru -1 of anID
my setLocationToLeaveForReminderID(35.745769, 139.675565, "Target Place", theID, 200)

–指定場所に到着した時に発動するGeofence Alarmを指定のリマインダーに登録する。Geofence半径指定つき(単位:メートル)
on setLocationToEnterForReminderID(aLatitude, aLongitude, aTitle, theID, aRangeByMeter)
  — Get event store
  
set eventStore to EKEventStore’s alloc()’s initWithAccessToEntityTypes:(EKEntityMaskReminder)
  
  
— Get the reminder
  
set theReminder to eventStore’s calendarItemWithIdentifier:theID
  
  
–Create the geofence alarm
  
set enterAlarm to EKAlarm’s alarmWithRelativeOffset:0
  
enterAlarm’s setProximity:(EKAlarmProximityEnter)
  
set structLoc to EKStructuredLocation’s locationWithTitle:aTitle
  
set aLoc to CLLocation’s alloc()’s initWithLatitude:aLatitude longitude:aLongitude
  
structLoc’s setGeoLocation:aLoc
  
  
— Set radius by meters
  
structLoc’s setRadius:aRangeByMeter
  
enterAlarm’s setStructuredLocation:structLoc
  
  
theReminder’s addAlarm:enterAlarm
  
set aRes to eventStore’s saveReminder:theReminder commit:true |error|:(missing value)
  
  
return aRes as boolean
end setLocationToEnterForReminderID

–指定場所を出発した時に発動するGeofence Alarmを指定のリマインダーに登録する。Geofence半径指定つき(単位:メートル)
on setLocationToLeaveForReminderID(aLatitude, aLongitude, aTitle, theID, aRangeByMeter)
  — Get event store; 1 means reminders
  
set eventStore to EKEventStore’s alloc()’s initWithAccessToEntityTypes:(EKEntityMaskReminder)
  
  
— Get the reminder
  
set theReminder to eventStore’s calendarItemWithIdentifier:theID
  
  
–Create the geofence alarm
  
set leaveAlarm to EKAlarm’s alarmWithRelativeOffset:0
  
leaveAlarm’s setProximity:(EKAlarmProximityLeave)
  
set structLoc to EKStructuredLocation’s locationWithTitle:aTitle
  
set aLoc to CLLocation’s alloc()’s initWithLatitude:aLatitude longitude:aLongitude
  
structLoc’s setGeoLocation:aLoc
  
  
— Set radius by meters
  
structLoc’s setRadius:aRangeByMeter
  
leaveAlarm’s setStructuredLocation:structLoc
  
  
theReminder’s addAlarm:leaveAlarm
  
set aRes to eventStore’s saveReminder:theReminder commit:true |error|:(missing value)
  
  
return aRes as boolean
end setLocationToLeaveForReminderID

★Click Here to Open This Script 

Posted in Calendar geolocation | Tagged 10.11savvy 10.12savvy 10.13savvy Reminders | Leave a comment

旧暦計算を行う

Posted on 5月 4, 2018 by Takaaki Naganoya

指定の年・月・日から旧暦の日付および六曜を計算するAppleScriptです。

旧暦は太陰暦で、月の満ち欠けを基準とした暦(こよみ)です。旧暦計算は各種関数が必要になるため、AppleScriptだけで計算させると骨が折れますが、これまでにも他の言語のプログラムを呼び出すかたちで計算ライブラリを利用してきました。

本Scriptでは、Objective-Cで書かれたプログラム(バンドル内にplistでデータを持つタイプ)をCocoa Framework化してAppleScriptから呼び出せるようにしたものです。

–> kyurekiKit.framework (To ~/Library/Frameworks)

きょうび、旧暦計算が必要な用途なんてカレンダー製作とか手帳製作あたりで、クライアント企業もだいたい決まっています。業界にその名もとどろく、事前に仕様を出さないのに仕様後出しじゃんけんをしまくって難癖をつけてくる悪名高い極悪非道クライアント様が。だいたいは、事前に旧暦計算データも支給されるので、自前で旧暦計算する必要性に遭遇したことはありません。

AppleScript名:旧暦計算を行う
— Created 2018-05-04 by Takaaki Naganoya
— 2018 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "KyurekiKit" –https://github.com/kyasusoft/Rokuyo
–2000年から2032年までのデータをFrameworkに内蔵

set curDat to current date
set curYear to year of curDat
set curMonth to month of curDat as number
set curDate to day of curDat

set r to current application’s KYRokuyo’s alloc()’s init()
set rokuyoText to (r’s sinrekiToRokuyoWithYear:curYear |month|:curMonth |day|:curDate) as string

set kyuMonth to (r’s kyuMonth) as integer
set kyuDay to (r’s kyuDay) as integer

return {kyuMonth, kyuDay, rokuyoText}
–>  {​​​​​3, ​​​​​19, ​​​​​"先負"​​​}

★Click Here to Open This Script 

Posted in Calendar | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

自然言語で指定した日時以降に作成されたファイルをSpotlight検索

Posted on 5月 3, 2018 by Takaaki Naganoya
AppleScript名:自然言語で指定した日時以降に作成されたファイルをSpotlight検索
— Created 2017-09-21 by Takaaki Naganoya
— Modified 2017-09-22 by Shane Stanley
— 2017 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use mdLib : script "Metadata Lib" version "2.0.0"

property NSString : a reference to current application’s NSString
property NSDataDetector : a reference to current application’s NSDataDetector
property NSTextCheckingTypeDate : a reference to current application’s NSTextCheckingTypeDate

set aDate to getDatesIn("先週の月曜日") of me –"last Monday" in Japanese
log aDate

set thePath to POSIX path of (path to desktop)

set theFiles to mdLib’s searchFolders:{thePath} searchString:("kMDItemFSCreationDate >= %@") searchArgs:{aDate}
–> returns POSIX path list

on getDatesIn(aString)
  set anNSString to NSString’s stringWithString:aString
  
set theDetector to NSDataDetector’s dataDetectorWithTypes:(NSTextCheckingTypeDate) |error|:(missing value)
  
set theMatch to theDetector’s firstMatchInString:anNSString options:0 range:{0, anNSString’s |length|()}
  
if theMatch = missing value then error "No date found with String:" & aString
  
set theDate to theMatch’s |date|()
  
return theDate as date
end getDatesIn

★Click Here to Open This Script 

Posted in Calendar file Spotlight | Tagged 10.11savvy 10.12savvy 10.13savvy | Leave a comment

Markdownのimglinkタグ行のリンク書き換え

Posted on 5月 3, 2018 by Takaaki Naganoya

Markdown書類からリンクしているローカルの画像(相対パス表記)へのリンクを書き換えるAppleScriptです。

MacDownが画像リンクの管理などは一切してくれないので、自前で(AppleScriptで)書き換えを行なっています。

ルートフォルダはフォルダ名が「–」ではじまるようにルールを(勝手に)決めており、各Markdown書類フォルダをさらに細分化した場合には、Markdown書類から画像フォルダへの相対パス指定が合わなくなってしまいます。

そこで、画像フォルダを求めてMarkdown書類の画像リンクを再計算して書き換えてみました。画像自体をルートフォルダからSpotlightで検索するようにしてもよいのですが、今回はとりあえずルールを自分で決めて自分で守っているので、このように処理してみました。

ただ、いまだにリンク画像のパスを手で書かされる(記述自体はAppleScriptでその場で計算しているので完全手書きではないですが)のには、いささかMarkdownの仕様の素朴さに呆れてしまうところです、、、、

AppleScript名:Markdownのimglinkタグ行のリンク書き換え
— Created 2017-01-26 by Takaaki Naganoya
— 2017 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use mdLib : script "Metadata Lib" version "2.0.0" –https://www.macosxautomation.com/applescript/apps/

property NSArray : a reference to current application’s NSArray
property NSString : a reference to current application’s NSString
property NSScanner : a reference to current application’s NSScanner
property NSPredicate : a reference to current application’s NSPredicate
property NSDictionary : a reference to current application’s NSDictionary
property NSMutableArray : a reference to current application’s NSMutableArray
property NSDataDetector : a reference to current application’s NSDataDetector
property NSAttributedString : a reference to current application’s NSAttributedString
property NSUTF8StringEncoding : a reference to current application’s NSUTF8StringEncoding
property NSTextCheckingTypeLink : a reference to current application’s NSTextCheckingTypeLink

set origPath to POSIX path of (choose folder with prompt "Markdown書類が入っているフォルダを選択")
set savePath to POSIX path of (choose folder with prompt "画像フォルダを選択")

set tmp2 to NSString’s stringWithString:savePath
set tmp3 to (tmp2’s lastPathComponent()) as string

–Spotlightで指定フォルダ以下のMarkdown書類を検索
set aRes to mdLib’s searchFolders:{origPath} searchString:("kMDItemKind == %@ ") searchArgs:{"Markdown Document"}

repeat with i in aRes
  
  
–テキストエンコーディングをUTF-8でMarkDown書類テキスト読み込み
  
set aText to (NSString’s stringWithContentsOfFile:(i) encoding:(NSUTF8StringEncoding) |error|:(missing value)) as string
  
  
–Markdown記法の画像タグが入っている場合のみ処理
  
set repLinkURLs to {} –パス置換対象リスト(oldPath, newPathでペア)
  
  
set aFreq to retFrequency(aText, "![") of me
  
  
if aFreq is not equal to 0 then
    set bList to parseStringParagraphs(NSString’s stringWithString:aText) of me
    
set aPredicates to NSPredicate’s predicateWithFormat_("SELF BEGINSWITH[cd] %@", "![")
    
set cList to (bList’s filteredArrayUsingPredicate:aPredicates) as list
    
    
–画像ダウンロードおよび、ダウンロードずみ画像への相対パスの計算ループ
    
repeat with ii in cList
      set jj to contents of ii –画像リンクのMarkdownタグ行
      
set tmpLinkPath to parseStrFromTo(jj, "(", ")") of me
      
      
set aStr to (NSString’s stringWithString:((contents of i) as string))
      
set aList to (aStr’s stringByDeletingLastPathComponent’s pathComponents()) as list of string or string
      
      
set aLen to length of aList
      
      
–リンク画像の相対パスを絶対パスに変換する
      
set rStr to (NSString’s stringWithString:tmpLinkPath)
      
set r2Str to rStr’s stringByDeletingLastPathComponent’s lastPathComponent() –フォルダ名(="9999_images")
      
set r3Str to (rStr’s lastPathComponent()) as string –ファイル名(="fake_scriptable.png")
      
      
–書籍のルートフォルダを求め、その直下にある画像フォルダを名指しで指定
      
repeat with i2 from aLen to 0 by -1
        set j to contents of (item i2 of aList)
        
if j begins with "–" then
          exit repeat
        end if
      end repeat
      
      
set f1Path to (items 1 thru i2 of aList) & r2Str & r3Str
      
set f2Path to (NSString’s pathWithComponents:f1Path) as string
      
      
–MarkDown書類と移動先の画像フォルダ中の画像の相対パスを求める
      
set newRelPath to calcRelativePathFromTwoAbsolutePaths(i, f2Path) of me
      
      
set the end of repLinkURLs to {tmpLinkPath, newRelPath}
      
    end repeat
    
    
–リンク書き換え
    
copy aText to bText
    
repeat with ii in repLinkURLs
      copy ii to {oldPath, newPath}
      
set bText to repChar(bText, oldPath, newPath) of me
    end repeat
    
    
–もともとのパスにMarkdown書類を上書き保存
    
set writeString to (NSString’s stringWithString:bText)
    
set ssRes to (writeString’s writeToFile:i atomically:true encoding:(NSUTF8StringEncoding) |error|:(missing value))
    
  end if
end repeat

–指定文字列内の指定キーワードの出現回数を取得する
on retFrequency(origText, aKeyText)
  set aRes to parseByDelim(origText, aKeyText) of me
  
return ((count every item of aRes) – 1)
end retFrequency

on parseByDelim(aData, aDelim)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set dList to text items of aData
  
set AppleScript’s text item delimiters to curDelim
  
return dList
end parseByDelim

–テキストを行ごとにparseしてNSArrayに
on parseStringParagraphs(anNSString)
  set anArray to NSMutableArray’s alloc()’s init()
  
set aRange to current application’s NSMakeRange(0, anNSString’s |length|())
  
  
repeat while aRange’s |length|() > 0
    set subRange to anNSString’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 anNSString’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
  
  
return anArray
end parseStringParagraphs

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

on parseStrFromTo(aParamStr, fromStr, toStr)
  set theScanner to NSScanner’s scannerWithString:aParamStr
  
set anArray to NSMutableArray’s array()
  
  
repeat until (theScanner’s isAtEnd as boolean)
    — terminate check, return the result (aDict) to caller
    
set {theResult, theKey} to theScanner’s scanUpToString:fromStr intoString:(reference)
    
    
— skip over separator
    
theScanner’s scanString:fromStr intoString:(missing value)
    
set {theResult, theValue} to theScanner’s scanUpToString:toStr intoString:(reference)
    
if theValue is missing value then set theValue to "" –>追加
    
    
— skip over separator
    
theScanner’s scanString:toStr intoString:(missing value)
    
    
anArray’s addObject:theValue
  end repeat
  
  
if (anArray’s |count|()) as integer = 1 then
    return theValue as list of string or string
  else
    return anArray as list
  end if
end parseStrFromTo

–2つの絶対パス間の相対パスを求める
on calcRelativePathFromTwoAbsolutePaths(aPOSIXfile as string, bPOSIXfile as string)
  set aStr to NSString’s stringWithString:aPOSIXfile
  
set bStr to NSString’s stringWithString:bPOSIXfile
  
  
set aList to aStr’s pathComponents() as list
  
set bList to bStr’s pathComponents() as list
  
  
set aLen to length of aList
  
set bLen to length of bList
  
  
if aLen ≥ bLen then
    copy aLen to aMax
  else
    copy bLen to aMax
  end if
  
  
repeat with i from 1 to aMax
    set aTmp to contents of item i of aList
    
set bTmp to contents of item i of bList
    
    
if aTmp is not equal to bTmp then
      exit repeat
    end if
  end repeat
  
  
set bbList to items i thru -1 of bList
  
set aaItem to (length of aList) – i
  
  
set tmpStr to {}
  
repeat with ii from 1 to aaItem
    set the end of tmpStr to ".."
  end repeat
  
  
set allRes to NSString’s pathWithComponents:(tmpStr & bbList)
  
return allRes as text
end calcRelativePathFromTwoAbsolutePaths

★Click Here to Open This Script 

Posted in file File path Markdown Spotlight Text | Tagged 10.11savvy 10.12savvy 10.13savvy MacDown | Leave a comment

Post navigation

  • Older posts
  • Newer posts

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 15, Sequoia
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Numbersで選択範囲のセルの前後の空白を削除
  • メキシカンハットの描画
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AppleScriptによる並列処理
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • macOS 15でも変化したText to Speech環境
  • AppleScript入門③AppleScriptを使った「自動化」とは?
  • デフォルトインストールされたフォント名を取得するAppleScript
  • 【続報】macOS 15.5で特定ファイル名パターンのfileをaliasにcastすると100%クラッシュするバグ
  • Script Debuggerの開発と販売が2025年に終了
  • macOS 15 リモートApple Eventsにバグ?
  • AppleScript入門① AppleScriptってなんだろう?
  • macOS 14で変更になったOSバージョン取得APIの返り値
  • NSObjectのクラス名を取得 v2.1
  • macOS 15:スクリプトエディタのAppleScript用語辞書を確認できない
  • 有害ではなくなっていたSpaces
  • Xcode上のAppleScriptObjCのプログラムから、Xcodeのログ欄へのメッセージ出力を実行

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (194) 14.0savvy (147) 15.0savvy (136) CotEditor (66) Finder (51) iTunes (19) Keynote (119) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (76) Pages (55) Safari (44) Script Editor (27) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • check sum
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • date
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • process
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC