I don’t know how to make some kind of preferences file that my script can read each time it runs, but I do know how to write to a text file. What I need now is to be able to read the last few characters of a text file and take different actions based on them. Anyone know how?
Sure, but be a bit more specific about the problem - you know how to read and write a file - what don’t you know?
Have you read “The Ins & Outs of File Read/Write” by Nigel Garvey?
Hi,
if you only want to read a file, create one in TextEdit with your data and save it as plain text.
Then you can read it with:
read file "path:to:the:file"
to get a list of e.g. all paragraphs, you can use a text delimiter
read file "path:to:the:file" using delimiter ASCII character 10
.
For handling preferences you can also use script objects
Thanks, this is perfect. I’m working up to reading through that sourcebook article, just starting it makes my head spin! What I’m trying to set up is a txt file that I can search for example "ChckbxA - " and then use the next characters to change my app. Anyway, happy scripting all!
Something like this:
set AppleScript's text item delimiters to ""
-- set up a file
set myText to "This file contains the word ChckbxA = false, and a bunch of stuff following it."
set f to open for access ((path to desktop folder as text) & "newFile.txt") with write permission
try
set eof of f to 0 -- erases and starts at beginning
write myText to f
close access f
on error
close access f
end try
-- Now read it
set T to read alias ((path to desktop folder as text) & "newFile.txt")
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "ChckbxA "
set P to text items of T
if (count P) = 2 then set P to text item 2 of P -- if count P > 2 then there is more than one ChckbxA
set AppleScript's text item delimiters to tid
set P to word 2 of P --> "false"
Thanks, that is exactly what I wanted!
How long have you been scripting, you seem to know everything.
Are you going to be using this method in an applescript studio app? If so, you’re missing out on the built-in capabilities of your app called “user defaults” that are the preferred method of storing application state. Saving your preferences in a text file is considered a hack, and should only be done in the most unique of cases. User defaults is easy to use, is automatically configured for every different user, and is technology that is built right into the application framework. That means no mess for you, no added work for you, and reliability that you will not be able to guarantee with your custom method.
If you’re not using this in a ASStudio project, then I apologize for making assumptions. Actually, even if you’re just using this in a plain applescript application, you can still access the user defaults system through ‘do script’ calls to a custom plist file, which is probably just are reliable, if not more, than reading and writing to a text file.
Using a plist file via user defaults is DEFINITELY the way to go in an ASStudio app. You should be wary of creating your own preferences scheme using reading and writing to text files. Using user defaults, you can do in two to four lines of code what you may end up writing in dozens of custom lines of reading/writing/parsing routines. Just something to think seriously about if your developing an ASS app.
j
I wrote my first AppleScript in March of 2004 - you can learn a ton in a couple of years. I’ll never be Kai, Nigel, Jobu, Jacques, or a few others but I get by. So will you in no time. As Kai says: “It’s only easy when you know the answer”, but first you have to encounter all the problems and understand the solutions, as you’re doing.
I’ve never had a problem storing a single word as a plist key, but have never succeeded in storing a long string of text. How do you do that in plain vanilla 'do shell script defaults write …" AppleScript? I’ve tried various quoting schemes, using the -string switch, etc. but it always errors.
You can use long strings, even ones with spaces in the key or value, as long as you single-quote the values you’re passing to the shell script. I don’t ever use the “quoted form of” command, but instead manually code the single quotes into the string I’m sending. I’d advise using only basic characters, alphanumeric and shift-modified numbers. Any extended characters will be converted to plain text by AS before being sent to the shell script. Also make sure not to send any single-quotes in your key or value strings, or it will prematurely end your enclosed string and throw an error.
set theDefaultsDomain to "com.jobu.eminent" --> Should be a reverse domain string w/no spaces & no ".plist" extension
set theKey to "Mauris molestie libero ut dolor tincidunt." --> Can be a string with spaces, as long as the shell script single-quotes it
set theValue to "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Integer aliquet egestas elit. Aliquam erat volutpat. Aenean arcu leo, semper a, eleifend et, tempor nec, justo. Vivamus accumsan. Nulla volutpat tortor a libero. Morbi dictum suscipit lorem. Aliquam porta. Vestibulum eros. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos hymenaeos. Cras eu eros. Donec ac sapien auctor massa vulputate egestas. Suspendisse dignissim nibh a ipsum."
writePlistEntry(theDefaultsDomain, theKey, theValue) --> Write the key/value pair
return (readPlistEntry(theDefaultsDomain, theKey)) --> Read the key/value pair, if possible
(* Subroutines *)
to writePlistEntry(tmpDomain, tmpKey, tmpValue)
try
set theShellScript to ("defaults write " & tmpDomain & " '" & tmpKey & "' '" & tmpValue & "'") --> Note the single-quotes
do shell script theShellScript
return true
end try
return false
end writePlistEntry
to readPlistEntry(tmpDomain, tmpKey)
try
set theShellScript to ("defaults read " & tmpDomain & " '" & tmpKey & "'") --> Note the single-quotes
return ((do shell script theShellScript) as string)
end try
return "Error Reading Plist"
end readPlistEntry
j
Thanks, Jobu. Two very handy handlers - I’ve stored them in my box of tricks.
Translated into VF3K’s problem (without as much checking as I would normally do), we get:
set theDefaultsDomain to "com.SomeName.someText" -- make up a new name here
set theKey to "TextVal.1" --> Can be a string with spaces, as long as the shell script single-quotes it
set theValue to "This file contains the word ChckbxA = false, and a bunch of stuff following it."
writePlistEntry(theDefaultsDomain, theKey, theValue) --> Write the key/value pair
set theAnswer to getWord((readPlistEntry(theDefaultsDomain, theKey))) --> false
to getWord(theText)
set tid to AppleScript's text item delimiters
set AppleScript's text item delimiters to "ChckbxA "
set P to text items of theText
if (count P) = 2 then set P to text item 2 of P -- if count P > 2 then there is more than one ChckbxA
set AppleScript's text item delimiters to tid
return word 2 of P --> "false"
end getWord
to writePlistEntry(tmpDomain, tmpKey, tmpValue)
try
set theShellScript to ("defaults write " & tmpDomain & " '" & tmpKey & "' '" & tmpValue & "'") --> Note the single-quotes
do shell script theShellScript
return true
end try
return false
end writePlistEntry
to readPlistEntry(tmpDomain, tmpKey)
try
set theShellScript to ("defaults read " & tmpDomain & " '" & tmpKey & "'") --> Note the single-quotes
return ((do shell script theShellScript) as string)
end try
return "Error Reading Plist"
end readPlistEntry
Thanks! I’m going to use that in my startup app to see what my prefs are. Anyone interested in seeing my startup app? I’d love some advice on it.
Anyway, I worked on it some more, and although it isn’t a finished product here it is! (I know the experienced scripters will wince)
write_to_file("Startup Initiated")
set currentDate to the current date
set timeStarted to the time of the currentDate
-- Open all apps --
set allApps to {"Quicksilver", "*Mail", "*Stickies", "*MiniBatteryLogger", "Dashboard KickStart", "GrowlHelperApp", "iTunesHelper", "GrowlMenu", "LiteSwitch X", "Alarm Clock", "TapDex", "Picture Switcher", "GrowlTunes", "Ejector"}
repeat with anApp in allApps
if "*" is in anApp then
set HideApp to word 2 of anApp
if "MiniBatteryLogger" is in HideApp then
tell application "MiniBatteryLogger" to activate
tell application "System Events"
tell process "MiniBatteryLogger" to set frontmost to true
click button "Dismiss" of sheet 1 of window "MiniBatteryLogger" of application process "MiniBatteryLogger"
set visible of process "MiniBatteryLogger" to false
end tell
else
tell application HideApp to activate
tell application "System Events" to set visible of process HideApp to false
end if
else
tell application anApp to activate
end if
end repeat
write_to_file("All Apps Opened")
-- Set display brightness --
setBrightness(1)
write_to_file("Brightness set")
-- Set energy saver settings --
setSlpDim("0", "180")
write_to_file("Sleep and dim set")
-- Set Volume based on source
setVolumeifSource("3", "6.5")
write_to_file("Volume set")
-- Display the date and time in a note (Stickied) --
set OnTimeGottenSecs to get_on_time_seconds()
set OnTimeGotten to get_on_time()
if OnTimeGottenSecs ≥ (60 * 5) then
growl_notification("Brushed", "System Notice", "Startup occurred at " & currentDate)
else
growl_notification("Brushed", "System Notice", "Login occurred at " & currentDate)
growl_notification("Brushed", "System Notice", "The computer has been active for " & OnTimeGotten)
end if
-- Set network connections (Airport/Ethernet) --
start airport
enable airport
-- Display IP Address --
try
set myIP to word 25 of (do shell script "curl checkip.dyndns.org")
write_to_file("My IP address is " & myIP)
growl_notification("Brushed", "Internet Connection", "JL's Mac is using the IP " & return & myIP)
on error
set myIP to "No active internet connection"
write_to_file("No active internet connection")
growl_notification("Brushed", "Internet Connection", "There is no active internet connection")
end try
-- Set screen lock ON --
try
tell application "System Preferences"
activate
set current pane to pane "com.apple.preference.security"
tell application "System Events"
tell process "System Preferences"
set frontmost to true
set SecState to value of checkbox "Require password to wake this computer from sleep or screen saver" of window "Security"
my write_to_file("State of comp security = " & SecState)
if value of checkbox "Require password to wake this computer from sleep or screen saver" of window "Security" = 0 then
click checkbox "Require password to wake this computer from sleep or screen saver" of window "Security"
end if
end tell
end tell
quit
end tell
on error errorText1
write_to_file("Error setting security Prefs - " & errorText1)
end try
-- Check for new mail and display dialog if so --
tell application "Mail"
check for new mail
-- Send an email if my IP isn't from home.
if myIP ≠"72.136.59.185" then
set newMessage to make new outgoing message with properties {subject:"JL's Mac Update", content:"IP address has changed to : " & myIP}
tell newMessage
make new to recipient at end of to recipients with properties {name:"Jamie", address:"jamie.lee1@gmail.com"}
end tell
send newMessage
end if
end tell
-- Log running processes
set currentDate1 to the current date
set timeStarted1 to the time of the currentDate1
set startupTimeRunning to timeStarted1 - timeStarted
growl_notification("Brushed", "System Notice", "Startup took " & startupTimeRunning & " seconds")
tell application "System Events" to set allAppsActive to the (name of every process)
set RunningApps to ""
repeat with anApp in allAppsActive
set RunningApps to RunningApps & anApp & ", "
end repeat
write_to_file("Startup Sequence took " & startupTimeRunning & " seconds")
write_to_file("The running apps at startup are: " & RunningApps)
growl_notification("Bezel", "System Notice", "Startup is complete")
write_to_file("Startup Completed" & return & return)
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
-- -- Handlers/Subroutines -- --
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
on setSlpDim(sleep, dim)
do shell script ("pmset sleep " & sleep) password ¬
"wasps365(haply" with administrator privileges
do shell script ("pmset dim " & dim) password ¬
"wasps365(haply" with administrator privileges
end setSlpDim
on write_to_file(this_data)
set currentDate to the current date
set target_file to "JL's Mac:Users:JTL:Startup Log:"
set this_data to (currentDate & " : " & this_data & return) as text
try
set the target_file to the target_file as text
set the open_target_file to ¬
open for access file target_file with write permission
write this_data to the open_target_file starting at eof
close access the open_target_file
return true
on error
try
close access file target_file
end try
return false
end try
end write_to_file
on setBrightness(bValue)
tell application "System Preferences"
activate
set current pane to pane "com.apple.preference.displays"
tell application "System Events"
tell process "System Preferences"
set bValueB4 to value of slider 1 of group 2 of tab group 1 of window 1
my write_to_file("The brightness value = " & bValueB4)
if bValueB4 ≠bValue then
tell slider 1 of group 2 of tab group 1 of window 1 to set value to bValue
end if
end tell
end tell
quit
end tell
end setBrightness
on setVolumeifSource(headphoneVolume, InternalVolume)
tell application "System Preferences"
activate
reveal anchor "output" of pane id ¬
"com.apple.preference.sound"
tell application "System Events" to tell process "System Preferences" to set S to value of text field 1 of row 1 of table 1 of scroll area 1 of tab group 1 of window "Sound"
quit
end tell
if S = "Internal Speakers" then tell application "Finder" to set volume InternalVolume
if S = "Headphones" then tell application "Finder" to set volume headphoneVolume
end setVolumeifSource
(*on growl_registration(AllNotifications, AppToRegister)
tell application "GrowlHelperApp"
register as application AppToRegister ¬
all notifications AllNotifications ¬
default notifications AllNotifications ¬
icon of application "Finder"
end tell
end growl_registration*)
on growl_notification(_name, _title, _description)
tell application "GrowlHelperApp"
notify with name _name ¬
title _title ¬
description _description ¬
application name "Login Application"
end tell
end growl_notification
on get_on_time()
set t to GetMilliSec
set hh to t div (3600.0 * 1000.0)
set t to t - hh * (3600.0 * 1000.0)
set mm to t div (60.0 * 1000.0)
set t to t - mm * (60.0 * 1000.0)
set ss to t / 1000.0
hh & ":" & mm & ":" & ss & " since boot" as string
end get_on_time
on get_on_time_seconds()
set t to GetMilliSec
set hh to t div (3600.0 * 1000.0)
set t to t - hh * (3600.0 * 1000.0)
set mm to t div (60.0 * 1000.0)
set t to t - mm * (60.0 * 1000.0)
set ss to t / 1000.0
hh & ":" & mm & ":" & ss & " since boot" as string
set totalSeconds to ((hh * 60 * 60) + (mm * 60) + (ss)) as integer
return totalSeconds
end get_on_time_seconds
P.S. Some of this is from the forum, thanks to all of the AMAZING scripting minds out there.