Text
Random Messages status message
set iChatPlist to "~/Library/Preferences/com.apple.iChat.StatusMessages.plist" tell application "System Events" set statusMessages to get value of property list item "CustomAvailableMessages" of contents of property list file iChatPlist set newStatus to some item of statusMessages end tell tell application "Messages" set status message to newStatus end tell
Explanation:
Messages still uses plists using iChat's naming scheme1, and com.apple.iChat.StatusMessages.plist contains all status messages
With System Events we can read plist contents. The plist contains two property list items CustomAvailableMessages and CustomAwayMessages.
When you read a property list item if it contains multiple items or an array, AppleScript returns it to you as an array.
From an array you can just choose a random (some) item
It was known as iChat for long time after all ↩︎
0 notes
Text
Disable "copying" style from Terminal
Use Terminal? With a custom colour scheme? Hate when you copy text and having to remember to paste[^1] matching style just to avoid bringing your strange white & ANSI colours on black to your emails and other text?
Luckily this "feature" can be easily disabled: $ defaults write com.apple.Terminal CopyAttributesProfile com.apple.Terminal.no-attributes
The only unfortunate part with this is that the setting is tied to the terminal profile[^2] so if you e.g. duplicate a profile and remove the original profile, com.apple.Terminal.no-attributes value reverts back to com.apple.Terminal.attributes
[1]: Unless you already swapped Paste and Paste matching Style keyboard shortcuts already
[2]: Not to the global Terminal property list
0 notes
Text
Open current folder in shell
If you want to open the current folder in shell on OS X the simplest way is just by dragging the folder icon to your terminal window. Unfortunately, your shell window might not be visible or running, so what other options do you have?
Drag the folder icon to Terminal on Dock.
Add Terminal to the tool bar of Finder by command-dragging it there from Utilities. Now you can a) launch it faster than from the Dock, and b) drag folders1 on it to open a new shell window.
Both of these are good to know, and it's handy to have Terminal icon on your Finder toolbar, like it is to have also Mail 2 or your text editor, but it's not as effective as having a keyboard command.
To create a keyboard command for launching current Finder window in Terminal:
Create a new service in Automator.
Service receives No Input in Finder.
Add Run AppleScript function.
For the code: tell application "Finder" set _path to quoted form of (POSIX path of (target of window 1 as alias)) # Get Current window's path end tell tell application "Terminal" do script "cd " & _path & "; clear; echo " & _path # open a new shell window and echo the path to the top of the window activate end tell
Save it as a service and assign a keyboard command for it in Sys.Prefs>Keyboard>Shortcuts>Services.
Or any other file Terminal can open. ↩︎
To quickly email files ↩︎
0 notes
Link
Joel Spolsky on abstraction layers:
Abstractions fail. Sometimes a little, sometimes a lot. There's leakage. Things go wrong. It happens all over the place when you have abstractions.
0 notes
Link
0 notes
Link
Brett Terpstra had already resolved a problem I've had for a while: how to find markdown files with Spotlight. His brief, but informative enough, explanation led me to a way to add additional, effectively plain-text, content for spotlight to index:
Download his mdimport bundle
Open it's info.plist in Xcode, or a text-editor
Add a new line into Document content type UTIs (LSItemContentTypes) referencing the app whose content types you want to be indexed. E.g. to index html add com.apple.safari
0 notes
Text
Link directly to man pages
You can create direct links to terminal's man pages using "x-man-page" URL type. E.g. x-man-page://grep launches terminal and opens grep's man page in a separate window.
Using this URI scheme you can create service that receives selected text in any application and opens it as an URL using x-man-page:// prefix. After you've created the service you can bind it to a keyboard command in System Preferences > Keyboards > Keyboard Shortcuts > Services for fast access.
0 notes
Text
Automate variable changes to AppleScript
Sometimes you might need to do multiple similar changes to your scripts. There is always option to find&replace, but this gets tedious for multiple files. So why not script your script changes. This removes the human error factor and when wrapped to a nice UI (e.g. "just drop your scripts here") it makes it easy to share the changes with other users of the scripts.
OS X has all the necessary utilities for this built-in: osadecompile, to decompile AppleScripts to plaintext output osacompile, to compile plaintext back to AppleScript
Now all needed is something to do the substitution for which regular expressions is the simplest and fastest method. Whether you prefer sed or awk is up to you. This example uses sed since it's slightly simpler for straightforward1 substitutions. For more complex2 substitutions, like ones requiring programmability, awk tends to be simpler and more versatile solution.
$ osadecompile old_scriptname.scpt | sed 's/old_var/new_var/;s/Old App Name/New App Name/;s/etc/and so on/' | osacompile -o new_scriptname.scpt
In this example osadecompile prints script contents from "old_scriptname.scpt", sed changes all instances of "old_var" to "new_var" and "Old App Name" to "New App Name", and then osacompile writes these changes to a file called "new_scriptname.scpt". All this can be easily wrapped to an application that does it for the user with just drag'n'drop.
Change "foo" to "bar" ↩︎
Change certain text around "foo" ↩︎
0 notes
Text
Calling Script Objects from another script
If you have a set of script objects you're using often in multiple scripts, instead of copy-pasting the code over and over again to multiple scrips you might want to create a separate script library you call when ever you need that object.
You can load existing scripts with load script [path to script]
E.g. occasionally I need a method to round fractions. Instead of using following code in all scripts requiring rounding it can be called from an external script:
on _RoundThis(n, numDecimals) set x to 10 ^ numDecimals (((n * x) + 0.5) div 1) / x end _RoundThis
To call _RoundThis() from another script load the script and assign it to a variable. Then just call the script object through the variable:
property _scriptPath : (path to home folder) & "AppleScript:ScriptLibrary.scpt" as string set myLib to load script _scriptPath as alias myLib's _RoundThis(3.14159265359, 3) --> 3.142
In this example _RoundThis() is stored in a file called "ScriptLibrary.scpt" along with other script objects, but now they are all at your disposal without needing to keep the code in multiple places which helps version controlling. In a way this is the first step towards your own framework.
You can go even further 1 by creating a script object around another scripts script object 2
global myLib on _RoundThis(n, D) myLib's _RoundThis(n, D) end _RoundThis
You're definitely losing the benefit of leaner code with a likely performance hit for more complex tasks. ↩︎
Definitely too meta ↩︎
0 notes
Link
> Starting in OS X 10.5, AppleScript allows use of the # symbol as a comment-to-end-of-line token (the traditional double hyphen (--) is also still supported). This means that you can make a plain AppleScript script into a Unix executable by beginning it with the following line and giving it execute permission.
#!/usr/bin/osascript
0 notes
Text
Months in AppleScript
The simplest way to get date in AppleScript is with **(current date)** current date --> date "Wednesday, 20 February 2013 12:34:56" You can also grab individual parts of the date set today to weekday of (current date) --> Wednesday set thisYear to year of (current date) --> 2013 And combine them: set _d to {day, month, year} of *(current date)* --> {20, February, 2013} Unfortunately there isn't an automated way to call month in numeric form while month as number is probably more useful format than month as text[^1]. I've used and seen many workarounds for this ranging from array full of months[^2] to **do shell script "date +%Y.%m.%d"** but luckily there is a simpler *native* solution in AppleScript since it can also treat months as integers: set thisMonth to month of (current date) as integer --> 2 Naturally same works with weekdays (though remember that Sunday is then 1st day of week): set today to weekday of (current date) --> Wednesday set today to weekday of (current date) as integer --> 4 If you're calling for multiple items, such as day+month+year, at the time you can't determine their type while calling so you need to convert them afterwards: set today to {day, month, year} of (current date) --> {20, February, 2013} set item 2 of today to (item 2 of today as integer) --> {20, 2, 2013} You can also multiply months by 1 (or any other number) and AppleScript will force the number to behave as interger_ set today to {day, month, year} of (current date) --> {20, February, 2013} set item 2 of today to (item 2 of today)*1 --> {20, 2, 2013} [^1]:Especially when programming or scripting [^2]: Plain and Simple: global monthArray global thisMonth set monthArray to {"January", "February", "March"} set thisMonth to month of (current date) my getMonthNumber(thisMonth as text) on getMonthNumber(thisMonth) repeat with i from 1 to the count of monthArray if item i of monthArray contains thisMonth then exit repeat end repeat return i end getMonthNumber
0 notes
Link
Apple's very thorough and explanatory[^1] Developer documentation for shell scripting fundamentals [^1]: Even for sed and awk!
0 notes
Text
Easy markdown footnotes
> This script is intended to be used in combination with a text expander software[^1] supporting running AppleScripts from snippets. > This markdown's footnote reference, [^n], to the point of typing and then moves cursor to the end of the document and then adds the footnote, [^n]:, there. # # AppleScript global _app set _app to my GetCurrentApp() set _mdRef to "[^1]" set _mdFootNote to "[^1]:" **tell application "System Events" to tell process _app** keystroke backspace keystroke _mdRef keystroke (ASCII character 31) using command down keystroke return & _mdFootNote **end tell** **on GetCurrentApp()** tell application "System Events" to set _app to item 1 of (every process whose frontmost is true) return name of _app **end GetCurrentApp** # # Explanation (for some parts) global _app, declaring a global variable is not necessary in this case but if you use your own handlers often it is good practice to declare ones you pass around. For more info see [Apple's AppleScript Language Guide on Variables and Properties](https://developer.apple.com/library/mac/#documentation/applescript/conceptual/applescriptlangguide/conceptual/ASLR_variables.html) set _app to my GetCurrentApp(), call to a handler may fail when called from within an application if you do not specify its **my** handler(). Again as with global declaration, not necessary in this but is a good practice to get muscle memory into. tell application "System Events" to tell process _app, "tell x to tell y" is way more practical and requires less code than "tell x, newline, tell y, newline, code, end tell, end tell". keystroke (ASCII character 8) --Backspace, I've set my TextExpander to only consider snippets after a space, which is why I need to have it removed. Adjust if/as needed. keystroke (ASCII character 31) using command down --Command+Down Arrow, as stated in the comment, this is just cmd-down arrow on GetCurrentApp() This creates the handler tell application "System Events" to set _app to item 1 of (every process whose frontmost is true), check which app declares it's frontmost and grab the name, again "tell x to tell y" saves an "end tell" [^1]: Such as [Smile's TextExpander](http://smilesoftware.com/TextExpander/)
0 notes
Text
Recent XKCD "hover gag" as status message
> This script uses regular expressions (sed) to lookup content in HTML source and sets the result as iChat/Messages status. In this case it grabs the "hover gag" from most recent [XKCD](http://xkcd.com). set _XKCDStatus to do shell script "curl http://xkcd.com | grep \"http://imgs.xkcd.com/comics\" | sed -n 's/.*title=\"//;s/\" alt=.*//p' | tr -s \"'\" \"'\"" tell application "Messages" to set status message to (_XKCDStatus) ### Explanations \" == Escaped quotation mark. If your script contains quotation marks and you're not intending to end your script, you need to escape the quotation mark with a \ *do shell script* == tells AppleScript to execute the following command in Terminal shell sed == a unix command-line stream editor that parses text. [See more info about sed in wikipedia](http://en.wikipedia.org/wiki/Sed) or $ man sed -n == do not automatically print s/Foo/Bar/ == substitute Foo with Bar, in this case substitute "title=" and anything before with nothing, and substitute "alt=" and anything after with nothing. ; == and .* == wildcard /p == print match stated by expression before tr -s "FooBar" "Foo" == tr is another unix tool that converts text, by default it matches characters so we need to declare with -s to replace the phrases. In case of tr -s \"'\" \"'\" we're replacing html-encoded apostrophe[^1] with a "real" one [^1]: Apostrophe needs to be encoded, some browsers otherwise might presume your title text ending there — depending on how strictly they follow HTML syntax. See comment above regarding escaping quotation marks. If you can encode the character differently I recommend doing so to avoid quirky "fences" such as \"\/\" where we escape a quoted forward slash and the slash itself.
0 notes
Text
Simple loops
This is a simple loop that goes through every item in an array.
In the example below the script displays a dialog with for each item in the myArray array
set myArray to {"Foo", "Bar", "Lorem", "Ipsum"}
repeat with itemName in myArray
display dialog itemName buttons {"OK"}
end repeat
Loop below does the same as the one above but you will have better access to the item in the array.
In the example below the script reverses every word in myArray
set myArray to {"Quick", "Red", "Fox", "Jumps", "Over", "Lazy", "Brown", "Dog"}
set len to (count items of myArray)
set counter to 0
repeat len times
set counter to counter + 1
set item counter of myArray to (reverse of text items of item counter of myArray) as text
end repeat
0 notes
Text
Capitalize every word
This script converts "quick red fox jumps over a lazy brown dog" into "Quick Red Fox Jumps Over A Lazy Brown Dog"
capitalize("quick red fox jumps over a lazy brown dog")
on capitalize(capitalizeMe)
set lowerCaseChars to {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"}
set upperCaseChars to {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
set oldDelims to AppleScript's text item delimiters
set AppleScript's text item delimiters to " "
set capitalizeMe to text items of capitalizeMe
set AppleScript's text item delimiters to oldDelims
set len to count items of capitalizeMe
set counter to 0
repeat len times
set counter to counter + 1
set w to item counter of capitalizeMe
set checkChar to 1st character of w
repeat with i from 1 to the count of lowerCaseChars
if item i of lowerCaseChars contains checkChar then exit repeat
end repeat
set newChar1 to item i of upperCaseChars
if (count characters of w) = 1 then
set item counter of capitalizeMe to newChar1
else
set item counter of capitalizeMe to newChar1 & (characters 2 through -1 of w) as item
end if
end repeat
set AppleScript's text item delimiters to " "
return capitalizeMe as string
set AppleScript's text item delimiters to oldDelims
end capitalize
0 notes