Add notes field

Add notes field

(*
	Log Page - Log categorized web page bookmarks to a text file

	Version: @@VERSION@@
	Date:    2011-03-14
	Author:  Steve Wheeler

	Get the title, URL, current date and time, and a user-definable
	category for the frontmost Safari window and log the info to a text
	file.

	This program is free software available under the terms of a
	BSD-style (3-clause) open source license detailed below.
*)

(*
Copyright (c) 2011 Steve Wheeler
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)

(*
	TODO: Change the following local-only config before any public release.
	The log file should be: $GTD_IN/logs/urls/urls.YYYY.txt
	Or just: $GTD_IN/logs/urls.txt

	TODO: The edit_log() function is currently incomplete. It will only launch
	an editor from the shell and only if that editor is a GUI editor (in this
	case, MacVim). If I release this script publicly, I will still need to
	implement funtionality to launch a GUI editor normally (with the 'open'
	AppleScript commmand) as well as a command-line editor run in the Terminal.
*)

property script_name : "Log Page"
property script_version : "@@VERSION@@"

---------- USER CONFIGURATION ----------------------------------------
-- Default log directory to use if one is not read from config file:
--set log_dir to POSIX path of (path to application support folder from user domain) & "Jazzhead/Log Page/"
set log_dir to POSIX path of (path to desktop folder) & "Log Page/" -- :DEBUG:

-- Log file name:
set log_name to "urls.txt"

-- Default categories/labels if none are found in (or there is no)
-- URL file. Modify as desired:
set default_cats to "Development
Development:AppleScript
Development:AppleScript:Mail
Design
Productivity:GTD
Apple:Mac OS X
Apple:iOS
Career
Education
Health
Health:Diet
Health:Fitness
General"

-- Text editor to use if manually editing the log file.
--
-- This example:
--	1. Opens the file using MacVim ('mvim' as installed by MacPorts)
--	2. Switches the local working directory for just that buffer to the
--	    directory containing the file ('lcd')
--	3. Gives the MacVim window a name ('--servername').
--
set text_editor to "/opt/local/bin/mvim \"+lcd %:p:h\" --servername LOG_PAGE"

-- Should the specified editor be launched from the unix shell?
set should_use_shell to true
---------- END User Configuration ----------------------------------------

---------- ADVANCED (EXPERIMENTAL) ---------------------------------------------
-- For advanced users familiar with the command-line, override the default log
-- directory path. This probably won't be in a public release.
--
-- Grab an exported shell environment variable from a config file to use as the
-- log directory path. For this example, I have a "~/.gtdrc" config file that I
-- source from my "~/.bash_profile" file so that it exportss environment
-- variables relating to my GTD system. That makes those variables available to
-- any of the shell scripts and tools that I use. For instance, when I'm
-- editing files in Vim, I can write paths to other files using one of the
-- environment variables rather than a full or relative path and the 'gf'
-- command will work for jumping to that file. The config file looks like this:
--
--         # ~/.gtdrc
--         #
--         # File locations for GTD documents
--
--         export GTD_DIR=$HOME/Documents/org  # GTD root directory
--         export GTD_IN=$GTD_DIR/content      # source/input files
--         export GTD_OUT=$GTD_DIR/html        # generated HTML output files
--         export GTD_LIB=$GTD_DIR/lib         # code library files
--         export GTD_BIN=$GTD_LIB/script      # scripts
--
-- Remove (or comment out) the "(*" and "*)" comment markers below to use this
-- section. Make sure you also configure the two variables for your system.
--(*
--------------- USER CONFIGURATION ----------
-- Path to your config file:
set cfg_file to POSIX path of (path to home folder) & ".gtdrc"
-- The environment variable you're interested in:
set env_var to "GTD_IN"
--------------- END User Configuration ---------

-- Check for environment variable in config file:
set s to "egrep '\\<" & env_var & "=' " & quoted form of cfg_file &
	" > /dev/null 2>&1; echo $?"
set shell_status to (do shell script s) as integer
-- Source the config file and echo the desired variable:
if shell_status is 0 then -- (means that grep found a match)
	set s to ". " & quoted form of cfg_file & " && echo $" & env_var
	set gtd_in_dir to do shell script s
	set log_dir to gtd_in_dir & "/logs/"

	--------------------
	-- OPTIONAL: Override the Text editor to integrate with my GTD system.
	--
	-- This example:
	--	1. Opens the file using MacVim ('mvim' as installed by MacPorts)
	--	2. Switches the local working directory ('lcd') for just that buffer to
	--	    my GTD content directory ($GTD_IN after escaping potential spaces)
	--	3. Gives the MacVim window a name ('--servername').

	----- First, escape any potential spaces in the directory path:
	--
	--set gtd_in_dir to gtd_in_dir & " foo    bar" -- :DEBUG: spaces in path
	--
	set s to "echo " & quoted form of gtd_in_dir & " | sed 's/ \\{1,\\}/\\\\ /g'" -- escape spaces
	set gtd_in_dir to do shell script s
	--
	--log gtd_in_dir -- :DEBUG: need to use 'log' to see the value w/o AppleScript escapes

	----- Finally, set the editor with all of the options:
	--
	set text_editor to "/opt/local/bin/mvim \"+lcd " & gtd_in_dir & "\" --servername GTD --remote-silent"
	--
	--log text_editor -- :DEBUG:
	--return text_editor -- :DEBUG:
	--------------------
end if
---------- END Advanced --------------------------------------------------------
--*)

--return log_dir -- :DEBUG:

--
-- Get URL and title from front browser window
--
tell application "Safari"
	--activate
	try
		set this_url to URL of front document
		set this_title to name of first tab of front window whose visible is true
	on error
		return false
	end try
end tell
-- Transliterate non-ASCII characters to ASCII
set this_title to convert_to_ascii(this_title)

--return this_title -- :DEBUG:

--
-- Format the record separator between log entries
--
set rule_char to "-"
set rule_width to 80
set field_width to 7
set field_sep to " | "
set rec_sep to "" & multiply_text(rule_char, field_width - 1) &
	"+" & multiply_text(rule_char, rule_width - field_width)

--
-- Format date-time string as "YYYY-MM-DD HH:MM:SS"
--
set {year:y, month:m, day:d, hours:hh, minutes:mm, seconds:ss} to current date
set m to m as integer -- coerce month string
-- Pad numbers with leading zeros:
set tmp_list to {}
repeat with this_item in {m, d, hh, mm, ss}
	set this_item to text 2 thru -1 of (100 + this_item as text)
	set end of tmp_list to this_item
end repeat
set {m, d, hh, mm, ss} to tmp_list
-- Final string:
set date_time to join_list({y, m, d}, "-") & " " & join_list({hh, mm, ss}, ":")

-- Log file name
--set log_name to "urls." & y & ".txt"

--
-- Create log directory if it doesn't already exist. (Go ahead and use a shell
-- command since it's easy to create intermediate directories all in one step.):
--
try
	set s to "mkdir -pm700 " & quoted form of log_dir
	do shell script s
on error err_msg number err_num
	error "Can't create log directory: " & err_msg number err_num
	return "Fatal Error: Can't create log directory"
end try

set log_file_posix to "" & log_dir & log_name
set log_file to POSIX file log_file_posix

--
-- Add header to new or empty log file
--
set should_init to false
tell application "Finder"
	if (not (exists log_file)) or (_IO's read_file(log_file) is "") then
		set should_init to true
	end if
end tell

set head_sep to multiply_text("#", 80)
if should_init then
	set file_header to head_sep & "
# urls.txt - Timestamped and categorized URL archive
# ==================================================
# Optionally list some categories/labels of URLs below that might not yet
# be used. Any categories/lables listed here or in the web page records
# will be presented as a list to select from when saving new URLs.
" & head_sep & linefeed & default_cats & linefeed & head_sep & "
# END: category/label list
" & head_sep & linefeed
	tell _IO to write_file(log_file, file_header)
	set cat_txt to default_cats
else
	-- Read categories from file
	(*
		:TODO: Error handling.
	*)
	set cat_txt to text 2 thru -2 of (item 3 of split_text(_IO's read_file(log_file), head_sep))
end if

-- Parse any existing labels from the "Label" fields of the URLs file:
set s to "egrep '^Label ' " & quoted form of log_file_posix &
	" | sed 's/^Label | //' | sort | uniq"
--return s
set used_cats to do shell script s without altering line endings
-- Sort those along with the manually entered categories/labels:
set s to "echo \"" & cat_txt & linefeed & used_cats & "\" | egrep -v '^$' | sort | uniq"
set cat_txt to do shell script s
-- Coerce the lines into a list:
set cat_list to paragraphs of cat_txt
--return cat_list -- :DEBUG:

--
-- Prompt for category/subcategory of URL
--

-- Select an existing category
set t to "" & script_name & " (1/3)"
set m to "Please select a category for the URL you want to log. You will have a chance to edit your choice."
set cat_choice to choose from list cat_list with title t with prompt m OK button name "Select"
--if cat_choice is false then return false
if cat_choice is false then set cat_choice to "Please enter a category..."

-- Modify or enter a new category
set b to {"Cancel", "Manually Edit Log File", "Append URL to Log File..."}
set t to "" & script_name & " (2/3)"
set m to "To log the URL for:" & return & return
	& tab & "\"" & this_title & "\"" & return & return &
	"please provide a category and any optional subcategories (or edit your selected category) for the URL. Example: \"Development:AppleScript:Mail\""
display dialog m default answer cat_choice with title t buttons b default button last item of b
set {this_label, btn_pressed} to {text returned of result, button returned of result}

-- Optionally add note
if btn_pressed is last item of b then
	set last item of b to "Append URL to Log File"
	set t to "" & script_name & " (3/3)"
	set m to "Optionally add a short note. Just leave the field blank if you don't want to add a note."
	display dialog m default answer "" with title t buttons b default button last item of b
	set {this_note, btn_pressed} to {text returned of result, button returned of result}
end if

--
-- Append or edit the log file
--
if btn_pressed is last item of b then
	set final_text to join_list({
		"Date " & field_sep & date_time,
		"Label" & field_sep & this_label,
		"Title" & field_sep & this_title,
		"URL  " & field_sep & this_url}, linefeed) & linefeed
	if this_note is not "" then
		set final_text to final_text & "Note " & field_sep & this_note & linefeed
	end if
	set final_text to final_text & rec_sep & linefeed
	--return "[DEBUG]" & return & final_text
	_IO's append_file(log_file, final_text)
else
	if should_use_shell then
		set this_log_file to quoted form of log_file_posix
	else
		set this_log_file to log_file
	end if
	edit_log(this_log_file, text_editor, should_use_shell)
end if

--display alert "Log Page" message "DEBUG: Script complete."

(************************************************************
 *	Subroutines
 ************************************************************)

-- ===== Main Functions =====

on edit_log(log_file, text_editor, should_use_shell)
	(*
		TODO:MAYBE:
		Have a configuration variable in the main script to specify which text
		editor to use. Have another variable for configuring whether or not
		it's a GUI application. Then this function would use 'open' to launch a
		GUI app or script the Terminal to launch a command-line editor.
		Optionally use 'do shell script' to launch a compatible GUI app from a
		command line (so that the working directory can be changed to that of
		the file first), but I don't know if that will really be necessary
		since I have a Vim shortcut for quickly changing the working directory
		if need be.
	*)
	if should_use_shell then
		set s to text_editor & space & log_file & space & "> /dev/null 2>&1"
		do shell script s
		return
	else
		set t to script_name
		set m to ":TODO: edit_log() function: use non-shell-invoked editor."
		set b to {"Cancel"}
		display alert t message m buttons b cancel button 1 as critical
		return false
	end if
end edit_log

-- ===== Utility Functions =====

on convert_to_ascii(non_ascii_txt)
	set s to "iconv -f UTF-8 -t US-ASCII//TRANSLIT <<<" & quoted form of non_ascii_txt
	do shell script s
end convert_to_ascii

on multiply_text(str, n)
	if n < 1 or str = "" then return ""
	set lst to {}
	repeat n times
		set end of lst to str
	end repeat
	return lst as string
end multiply_text

on split_text(txt, delim)
	set old_tids to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to (delim as string)
		set lst to every text item of (txt as string)
		set AppleScript's text item delimiters to old_tids
		return lst
	on error err_msg number err_num
		set AppleScript's text item delimiters to old_tids
		error "Can't split_text(): " & err_msg number err_num
	end try
end split_text

on join_list(lst, delim)
	set old_tids to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to (delim as string)
		set txt to lst as string
		set AppleScript's text item delimiters to old_tids
		return txt
	on error err_msg number err_num
		set AppleScript's text item delimiters to old_tids
		error "Can't join_list(): " & err_msg number err_num
	end try
end join_list

(************************************************************
 *	Script Objects
 ************************************************************)

script _IO

	(* == PUBLIC == *)

	on write_file(file_path, this_data)
		_write_file(file_path, this_data, string, false) -- overwrite existing file
	end write_file

	on append_file(file_path, this_data)
		_write_file(file_path, this_data, string, true) -- append new data to end of existing file
	end append_file

	on read_file(file_path)
		_read_file(file_path, string)
	end read_file

	(* == PRIVATE == *)

	on _write_file(file_path, this_data, data_class, should_append_data)
		try
			set file_path to file_path as text
			set file_handle to
				open for access file file_path with write permission
			if not should_append_data then
				set eof of the file_handle to 0
			write this_data as data_class to file_handle starting at eof
			close access file_handle
			return true
		on error err_msg number err_num
			try
				close access file file_path
			end try
			error err_msg number err_num
			return false
		end try
	end _write_file

	on _read_file(file_path, data_class)
		try
			set file_path to file_path as text
			if (get eof file file_path) is 0 then
				set file_contents to ""
			else
				set file_contents to read file file_path as data_class
			end if
			return file_contents
		on error
			return 0
		end try
	end _read_file
end script

(*
	Log Page - Log categorized web page bookmarks to a text file

	Version: @@VERSION@@
	Date:    2011-02-09
	Author:  Steve Wheeler

	Get the title, URL, current date and time, and a user-definable
	category for the frontmost Safari window and log the info to a text
	file.

	This program is free software available under the terms of a
	BSD-style (3-clause) open source license detailed below.
*)

(*
Copyright (c) 2011 Steve Wheeler
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*)

(*
	TODO: Change the following local-only config before any public release.
	The log file should be: $GTD_IN/logs/urls/urls.YYYY.txt
	Or just: $GTD_IN/logs/urls.txt

	TODO: The edit_log() function is currently incomplete. It will only launch
	an editor from the shell and only if that editor is a GUI editor (in this
	case, MacVim). If I release this script publicly, I will still need to
	implement funtionality to launch a GUI editor normally (with the 'open'
	AppleScript commmand) as well as a command-line editor run in the Terminal.
*)

property script_name : "Log Page"
property script_version : "@@VERSION@@"

---------- USER CONFIGURATION ----------------------------------------
-- Default log directory to use if one is not read from config file:
--set log_dir to POSIX path of (path to application support folder from user domain) & "Jazzhead/Log Page/"
set log_dir to POSIX path of (path to desktop folder) & "Log Page/" -- :DEBUG:

-- Log file name:
set log_name to "urls.txt"

-- Default categories/labels if none are found in (or there is no)
-- URL file. Modify as desired:
set default_cats to "Development
Development:AppleScript
Development:AppleScript:Mail
Design
Productivity:GTD
Apple:Mac OS X
Apple:iOS
Career
Education
Health
Health:Diet
Health:Fitness
General"

-- Text editor to use if manually editing the log file.
--
-- This example:
--	1. Opens the file using MacVim ('mvim' as installed by MacPorts)
--	2. Switches the local working directory for just that buffer to the
--	    directory containing the file ('lcd')
--	3. Gives the MacVim window a name ('--servername').
--
set text_editor to "/opt/local/bin/mvim \"+lcd %:p:h\" --servername LOG_PAGE"

-- Should the specified editor be launched from the unix shell?
set should_use_shell to true
---------- END User Configuration ----------------------------------------

---------- ADVANCED (EXPERIMENTAL) ---------------------------------------------
-- For advanced users familiar with the command-line, override the default log
-- directory path. This probably won't be in a public release.
--
-- Grab an exported shell environment variable from a config file to use as the
-- log directory path. For this example, I have a "~/.gtdrc" config file that I
-- source from my "~/.bash_profile" file so that it exportss environment
-- variables relating to my GTD system. That makes those variables available to
-- any of the shell scripts and tools that I use. For instance, when I'm
-- editing files in Vim, I can write paths to other files using one of the
-- environment variables rather than a full or relative path and the 'gf'
-- command will work for jumping to that file. The config file looks like this:
--
--         # ~/.gtdrc
--         #
--         # File locations for GTD documents
--
--         export GTD_DIR=$HOME/Documents/org  # GTD root directory
--         export GTD_IN=$GTD_DIR/content      # source/input files
--         export GTD_OUT=$GTD_DIR/html        # generated HTML output files
--         export GTD_LIB=$GTD_DIR/lib         # code library files
--         export GTD_BIN=$GTD_LIB/script      # scripts
--
-- Remove (or comment out) the "(*" and "*)" comment markers below to use this
-- section. Make sure you also configure the two variables for your system.
--(*
--------------- USER CONFIGURATION ----------
-- Path to your config file:
set cfg_file to POSIX path of (path to home folder) & ".gtdrc"
-- The environment variable you're interested in:
set env_var to "GTD_IN"
--------------- END User Configuration ---------

-- Check for environment variable in config file:
set s to "egrep '\\<" & env_var & "=' " & quoted form of cfg_file &
	" > /dev/null 2>&1; echo $?"
set shell_status to (do shell script s) as integer
-- Source the config file and echo the desired variable:
if shell_status is 0 then -- (means that grep found a match)
	set s to ". " & quoted form of cfg_file & " && echo $" & env_var
	set gtd_in_dir to do shell script s
	set log_dir to gtd_in_dir & "/logs/"

	--------------------
	-- OPTIONAL: Override the Text editor to integrate with my GTD system.
	--
	-- This example:
	--	1. Opens the file using MacVim ('mvim' as installed by MacPorts)
	--	2. Switches the local working directory ('lcd') for just that buffer to
	--	    my GTD content directory ($GTD_IN after escaping potential spaces)
	--	3. Gives the MacVim window a name ('--servername').

	----- First, escape any potential spaces in the directory path:
	--
	--set gtd_in_dir to gtd_in_dir & " foo    bar" -- :DEBUG: spaces in path
	--
	set s to "echo " & quoted form of gtd_in_dir & " | sed 's/ \\{1,\\}/\\\\ /g'" -- escape spaces
	set gtd_in_dir to do shell script s
	--
	--log gtd_in_dir -- :DEBUG: need to use 'log' to see the value w/o AppleScript escapes

	----- Finally, set the editor with all of the options:
	--
	set text_editor to "/opt/local/bin/mvim \"+lcd " & gtd_in_dir & "\" --servername GTD --remote-silent"
	--
	--log text_editor -- :DEBUG:
	--return text_editor -- :DEBUG:
	--------------------
end if
---------- END Advanced --------------------------------------------------------
--*)

--return log_dir -- :DEBUG:

--
-- Get URL and title from front browser window
--
tell application "Safari"
	--activate
	try
		set this_url to URL of front document
		set this_title to name of first tab of front window whose visible is true
	on error
		return false
	end try
end tell
-- Transliterate non-ASCII characters to ASCII
set this_title to convert_to_ascii(this_title)

--return this_title -- :DEBUG:

--
-- Format the record separator between log entries
--
set rule_char to "-"
set rule_width to 80
set field_width to 7
set field_sep to " | "
set rec_sep to "" & multiply_text(rule_char, field_width - 1) &
	"+" & multiply_text(rule_char, rule_width - field_width)

--
-- Format date-time string as "YYYY-MM-DD HH:MM:SS"
--
set {year:y, month:m, day:d, hours:hh, minutes:mm, seconds:ss} to current date
set m to m as integer -- coerce month string
-- Pad numbers with leading zeros:
set tmp_list to {}
repeat with this_item in {m, d, hh, mm, ss}
	set this_item to text 2 thru -1 of (100 + this_item as text)
	set end of tmp_list to this_item
end repeat
set {m, d, hh, mm, ss} to tmp_list
-- Final string:
set date_time to join_list({y, m, d}, "-") & " " & join_list({hh, mm, ss}, ":")

-- Log file name
--set log_name to "urls." & y & ".txt"

--
-- Create log directory if it doesn't already exist. (Go ahead and use a shell
-- command since it's easy to create intermediate directories all in one step.):
--
try
	set s to "mkdir -pm700 " & quoted form of log_dir
	do shell script s
on error err_msg number err_num
	error "Can't create log directory: " & err_msg number err_num
	return "Fatal Error: Can't create log directory"
end try

set log_file_posix to "" & log_dir & log_name
set log_file to POSIX file log_file_posix

--
-- Add header to new or empty log file
--
set should_init to false
tell application "Finder"
	if (not (exists log_file)) or (_IO's read_file(log_file) is "") then
		set should_init to true
	end if
end tell

set head_sep to multiply_text("#", 80)
if should_init then
	set file_header to head_sep & "
# urls.txt - Timestamped and categorized URL archive
# ==================================================
# Optionally list some categories/labels of URLs below that might not yet
# be used. Any categories/lables listed here or in the web page records
# will be presented as a list to select from when saving new URLs.
" & head_sep & linefeed & default_cats & linefeed & head_sep & "
# END: category/label list
" & head_sep & linefeed
	tell _IO to write_file(log_file, file_header)
	set cat_txt to default_cats
else
	-- Read categories from file
	(*
		:TODO: Error handling.
	*)
	set cat_txt to text 2 thru -2 of (item 3 of split_text(_IO's read_file(log_file), head_sep))
end if

-- Parse any existing labels from the "Label" fields of the URLs file:
set s to "egrep '^Label ' " & quoted form of log_file_posix &
	" | sed 's/^Label | //' | sort | uniq"
--return s
set used_cats to do shell script s without altering line endings
-- Sort those along with the manually entered categories/labels:
set s to "echo \"" & cat_txt & linefeed & used_cats & "\" | egrep -v '^$' | sort | uniq"
set cat_txt to do shell script s
-- Coerce the lines into a list:
set cat_list to paragraphs of cat_txt
--return cat_list -- :DEBUG:

--
-- Prompt for category/subcategory of URL
--

-- Select an existing category
set msg to "Please select a category for the URL you want to log. You will have a chance to edit your choice."
set cat_choice to choose from list cat_list with title script_name with prompt msg OK button name "Select"
--if cat_choice is false then return false
if cat_choice is false then set cat_choice to "Please enter a category..."

-- Modify or enter a new category
set btns to {"Cancel", "Manually Edit Log File", "Append URL to Log File"}
set msg to "To log the URL for:" & return & return
	& tab & "\"" & this_title & "\"" & return & return &
	"please provide a category and any optional subcategories (or edit your selected category) for the URL. Example: \"Development:AppleScript:Mail\""
display dialog msg default answer cat_choice with title script_name buttons btns default button last item of btns
set {this_label, btn_pressed} to {text returned of result, button returned of result}

--
-- Append or edit the log file
--
if btn_pressed is last item of btns then
	set final_text to join_list({
		"Date " & field_sep & date_time,
		"Label" & field_sep & this_label,
		"Title" & field_sep & this_title,
		"URL  " & field_sep & this_url,
		rec_sep}, linefeed) & linefeed
	_IO's append_file(log_file, final_text)
else
	if should_use_shell then
		set this_log_file to quoted form of log_file_posix
	else
		set this_log_file to log_file
	end if
	edit_log(this_log_file, text_editor, should_use_shell)
end if

--display alert "Log Page" message "DEBUG: Script complete."

(************************************************************
 *	Subroutines
 ************************************************************)

-- ===== Main Functions =====

on edit_log(log_file, text_editor, should_use_shell)
	(*
		TODO:MAYBE:
		Have a configuration variable in the main script to specify which text
		editor to use. Have another variable for configuring whether or not
		it's a GUI application. Then this function would use 'open' to launch a
		GUI app or script the Terminal to launch a command-line editor.
		Optionally use 'do shell script' to launch a compatible GUI app from a
		command line (so that the working directory can be changed to that of
		the file first), but I don't know if that will really be necessary
		since I have a Vim shortcut for quickly changing the working directory
		if need be.
	*)
	if should_use_shell then
		set s to text_editor & space & log_file & space & "> /dev/null 2>&1"
		do shell script s
		return
	else
		set t to script_name
		set m to ":TODO: edit_log() function: use non-shell-invoked editor."
		set b to {"Cancel"}
		display alert t message m buttons b cancel button 1 as critical
		return false
	end if
end edit_log

-- ===== Utility Functions =====

on convert_to_ascii(non_ascii_txt)
	set s to "iconv -f UTF-8 -t US-ASCII//TRANSLIT <<<" & quoted form of non_ascii_txt
	do shell script s
end convert_to_ascii

on multiply_text(str, n)
	if n < 1 or str = "" then return ""
	set lst to {}
	repeat n times
		set end of lst to str
	end repeat
	return lst as string
end multiply_text

on split_text(txt, delim)
	set old_tids to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to (delim as string)
		set lst to every text item of (txt as string)
		set AppleScript's text item delimiters to old_tids
		return lst
	on error err_msg number err_num
		set AppleScript's text item delimiters to old_tids
		error "Can't split_text(): " & err_msg number err_num
	end try
end split_text

on join_list(lst, delim)
	set old_tids to AppleScript's text item delimiters
	try
		set AppleScript's text item delimiters to (delim as string)
		set txt to lst as string
		set AppleScript's text item delimiters to old_tids
		return txt
	on error err_msg number err_num
		set AppleScript's text item delimiters to old_tids
		error "Can't join_list(): " & err_msg number err_num
	end try
end join_list

(************************************************************
 *	Script Objects
 ************************************************************)

script _IO

	(* == PUBLIC == *)

	on write_file(file_path, this_data)
		_write_file(file_path, this_data, string, false) -- overwrite existing file
	end write_file

	on append_file(file_path, this_data)
		_write_file(file_path, this_data, string, true) -- append new data to end of existing file
	end append_file

	on read_file(file_path)
		_read_file(file_path, string)
	end read_file

	(* == PRIVATE == *)

	on _write_file(file_path, this_data, data_class, should_append_data)
		try
			set file_path to file_path as text
			set file_handle to
				open for access file file_path with write permission
			if not should_append_data then
				set eof of the file_handle to 0
			write this_data as data_class to file_handle starting at eof
			close access file_handle
			return true
		on error err_msg number err_num
			try
				close access file file_path
			end try
			error err_msg number err_num
			return false
		end try
	end _write_file

	on _read_file(file_path, data_class)
		try
			set file_path to file_path as text
			if (get eof file file_path) is 0 then
				set file_contents to ""
			else
				set file_contents to read file file_path as data_class
			end if
			return file_contents
		on error
			return 0
		end try
	end _read_file
end script


committed on 2015/12/13 19:00.

committed on 2015/12/13 19:00.

// Backup will be saved under ~/Library/Containers/com.apple.TextEdit/Data .

// config
var html = true;
var file = "note" + Date.now();
var data = "";

var dumpNote = function(note) {

  var text = "";
  var title = note.name();
  var body = note.body();

  if(html) {
    text = "
" + title + "
" + "\n" + body + "\n";
  } else {
    text = "Title: " + title + "\n" + "Body: " + body + "\n";
  }

  data = data + text;

}

var dumpFolder = function(folder) {

  var text = "";
  var name = folder.name();

  if(html) {
    text = "
" + name + "
" + "\n";
  } else {
    text = "Folder: " + name + "\n";
  }

  data = data + text;

  folder.notes().forEach(dumpNote);

}

var dumpAccount = function(account) {

  var text = "";
  var name = account.name();

  if(html) {
    text = "
" + name + "
" + "\n";
  } else {
    text = "Account: : " + name + "\n";
  }

  data = data + text

  var folders = account.folders();
  folders.forEach(dumpFolder);

}

var output = function() {

  if(html) {
    name = file + ".html";
  } else {
    name = file + ".text";
  }

  var app = Application("TextEdit");
  app.Document().make().name = name;

  doc = app.documents().find(function(el) {
          if(el.name() == name ) { return true }
        })

  doc.text = data;

  doc.close();

}

var main = function() {

  var account = Application("Notes").accounts();
  account.forEach(dumpAccount);

  output();

}

main()

// Backup will be saved under ~/Library/Containers/com.apple.TextEdit/Data .

// config
var html = true;
var file = "note" + Date();
var data = "";

var dumpNote = function(note) {

  var text = "";
  var title = note.name();
  var body = note.body();

  if(html) {
    text = "
" + title + "
" + "\n" + body + "\n";
  } else {
    text = "Title: " + title + "\n" + "Body: " + body + "\n";
  }

  data = data + text;

}

var dumpFolder = function(folder) {

  var text = "";
  var name = folder.name();

  if(html) {
    text = "
" + name + "
" + "\n";
  } else {
    text = "Folder: " + name + "\n";
  }

  data = data + text;

  folder.notes().forEach(dumpNote);

}

var dumpAccount = function(account) {

  var text = "";
  var name = account.name();

  if(html) {
    text = "
" + name + "
" + "\n";
  } else {
    text = "Account: : " + name + "\n";
  }

  data = data + text

  var folders = account.folders();
  folders.forEach(dumpFolder);

}

var output = function() {

  if(html) {
    name = file + ".html";
  } else {
    name = file + ".text";
  }

  var app = Application("TextEdit");
  app.Document().make().name = name;

  doc = app.documents().find(function(el) {
          if(el.name() == name ) { return true }
        })

  doc.text = data;

  doc.close();

}

var main = function() {

  var account = Application("Notes").accounts();
  account.forEach(dumpAccount);

  output();

}

main()


Add applescript to get CompuCell to run automatically on a mac


moveForMon.applescript, from darwin13

moveForMon.applescript, from darwin13

property DEF_ALL : false
property DEF_DEBUG_LEVEL : 1

on moveForMon(pars)

	set {all, debug_level} to {DEF_ALL, DEF_DEBUG_LEVEL}
	try
		set all to all of pars
	end try
	try
		set debug_level to debug_level of pars
	end try

	-- debug mode
	if debug_level > 0 then
		log "debug mode = " & debug_level
		if debug_level > 1 then
			display dialog "debug mode = " & debug_level
		end if
	end if

	-- set monitoring tools' positions
	-- SimpleFloatingClock
	set w_sfcCEST to 1
	set w_sfcJST to 2

	-- XRG
	set w_XRG to 1

	-- set monitoring tool's name
	-- GeekTool
	set s_gtCal to "gcalCal"
	set s_gtGcal to "gcalList"
	set s_gtTask to "gtasklist"
	set s_gtPs to "myps"

	-- x posiiotn for monitoring
	set ledge to -160
	set ledgeSFCoffset to 20

	-- y positions
	set y_sfcCEST to 30
	set y_sfcJST to y_sfcCEST + 100
	set y_gtCal to y_sfcJST + 105
	set y_gtGcal to y_gtCal + 115
	set y_gtTask to y_gtGcal + 175
	set y_gtPs to y_gtTask + 85
	set y_XRG to y_gtPs + 75

	-- app to be excepted
	set expApp to {"XRG"}

	-- app to be half size, in left monitor (0.7 times full)
	set halfSizeApp_L to {}

	-- app to be half size, in right monitor (0.7 times full)
	set halfSizeApp_R to {"AdobeReader"}

	-- app only to be moved, in left monitor
	set noResizeApp_L to {}

	-- app only to be moved, in right monitor
	set noResizeApp_R to {"Finder", "Skype", "Microsoft Word", "Microsoft Excel", "Microsoft PowerPoint"}

	-- app to be moved left
	set app_L to {"firefox", "Evernote", "thunderbird", "thunderbird-bin", "Mail"}

	-- app to be moved right
	set app_R to {"iTerm"}

	-- get screen size
	tell application "Finder"
		set scriptPath to (path to me)'s folder as text
	end tell
	set windowSizeScpt to scriptPath & "windowSize.scpt"
	set windowSize to load script file windowSizeScpt

	-- main screen
	set svs to windowSize's getVisibleFrame(1, 1) --+1 is used to avoid edge, especially needed for y position
	set dPosX to (item 1 of svs) + 1
	set dPosY to (item 2 of svs) + 1
	set dWidth to item 3 of svs
	set dHeight to item 4 of svs

	-- try to get left screen
	set dPosX_L to dPosX + 1
	set dPosY_L to dPosY + 1
	try
		set svsL to windowSize's getVisibleFrame(-1, 1)
		set dPosX_L to (item 1 of svsL) + 1
		set dPosY_L to (item 2 of svsL) + 1
	end try

	-- try to get right screen
	set dPosX_R to dPosX + 1
	set dPosY_R to dPosY + 1
	try
		set svsR to windowSize's getVisibleFrame(dPosX + dWidth + 1, 1)
		set dPosX_R to (item 1 of svsR) + 1
		set dPosY_R to (item 2 of svsR) + 1
	end try

	-- move monitoring tools
	if dPosX_L < 0 then
		if debug_level > 0 then
			log "ledge to ledgeDual"
		end if
	else
		set ledge to dWidth + ledge
		if debug_level > 0 then
			log "ledge to ledgeSingle"
		end if
	end if

	tell application "System Events"
		-- SimpleFloatingClock
		try
			set appName to "SimpleFloatingClock"
			tell process appName
				tell window w_sfcCEST
					set size to {1000, 1000}
					set position to {ledge + ledgeSFCoffset, y_sfcCEST}
				end tell
				tell window w_sfcJST
					set size to {1000, 1000}
					set position to {ledge + ledgeSFCoffset, y_sfcJST}
				end tell
			end tell
		end try

		---- GeekTool
		--try
		--	--set appName to "GeekTool"
		--	set appName to "GeekTool Helper" -- for GeekTool 3
		--
		--	tell process appName
		--		set nW to number of windows
		--		--display dialog appName & " in process, nWindows=" & nW
		--		tell window w_gtCal
		--		end tell
		--		tell window w_gtGcal
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtGcal}
		--		end tell
		--		tell window w_gtTask
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtTask}
		--		end tell
		--		tell window w_gtPs
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtPs}
		--		end tell
		--	end tell
		--	--on error errMsg
		--	--	display dialog "ERROR: " & errMsg
		--end try

		-- XRG
		try
			set appName to "XRG"
			tell process appName
				tell window w_XRG
					set size to {1000, 2000}
					set position to {ledge, y_XRG}
				end tell
			end tell
		end try
	end tell

	-- GeekTool (should be outside of application "System Events", and use application "GeekTool Helper" ?)
	-- can't use position to geeklets
	tell application "GeekTool Helper" -- can not use appName (variable), which shows error at id?
		--geeklets
		repeat with g in every «class gLet»
			tell g
				name
				if name is s_gtCal then
					set «class xpos» to ledge
					set «class ypos» to y_gtCal
				else if name is s_gtGcal then
					set «class xpos» to ledge
					set «class ypos» to y_gtGcal
				else if name is s_gtTask then
					set «class xpos» to ledge
					set «class ypos» to y_gtTask
				else if name is s_gtPs then
					set «class xpos» to ledge
					set «class ypos» to y_gtPs
				end if
			end tell
		end repeat
	end tell

	-- Move/Resize other windows
	if all then
		-- get application name
		tell application "System Events"
			set appList to (get name of every application process whose visible is true)
		end tell

		-- repeat for all app
		repeat with appName in appList
			if appName is not in expApp then
				tell application "System Events"
					try
						tell process appName
							set nW to number of windows
							repeat with i from 1 to nW
								if debug_level > 0 then
									log appName & " " & i
									if debug_level > 1 then
										display dialog appName & " " & i
									end if
								end if
								if appName is in halfSizeApp_L then
									if debug_level > 0 then
										log "half size left"
										if debug_level > 1 then
											display dialog "half size left"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, xsize:0.7, ysize:0.7, moveForMon:false, debug_level:debug_level})
								else if appName is in halfSizeApp_R then
									if debug_level > 0 then
										log "half size right"
										if debug_level > 1 then
											display dialog "half size right"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, xsize:0.7, ysize:0.7, moveForMon:false, debug_level:debug_level})
								else if appName is in noResizeApp_L then
									if debug_level > 0 then
										log "half size left"
										if debug_level > 1 then
											display dialog "half size left"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, resize:0, moveForMon:false, debug_level:debug_level})
								else if appName is in noResizeApp_R then
									if debug_level > 0 then
										log "move right"
										if debug_level > 1 then
											display dialog "move right"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, resize:0, moveForMon:false, debug_level:debug_level})
								else if appName is in app_L then
									if debug_level > 0 then
										log "move left full size"
										if debug_level > 1 then
											display dialog "move left full size"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, moveForMon:false, debug_level:debug_level})
								else if appName is in app_R then
									if debug_level > 0 then
										log "move right full size"
										if debug_level > 1 then
											display dialog "move right full size"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, moveForMon:false, debug_level:debug_level})
								end if
							end repeat
						end tell
					end try
				end tell
			end if
		end repeat
	end if
end moveForMon

on run
	moveForMon({})
end run

property DEF_ALL : false
property DEF_DEBUG_LEVEL : 1

on moveForMon(pars)

	set {all, debug_level} to {DEF_ALL, DEF_DEBUG_LEVEL}
	try
		set all to all of pars
	end try
	try
		set debug_level to debug_level of pars
	end try

	-- debug mode
	if debug_level > 0 then
		log "debug mode = " & debug_level
		if debug_level > 1 then
			display dialog "debug mode = " & debug_level
		end if
	end if

	-- set monitoring tools' positions
	-- SimpleFloatingClock
	set w_sfcCEST to 1
	set w_sfcJST to 2

	-- XRG
	set w_XRG to 1

	-- set monitoring tool's name
	-- GeekTool
	set s_gtCal to "gcalCal"
	set s_gtGcal to "gcalList"
	set s_gtTask to "gtasklist"
	set s_gtPs to "myps"

	-- x posiiotn for monitoring
	set ledge to -160
	set ledgeSFCoffset to 20

	-- y positions
	set y_sfcCEST to 30
	set y_sfcJST to y_sfcCEST + 100
	set y_gtCal to y_sfcJST + 105
	set y_gtGcal to y_gtCal + 115
	set y_gtTask to y_gtGcal + 175
	set y_gtPs to y_gtTask + 85
	set y_XRG to y_gtPs + 75

	-- app to be excepted
	set expApp to {"XRG"}

	-- app to be half size, in left monitor (0.7 times full)
	set halfSizeApp_L to {}

	-- app to be half size, in right monitor (0.7 times full)
	set halfSizeApp_R to {"AdobeReader"}

	-- app only to be moved, in left monitor
	set noResizeApp_L to {}

	-- app only to be moved, in right monitor
	set noResizeApp_R to {"Finder", "Skype", "Microsoft Word", "Microsoft Excel", "Microsoft PowerPoint"}

	-- app to be moved left
	set app_L to {"firefox", "Evernote", "thunderbird", "thunderbird-bin", "Mail"}

	-- app to be moved right
	set app_R to {"iTerm"}

	-- get screen size
	tell application "Finder"
		set scriptPath to (path to me)'s folder as text
	end tell
	set windowSizeScpt to scriptPath & "windowSize.scpt"
	set windowSize to load script file windowSizeScpt

	-- main screen
	set svs to windowSize's getVisibleFrame(1, 1) --+1 is used to avoid edge, especially needed for y position
	set dPosX to (item 1 of svs) + 1
	set dPosY to (item 2 of svs) + 1
	set dWidth to item 3 of svs
	set dHeight to item 4 of svs

	-- try to get left screen
	set dPosX_L to dPosX + 1
	set dPosY_L to dPosY + 1
	try
		set svsL to windowSize's getVisibleFrame(-1, 1)
		set dPosX_L to (item 1 of svsL) + 1
		set dPosY_L to (item 2 of svsL) + 1
	end try

	-- try to get right screen
	set dPosX_R to dPosX + 1
	set dPosY_R to dPosY + 1
	try
		set svsR to windowSize's getVisibleFrame(dPosX + dWidth + 1, 1)
		set dPosX_R to (item 1 of svsR) + 1
		set dPosY_R to (item 2 of svsR) + 1
	end try

	-- move monitoring tools
	if dPosX_L < 0 then
		if debug_level > 0 then
			log "ledge to ledgeDual"
		end if
	else
		set ledge to dWidth + ledge
		if debug_level > 0 then
			log "ledge to ledgeSingle"
		end if
	end if

	tell application "System Events"
		-- SimpleFloatingClock
		try
			set appName to "SimpleFloatingClock"
			tell process appName
				tell window w_sfcCEST
					set size to {1000, 1000}
					set position to {ledge + ledgeSFCoffset, y_sfcCEST}
				end tell
				tell window w_sfcJST
					set size to {1000, 1000}
					set position to {ledge + ledgeSFCoffset, y_sfcJST}
				end tell
			end tell
		end try

		---- GeekTool
		--try
		--	--set appName to "GeekTool"
		--	set appName to "GeekTool Helper" -- for GeekTool 3
		--
		--	tell process appName
		--		set nW to number of windows
		--		--display dialog appName & " in process, nWindows=" & nW
		--		tell window w_gtCal
		--		end tell
		--		tell window w_gtGcal
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtGcal}
		--		end tell
		--		tell window w_gtTask
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtTask}
		--		end tell
		--		tell window w_gtPs
		--			-- set size to {1000, 1000}
		--			set position to {ledge, y_gtPs}
		--		end tell
		--	end tell
		--	--on error errMsg
		--	--	display dialog "ERROR: " & errMsg
		--end try

		-- XRG
		try
			set appName to "XRG"
			tell process appName
				tell window w_XRG
					set size to {1000, 2000}
					set position to {ledge, y_XRG}
				end tell
			end tell
		end try
	end tell

	-- GeekTool (should be outside of application "System Events", and use application "GeekTool Helper" ?)
	-- can't use position to geeklets
	tell application "GeekTool Helper" -- can not use appName (variable), which shows error at id?
		--geeklets
		repeat with g in geeklets
			tell g
				name
				if name is s_gtCal then
					set x position to ledge
					set y position to y_gtCal
				else if name is s_gtGcal then
					set x position to ledge
					set y position to y_gtGcal
				else if name is s_gtTask then
					set x position to ledge
					set y position to y_gtTask
				else if name is s_gtPs then
					set x position to ledge
					set y position to y_gtPs
				end if
			end tell
		end repeat
	end tell

	-- Move/Resize other windows
	if all then
		-- get application name
		tell application "System Events"
			set appList to (get name of every application process whose visible is true)
		end tell

		-- repeat for all app
		repeat with appName in appList
			if appName is not in expApp then
				tell application "System Events"
					try
						tell process appName
							set nW to number of windows
							repeat with i from 1 to nW
								if debug_level > 0 then
									log appName & " " & i
									if debug_level > 1 then
										display dialog appName & " " & i
									end if
								end if
								if appName is in halfSizeApp_L then
									if debug_level > 0 then
										log "half size left"
										if debug_level > 1 then
											display dialog "half size left"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, xsize:0.7, ysize:0.7, moveForMon:false, debug_level:debug_level})
								else if appName is in halfSizeApp_R then
									if debug_level > 0 then
										log "half size right"
										if debug_level > 1 then
											display dialog "half size right"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, xsize:0.7, ysize:0.7, moveForMon:false, debug_level:debug_level})
								else if appName is in noResizeApp_L then
									if debug_level > 0 then
										log "half size left"
										if debug_level > 1 then
											display dialog "half size left"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, resize:0, moveForMon:false, debug_level:debug_level})
								else if appName is in noResizeApp_R then
									if debug_level > 0 then
										log "move right"
										if debug_level > 1 then
											display dialog "move right"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, resize:0, moveForMon:false, debug_level:debug_level})
								else if appName is in app_L then
									if debug_level > 0 then
										log "move left full size"
										if debug_level > 1 then
											display dialog "move left full size"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_L, monPosY:dPosY_L, moveForMon:false, debug_level:debug_level})
								else if appName is in app_R then
									if debug_level > 0 then
										log "move right full size"
										if debug_level > 1 then
											display dialog "move right full size"
										end if
									end if
									windowSize's windowSize({appName:appName, windowNumber:i, monPosX:dPosX_R, monPosY:dPosY_R, moveForMon:false, debug_level:debug_level})
								end if
							end repeat
						end tell
					end try
				end tell
			end if
		end repeat
	end if
end moveForMon

on run
	moveForMon({})
end run


display dialog on itsipTransfer script completion

property wdtitle : "itsipTransfer"
property datfilename : ""
property tabchar : "	"
property newline : "
"

on initDatfileName()
	tell application "Finder"
		set datfilename to (container of (path to me) as text) & "itsipTransfer.dat"
	end tell
end initDatfileName

on splitString(txt, delim)
	set orgdelim to AppleScript's text item delimiters
	set AppleScript's text item delimiters to delim
	set txtelems to every text item of txt
	set AppleScript's text item delimiters to orgdelim
	return txtelems
end splitString

on dumpTrackData()
	try
		set wf to open for access datfilename with write permission
		set eof wf to 0
		tell application "iTunes"
			repeat with ctrk in every track
				set datline to ((name of ctrk) as class utf8) & tabchar & ((artist of ctrk) as class utf8) & tabchar & ((album of ctrk) as class utf8) & tabchar & (year of ctrk) & tabchar & (rating of ctrk) & tabchar & (volume adjustment of ctrk) & tabchar & ((comment of ctrk) as class utf8) & newline
				write datline as class utf8 to wf
			end repeat
		end tell
		close access wf
	on error errStr number errorNumber
		try
			close access wf
		end try
		error errStr number errorNumber
		return false
	end try
end dumpTrackData

on identFieldsMatch(tinfo, artist, album, year)
	if (length of (srcartist of tinfo)) > 0 then
		set fval to (srcartist of tinfo) as class utf8
		set tval to artist as class utf8
		if fval is not equal to tval then
			return false
		end if
	end if
	if (length of (srcalbum of tinfo)) > 0 then
		set fval to ((srcalbum of tinfo) as class utf8)
		set tval to (album as class utf8)
		if fval is not equal to tval then
			return false
		end if
	end if
	if (length of (srcyear of tinfo) > 0) and (year > 0) and ((srcyear of tinfo) as integer) is not equal to year then
		return false
	end if
	return true
end identFieldsMatch

on updateTrackInfo(tinfo, overwrite)
	tell application "iTunes"
		set srchres to (search playlist "Music" for (srcname of tinfo) only songs)
		repeat with trk in srchres
			-- display dialog "testing " & (name of trk)
			if my identFieldsMatch(tinfo, (artist of trk), (album of trk), (year of trk)) then
				set statmsg to "found " & (name of trk) & " - " & (artist of trk)
				if overwrite or ((rating of trk) is equal to 0) then
					set updrat to ((srcrating of tinfo) as integer)
					set statmsg to statmsg & newline & "rating set to " & updrat
					set (rating of trk) to updrat
				end if
				if overwrite or ((volume adjustment of trk) is equal to 0) then
					set updva to ((srcvoladj of tinfo) as integer)
					set statmsg to statmsg & newline & "volume adjust set to " & updva
					set (volume adjustment of trk) to updva
				end if
				if overwrite or (((comment of trk) as class utf8) is equal to "") then
					set statmsg to statmsg & newline & (srccomment of tinfo)
					set (comment of trk) to (srccomment of tinfo)
				end if
				-- display dialog statmsg
			end if
		end repeat
	end tell
end updateTrackInfo

on loadTrackData(overwrite)
	set fh to (open for access file datfilename)
	set fc to (read fh for (get eof fh) as class utf8)
	close access fh
	set datlines to splitString(fc, newline)
	set linum to 0
	repeat with datline in datlines
		set linum to linum + 1
		set trkfields to splitString(datline, tabchar)
		updateTrackInfo({srcname:item 1 of trkfields, srcartist:item 2 of trkfields, srcalbum:item 3 of trkfields, srcyear:item 4 of trkfields, srcrating:item 5 of trkfields, srcvoladj:item 6 of trkfields, srccomment:item 7 of trkfields}, overwrite)
	end repeat
end loadTrackData

on dumpOrLoad()
	initDatfileName()
	set ptxt to "Write or read itsipTransfer.dat. This can take a while (~2000 tracks/minute write, ~500 tracks/minute read). There will be a completion message when the script is done running. Select what you want to do:" & newline
	set acts to {"Write track data", "Read default track data", "Read and overwrite"}
	set listchoice to choose from list acts with prompt ptxt with title wdtitle
	if listchoice is false then
		return false
	else if (listchoice as text) is equal to ((item 1 of acts) as text) then
		dumpTrackData()
		display dialog "Tracks written to ~/Library/iTunes/Scripts/itsipTransfer.dat"
	else if (listchoice as text) is equal to ((item 2 of acts) as text) then
		loadTrackData(false)
		display dialog "Default track categorization data loaded."
	else if (listchoice as text) is equal to ((item 3 of acts) as text) then
		loadTrackData(true)
		display dialog "Track categorizations read completed."
	end if
end dumpOrLoad

-- Main script
dumpOrLoad()

property wdtitle : "itsipTransfer"
property datfilename : ""
property tabchar : "	"
property newline : "
"

on initDatfileName()
	tell application "Finder"
		set datfilename to (container of (path to me) as text) & "itsipTransfer.dat"
	end tell
end initDatfileName

on splitString(txt, delim)
	set orgdelim to AppleScript's text item delimiters
	set AppleScript's text item delimiters to delim
	set txtelems to every text item of txt
	set AppleScript's text item delimiters to orgdelim
	return txtelems
end splitString

on dumpTrackData()
	try
		set wf to open for access datfilename with write permission
		set eof wf to 0
		tell application "iTunes"
			repeat with ctrk in every track
				set datline to ((name of ctrk) as class utf8) & tabchar & ((artist of ctrk) as class utf8) & tabchar & ((album of ctrk) as class utf8) & tabchar & (year of ctrk) & tabchar & (rating of ctrk) & tabchar & (volume adjustment of ctrk) & tabchar & ((comment of ctrk) as class utf8) & newline
				write datline as class utf8 to wf
			end repeat
		end tell
		close access wf
	on error errStr number errorNumber
		try
			close access wf
		end try
		error errStr number errorNumber
		return false
	end try
end dumpTrackData

on identFieldsMatch(tinfo, artist, album, year)
	if (length of (srcartist of tinfo)) > 0 then
		set fval to (srcartist of tinfo) as class utf8
		set tval to artist as class utf8
		if fval is not equal to tval then
			return false
		end if
	end if
	if (length of (srcalbum of tinfo)) > 0 then
		set fval to ((srcalbum of tinfo) as class utf8)
		set tval to (album as class utf8)
		if fval is not equal to tval then
			return false
		end if
	end if
	if (length of (srcyear of tinfo) > 0) and (year > 0) and ((srcyear of tinfo) as integer) is not equal to year then
		return false
	end if
	return true
end identFieldsMatch

on updateTrackInfo(tinfo, overwrite)
	tell application "iTunes"
		set srchres to (search playlist "Music" for (srcname of tinfo) only songs)
		repeat with trk in srchres
			-- display dialog "testing " & (name of trk)
			if my identFieldsMatch(tinfo, (artist of trk), (album of trk), (year of trk)) then
				set statmsg to "found " & (name of trk) & " - " & (artist of trk)
				if overwrite or ((rating of trk) is equal to 0) then
					set updrat to ((srcrating of tinfo) as integer)
					set statmsg to statmsg & newline & "rating set to " & updrat
					set (rating of trk) to updrat
				end if
				if overwrite or ((volume adjustment of trk) is equal to 0) then
					set updva to ((srcvoladj of tinfo) as integer)
					set statmsg to statmsg & newline & "volume adjust set to " & updva
					set (volume adjustment of trk) to updva
				end if
				if overwrite or (((comment of trk) as class utf8) is equal to "") then
					set statmsg to statmsg & newline & (srccomment of tinfo)
					set (comment of trk) to (srccomment of tinfo)
				end if
				-- display dialog statmsg
			end if
		end repeat
	end tell
end updateTrackInfo

on loadTrackData(overwrite)
	set fh to (open for access file datfilename)
	set fc to (read fh for (get eof fh) as class utf8)
	close access fh
	set datlines to splitString(fc, newline)
	set linum to 0
	repeat with datline in datlines
		set linum to linum + 1
		set trkfields to splitString(datline, tabchar)
		updateTrackInfo({srcname:item 1 of trkfields, srcartist:item 2 of trkfields, srcalbum:item 3 of trkfields, srcyear:item 4 of trkfields, srcrating:item 5 of trkfields, srcvoladj:item 6 of trkfields, srccomment:item 7 of trkfields}, overwrite)
	end repeat
end loadTrackData

on dumpOrLoad()
	initDatfileName()
	set ptxt to "You can write data for all tracks out to itsipTransfer.dat, or you can read from itsipTransfer.dat optionally overwriting what you already have. Processing speed is somewhere in the range of 2000 tracks/minute on write, and 500 tracks a minute on read, so go get some coffee or whatever after you click ok.  Select what you want to do:"
	set acts to {"Write track data", "Read default track data", "Read and overwrite"}
	set listchoice to choose from list acts with prompt ptxt with title wdtitle
	if listchoice is false then
		return false
	else if (listchoice as text) is equal to ((item 1 of acts) as text) then
		dumpTrackData()
	else if (listchoice as text) is equal to ((item 2 of acts) as text) then
		loadTrackData(false)
	else if (listchoice as text) is equal to ((item 3 of acts) as text) then
		loadTrackData(true)
	end if
end dumpOrLoad

-- Main script
dumpOrLoad()


fixes #382

fixes #382

# Allows to run the script from Script Editor for testing
VbaHandler("TestString")

on VbaHandler(ParameterString)
	set {PYTHONPATH, PythonInterpreter, PythonCommand, WORKBOOK_FULLNAME, ApplicationFullName, LOG_FILE} to SplitString(ParameterString, ",")
	set ShellCommand to PythonInterpreter & "python -B -u -W ignore -c \"import sys, os;sys.path.extend(os.path.normcase(os.path.expandvars('" & PYTHONPATH & "')).split(';'));" & ¬
		PythonCommand & " \" \"" & WORKBOOK_FULLNAME & "\" \"from_xl\" \"" & ApplicationFullName & "\" >\"" & LOG_FILE & "\" 2>&1 & "
	try
		do shell script "source ~/.bash_profile"
		return do shell script "source ~/.bash_profile;" & ShellCommand
	on error errMsg number errNumber
		try
			# Try again without sourcing .bash_profile
			return do shell script ShellCommand
		on error errMsg number errNumber
			return 1
		end try
	end try
end VbaHandler

on SplitString(TheBigString, fieldSeparator)
	# From Ron de Bruin's "Mail from Excel 2016 with Mac Mail example": www.rondebruin.nl
	tell AppleScript
		set oldTID to text item delimiters
		set text item delimiters to fieldSeparator
		set theItems to text items of TheBigString
		set text item delimiters to oldTID
	end tell
	return theItems
end SplitString

# Allows to run the script from Script Editor for testing
VbaHandler("TestString")

on VbaHandler(ParameterString)
	set {PYTHONPATH, PythonInterpreter, PythonCommand, WORKBOOK_FULLNAME, ApplicationFullName, LOG_FILE} to SplitString(ParameterString, ",")
	set ShellCommand to PythonInterpreter & "python -u -W ignore -c \"import sys, os;sys.path.extend(os.path.normcase(os.path.expandvars('" & PYTHONPATH & "')).split(';'));" & ¬
		PythonCommand & " \" \"" & WORKBOOK_FULLNAME & "\" \"from_xl\" \"" & ApplicationFullName & "\" >\"" & LOG_FILE & "\" 2>&1 & "
	try
		do shell script "source ~/.bash_profile"
		return do shell script "source ~/.bash_profile;" & ShellCommand
	on error errMsg number errNumber
		try
			# Try again without sourcing .bash_profile
			return do shell script ShellCommand
		on error errMsg number errNumber
			return 1
		end try
	end try
end VbaHandler

on SplitString(TheBigString, fieldSeparator)
	# From Ron de Bruin's "Mail from Excel 2016 with Mac Mail example": www.rondebruin.nl
	tell AppleScript
		set oldTID to text item delimiters
		set text item delimiters to fieldSeparator
		set theItems to text items of TheBigString
		set text item delimiters to oldTID
	end tell
	return theItems
end SplitString


Return index when creating slide

Return index when creating slide

on newPresentation(themeName)
	tell application "Keynote"
		activate
		-- FIXME: Make this selectable?
		set targetWidth to 1024 -- 1440 <-- higher resolution
		set targetHeight to 768 -- 1080 <-- higher resolution

		set props to {document theme:theme (themeName as string), width:targetWidth, height:targetHeight}

		set thisDocument to make new document with properties props
		return id of thisDocument
	end tell
end newPresentation

on openPresentation(posixPath)
	tell application "Keynote"
		open posixPath
	end tell
end openPresentation

on savePresentation(docId, posixPath)
	tell application "Keynote"
		activate
        set theDocument to document id docId
		save theDocument in POSIX file posixPath
        delete theDocument
        open posixPath
	end tell
end savePresentation

on closePresentation(docId)
	tell application "Keynote"
		activate
        set theDocument to document id docId
		close theDocument
	end tell
end savePresentation

on createSlide(docId, masterSlideName)
	tell application "Keynote"
		tell document id docId
			set thisSlide to make new slide with properties {base slide:master slide masterSlideName}
		end tell
		return slide number of thisSlide
	end tell
end createSlide

on deleteAllSlides(docId)
	tell application "Keynote"
		tell document id docId to delete every slide
	end tell
end deleteAllSlides

on finalize(docId)
	tell application "Keynote"
		tell document id docId to delete slide 1
	end tell
end finalize

on themeMasters(docId)
	--	  tell application "Keynote" to get the name of every master slide of thisDocument
	tell application "Keynote"
		set names to the name of every master slide of document id docId
		return names
	end tell
end themeMasters

on addImage(docId, slideIndex, n, filepath)
  tell application "Keynote"
	tell slide slideIndex of document id docId
		-- TO REPLACE A PLACEHOLDER OR EXISTING IMAGE:
		set thisPlaceholderImageItem to image n
		-- change the value of the “file name” property of the image to be an HFS file reference to the replacement image file
	    set macPath to POSIX file filepath as Unicode text
		set file name of thisPlaceholderImageItem to ¬
			alias macPath
	end tell
  end tell
end addImage

on addTitle(docId, slideIndex, thisSlideTitle)
	tell application "Keynote"
    	tell slide slideIndex of document id docId
			set the object text of the default title item to thisSlideTitle
		end tell
	end tell
end addTitle

on addBody(docId, slideIndex, thisSlideBody)
	tell application "Keynote"
    	tell slide slideIndex of document id docId
            set the object text of the default body item to thisSlideBody
		end tell
	end tell
end addTitle

on addPresenterNotes(docId, slideIndex, theNotes)
	tell application "Keynote"
    	tell slide slideIndex of document id docId
			set presenter notes to theNotes
		end tell
	end tell
end addPresenterNotes

on addText(docId, slideIndex, itemIndex, theText)
  tell application "Keynote"
  	tell slide slideIndex of document id docId
		set thisPlaceholderItem to text item itemIndex
		set object text of thisPlaceholderItem to theText
	end tell
  end tell
end addText

on newPresentation(themeName)
	tell application "Keynote"
		activate
		-- FIXME: Make this selectable?
		set targetWidth to 1024 -- 1440 <-- higher resolution
		set targetHeight to 768 -- 1080 <-- higher resolution

		set props to {document theme:theme (themeName as string), width:targetWidth, height:targetHeight}

		set thisDocument to make new document with properties props
		return id of thisDocument
	end tell
end newPresentation

on openPresentation(posixPath)
	tell application "Keynote"
		open posixPath
	end tell
end openPresentation

on savePresentation(docId, posixPath)
	tell application "Keynote"
		activate
        set theDocument to document id docId
		save theDocument in POSIX file posixPath
        delete theDocument
        open posixPath
	end tell
end savePresentation

on closePresentation(docId)
	tell application "Keynote"
		activate
        set theDocument to document id docId
		close theDocument
	end tell
end savePresentation

on createSlide(docId, masterSlideName)
	tell application "Keynote"
		tell document id docId
			set thisSlide to make new slide with properties {base slide:master slide masterSlideName}
		end tell
	end tell
end createSlide

on deleteAllSlides(docId)
	tell application "Keynote"
		tell document id docId to delete every slide
	end tell
end deleteAllSlides

on finalize(docId)
	tell application "Keynote"
		tell document id docId to delete slide 1
	end tell
end finalize

on themeMasters(docId)
	--	  tell application "Keynote" to get the name of every master slide of thisDocument
	tell application "Keynote"
		set names to the name of every master slide of document id docId
		return names
	end tell
end themeMasters

on addImage(docId, slideIndex, n, filepath)
  tell application "Keynote"
	tell slide slideIndex of document id docId
		-- TO REPLACE A PLACEHOLDER OR EXISTING IMAGE:
		set thisPlaceholderImageItem to image n
		-- change the value of the “file name” property of the image to be an HFS file reference to the replacement image file
	    set macPath to POSIX file filepath as Unicode text
		set file name of thisPlaceholderImageItem to ¬
			alias macPath
	end tell
  end tell
end addImage

on addTitle(docId, slideIndex, thisSlideTitle)
	tell application "Keynote"
    	tell slide slideIndex of document id docId
			set the object text of the default title item to thisSlideTitle
		end tell
	end tell
end addTitle

on addBody(docId, slideIndex, thisSlideBody)
	tell application "Keynote"
    	tell slide slideIndex of document id docId
            set the object text of the default body item to thisSlideBody
		end tell
	end tell
end addTitle

on addPresenterNotes(docId, slideIndex, theNotes)
	tell application "Keynote"
    	tell slide slideIndex of document id docId
			set presenter notes to theNotes
		end tell
	end tell
end addPresenterNotes

on addText(docId, slideIndex, itemIndex, theText)
  tell application "Keynote"
  	tell slide slideIndex of document id docId
		set thisPlaceholderItem to text item itemIndex
		set object text of thisPlaceholderItem to theText
	end tell
  end tell
end addText


fixed bug where the document name had the extension

-- export all layers to image files
-- Copyright (c) 2011, Charles-Axel Dein

-- Settings
property exportFileExtension : "png"
-- End of Settings

tell application "OmniGraffle Professional 5"
	set theWindow to front window
	set theDocument to document of theWindow
	set theFilename to name of theDocument
    -- remove .graffle
    set theFilename to text 1 thru ((offset of "." in theFilename) - 1) of theFilename

	set export_folder to (choose folder with prompt "Pick the destination folder") as string
	set export_folder to export_folder & theFilename & ":"

	-- create folder
	do shell script "mkdir -p " & quoted form of POSIX path of export_folder

	set canvasCount to count of canvases of theDocument

	set i to 0
	repeat with canvasNumber from 1 to canvasCount
		set theCanvas to canvas canvasNumber of theDocument
		set canvas_name to name of theCanvas
		set canvas of theWindow to theCanvas
		set layerCount to count of layers of theCanvas

		-- hide all layers, except those beginning with "*"
		-- also check if there is only one layer to be exported
		repeat with layerNumber from 1 to layerCount
			set theLayer to layer layerNumber of theCanvas
			set number_of_layer_to_be_exported to 0

			if theLayer is prints and class of theLayer is not shared layer then
				set layer_name to name of theLayer as string
				if character 1 of layer_name is not "*" then
					set visible of theLayer to false
					set number_of_layer_to_be_exported to number_of_layer_to_be_exported + 1
				else
					set visible of theLayer to true
				end if
			end if

		end repeat

		set area type of current export settings to current canvas
        set draws background of current export settings to false
        set include border of current export settings to false

		repeat with layerNumber from 1 to layerCount
			set theLayer to layer layerNumber of theCanvas

			if (theLayer is prints) and (class of theLayer is not shared layer) then
				set layer_name to name of theLayer as string
				set filename to canvas_name & " - " & layer_name & "." & exportFileExtension
				set export_filename to export_folder & filename

				-- show the layer, export, then hide the layer
				if character 1 of layer_name is not "*" then
					set visible of theLayer to true
					save theDocument in export_filename
					set visible of theLayer to false
				end if

			end if

		end repeat

	end repeat
end tell

-- export all layers to image files
-- Copyright (c) 2011, Charles-Axel Dein

-- Settings
property exportFileExtension : "png"
-- End of Settings

tell application "OmniGraffle Professional 5"
	set theWindow to front window
	set theDocument to document of theWindow
	set theFilename to name of theDocument

	set export_folder to (choose folder with prompt "Pick the destination folder") as string
	set export_folder to export_folder & theFilename & ":"

	-- create folder
	do shell script "mkdir -p " & quoted form of POSIX path of export_folder

	set canvasCount to count of canvases of theDocument

	set i to 0
	repeat with canvasNumber from 1 to canvasCount
		set theCanvas to canvas canvasNumber of theDocument
		set canvas_name to name of theCanvas
		set canvas of theWindow to theCanvas
		set layerCount to count of layers of theCanvas

		-- hide all layers, except those beginning with "*"
		-- also check if there is only one layer to be exported
		repeat with layerNumber from 1 to layerCount
			set theLayer to layer layerNumber of theCanvas
			set number_of_layer_to_be_exported to 0

			if theLayer is prints and class of theLayer is not shared layer then
				set layer_name to name of theLayer as string
				if character 1 of layer_name is not "*" then
					set visible of theLayer to false
					set number_of_layer_to_be_exported to number_of_layer_to_be_exported + 1
				else
					set visible of theLayer to true
				end if
			end if

		end repeat

		repeat with layerNumber from 1 to layerCount
			set theLayer to layer layerNumber of theCanvas

			if (theLayer is prints) and (class of theLayer is not shared layer) then
				set layer_name to name of theLayer as string
				set filename to canvas_name & " - " & layer_name & "." & exportFileExtension
				set export_filename to export_folder & filename

				-- show the layer, export, then hide the layer
				if character 1 of layer_name is not "*" then
					set visible of theLayer to true
					set area type of current export settings to current canvas
					save theDocument in export_filename
					set visible of theLayer to false
				end if

			end if

		end repeat

	end repeat
end tell


Added a newline to the end of the script - snak seemed unhappy without this.

--HG--
extra : convert_revision : svn%3A99687598-2e92-11dd-8019-fe7b9d601d1b/trunk%401904

FasdUAS 1.101.10
k
i
I0
registergrowl
registerGrowl
k

r

J
mPublic Message
mPrivate Message

o0allnotesallNotes
O
I
.registernullnull

appl
m

Snak

anot
o0allnotesallNotes

dnot
o0allnotesallNotes

iapp
m
Snak
m!!"nullaa;GrowlHelperApp.appL7P@)(K pGRRRalisWideBoy.1H+a3GrowlHelperApp.appa8v	 	Resources.1va3a2a1	TWideBoy:Library:PreferencePanes:Growl.prefPane:Contents:Resources:GrowlHelperApp.app&GrowlHelperApp.appWideBoyLLibrary/PreferencePanes/Growl.prefPane/Contents/Resources/GrowlHelperApp.app/"#
"l#$%
$l%&'
&i()
(I*
0pubmsg*+,
+o0con,-.
-o
0source./0
/o0
sourcehost012
1o
0target23
3o
0	thestring
)k4456
5l678
7l89:
9l;;VP################################################################################:<=
<l>>4.########	Edit these values to suit your wishes=?@
?lAAVP################################################################################@BC
BlCDE
DlFF:4 set ChannelsToMonitor to {"#example1", "#example2"}EGH
GlII/) set keywords to {"keyword1", "keyword2"}HJK
JrLM
LJ
Mo&0channelstomonitorChannelsToMonitorKNO
Nr	PQ
PJ
Qo0keywordsORS
Rl

STU
Tl

VVSM Set to false to popup notifications even when snak is the active applicationUWX
Wr

YZ
Ym

boovtrue
Zo00notifyinbackgroundonlyNotifyInBackgroundOnlyX[\
[l\]^
]l__VP################################################################################^`a
`lbb######### 	End Editable Regionacd
cleeWQ################################################################################	dfg
flghi
hlijk
jlklm
llnn)# Get the name of the topmost windowmop
oO$qr
qr#st
s6!uv
unwx
w1

pnam
x4y

prcs
ym
v= z{
z1

pisf
{m
boovtrue
to"0nameofactiveappNameOfActiveApp
rm||null

Finder.app΀0L7ΰp)(K MACSalisbWideBoy.1H+

Finder.app2	 CoreServices.1

.WideBoy:System:Library:CoreServices:Finder.app
Finder.appWideBoy&System/Library/CoreServices/Finder.app/p}~
}l%%~
l%%
l%%$ Get your current irc nickname
O%2
r)1
n)/
1-/

NICK
4)-

CONN
o+,0con
o
0mynick
m%&nullA߸`baSnakQP0L7ՀZ()(K ՠSNpaalisZWideBoy.1H+`baSnak`bۺtMt	 	Snak 4.13.1tM`ba|,WideBoy:Users:diggory:Desktop:Snak 4.13:Snak
SnakWideBoy$Users/diggory/Desktop/Snak 4.13/Snak/
l33
l33
l33NH First, make sure we are either focused on another app, or we want to be
l33'! notified even if Snak is on top
Z3
G3>
l36
>36
o34"0nameofactiveappNameOfActiveApp
m45
Snak
l9<
=9<
o9:00notifyinbackgroundonlyNotifyInBackgroundOnly
m:;
boovfals
kA
lAA
lAA
lAAa[ Make sure the message's target is in ChannelsToMonitor, or that ChannelsToMonitor is empty
ZA
lAN
GAN
EAD
oAB&0channelstomonitorChannelsToMonitor
oBC
0target
=GL
nGJ
1HJ

leng
oGH&0channelstomonitorChannelsToMonitor
mJK
kQ
lQQ
lQQHB if keywords is empty, we're successful and we display the message
lQQNH otherwise, only set success if the message contains one of our keywords
ZQ
lQV
=QV
nQT
1RT

leng
oQR0keywords
mTU
rY\
mYZ
boovtrue
o0keywordmatchkeywordMatch
k_
r_b
m_`
boovfals
o0keywordmatchkeywordMatch
Xc
Zs
lsv
Esv
ost
0	thestring
otu0thiskeywordthisKeyword
ry|
myz
boovtrue
o0keywordmatchkeywordMatch0thiskeywordthisKeyword
lfg
ofg0keywords
l
l;5 if the message contains our nick, we will display it
Z
l~
E
o}}
0	thestring
o||
0mynick~
r
m{
{boovtrue
ozz0keywordmatchkeywordMatchy
lxwxwy
lvuvu
lttmg If the message is coming from a valid channel, and we got success in matching either keywords or nick,
lss display an alert
Zrq
lp
=
ooo0keywordmatchkeywordMatch
mn
nboovtruep
k
n
Imlkm0
registergrowl
registerGrowllk
fj
O
Iih
i.notifygrnullnullhg
g
titl
l	f
	b

b

oee
0source

m:
odd
0targetfc
c
desc
lb
oaa
0	thestringb`
`
appl
m
Snak_^
_
name
mPublic Message^
m!jrq]
l\[\[]
lZYZYX
lWVWVX
lUTUTS
L
mR
RboovfalsS'
lQPQP !"
!lO#O#(" Log all private messages to growl"$%
$i&'
&IN(MN0privmsg()*
)oLL0con*+,
+oKK
0source,-.
-oJJ0
sourcehost./0
/oII
0target01H
1oGG
0	thestringHM
'kI2234
3lFEFE456
5lD7D7.( Get the name of the topmost application689
8O:;
:r<=
<6>?
>n
@A
@1
C
C
pnam
A4BB
B
prcs
BmAA
?=CD
C1@
@
pisf
Dm?
?boovtrue
=o>>"0nameofactiveappNameOfActiveApp
;m|9EF
El=<=<FGH
GZGIJ;:
IG"KL
KlM9
M>NO
No88"0nameofactiveappNameOfActiveApp
OmPP
Snak9
Ll Q7
Q= RS
Ro6600notifyinbackgroundonlyNotifyInBackgroundOnly
Sm5
5boovfals7
Jk%CTTUV
Un%*WX
WI&*43240
registergrowl
registerGrowl32
Xf%&VY1
YO+CZ[
ZI/B0/\
0.notifygrnullnull/\.]^
.
titl
]l16_-
_b16`a
`b14bc
bo12,,
0source
cm23dd:
ao45++
0target-^*ef
*
desc
el78g)
go78((
0	thestring)f'hi
'
appl
hm9:jj
Snaki&k%
&
name
km;<llPrivate Message%
[m+,!1;:Hm$
mlHH#"#"$%no
nl! ! op
plqrstq0
registergrowl
registerGrowl
0pubmsg0privmsgruv0
registergrowl
registerGrowlu0allnotesallNotesv!

appl

anot

dnot

iapp
.registernullnulllvEO*
Us
)wx

0pubmsg	y	y0con
0source0
sourcehost
0target
0	thestringw0con
0source0
sourcehost
0target
0	thestring&0channelstomonitorChannelsToMonitor0keywords00notifyinbackgroundonlyNotifyInBackgroundOnly"0nameofactiveappNameOfActiveApp
0mynick0keywordmatchkeywordMatch0thiskeywordthisKeywordx|z!

prcs

pnamz

pisf

CONN

NICK

bool

leng

kocl

cobj
.corecnte********0
registergrowl
registerGrowl

titl

desc

appl

name
.notifygrnullnull
jvEOjvEOeEO*k/,[,\Ze81EUO
*/,EUO
f&
	,j&,jeEY8fEO![l
kheEYh[OYOeEYhOPOe1)j+O#*aa%%aaaaaaUYhOPYhOPYhOft'{|0privmsg}}0con
0source0
sourcehost
0target
0	thestring{0con
0source0
sourcehost
0target
0	thestring"0nameofactiveappNameOfActiveApp00notifyinbackgroundonlyNotifyInBackgroundOnly||zP!djl

prcs

pnam

pisf

bool0
registergrowl
registerGrowl

titl

desc

appl

name
.notifygrnullnullJ*k/,[,\Ze81EUO
f&#)j+O*%%aUYhOPascr
ޭ

FasdUAS 1.101.10
k
i
I0
registergrowl
registerGrowl
k

r

J
mPublic Message
mPrivate Message

o0allnotesallNotes
O
I
.registernullnull

appl
m

Snak

anot
o0allnotesallNotes

dnot
o0allnotesallNotes

iapp
m
Snak
m!!"nullaa;GrowlHelperApp.appL7P@)(K pGRRRalisWideBoy.1H+a3GrowlHelperApp.appa8v	 	Resources.1va3a2a1	TWideBoy:Library:PreferencePanes:Growl.prefPane:Contents:Resources:GrowlHelperApp.app&GrowlHelperApp.appWideBoyLLibrary/PreferencePanes/Growl.prefPane/Contents/Resources/GrowlHelperApp.app/"#
"l#$%
$l%&'
&i()
(I*
0pubmsg*+,
+o0con,-.
-o
0source./0
/o0
sourcehost012
1o
0target23
3o
0	thestring
)k4456
5l678
7l89:
9l;;VP################################################################################:<=
<l>>4.########	Edit these values to suit your wishes=?@
?lAAVP################################################################################@BC
BlCDE
DlFF:4 set ChannelsToMonitor to {"#example1", "#example2"}EGH
GlII/) set keywords to {"keyword1", "keyword2"}HJK
JrLM
LJ
Mo&0channelstomonitorChannelsToMonitorKNO
Nr	PQ
PJ
Qo0keywordsORS
Rl

STU
Tl

VVSM Set to false to popup notifications even when snak is the active applicationUWX
Wr

YZ
Ym

boovtrue
Zo00notifyinbackgroundonlyNotifyInBackgroundOnlyX[\
[l\]^
]l__VP################################################################################^`a
`lbb######### 	End Editable Regionacd
cleeWQ################################################################################	dfg
flghi
hlijk
jlklm
llnn)# Get the name of the topmost windowmop
oO$qr
qr#st
s6!uv
unwx
w1

pnam
x4y

prcs
ym
v= z{
z1

pisf
{m
boovtrue
to"0nameofactiveappNameOfActiveApp
rm||null

Finder.app΀0L7ΰp)(K MACSalisbWideBoy.1H+

Finder.app2	 CoreServices.1

.WideBoy:System:Library:CoreServices:Finder.app
Finder.appWideBoy&System/Library/CoreServices/Finder.app/p}~
}l%%~
l%%
l%%$ Get your current irc nickname
O%2
r)1
n)/
1-/

NICK
4)-

CONN
o+,0con
o
0mynick
m%&nullA߸`baSnakQP0L7ՀZ()(K ՠSNpaalisZWideBoy.1H+`baSnak`bۺtMt	 	Snak 4.13.1tM`ba|,WideBoy:Users:diggory:Desktop:Snak 4.13:Snak
SnakWideBoy$Users/diggory/Desktop/Snak 4.13/Snak/
l33
l33
l33NH First, make sure we are either focused on another app, or we want to be
l33'! notified even if Snak is on top
Z3
G3>
l36
>36
o34"0nameofactiveappNameOfActiveApp
m45
Snak
l9<
=9<
o9:00notifyinbackgroundonlyNotifyInBackgroundOnly
m:;
boovfals
kA
lAA
lAA
lAAa[ Make sure the message's target is in ChannelsToMonitor, or that ChannelsToMonitor is empty
ZA
lAN
GAN
EAD
oAB&0channelstomonitorChannelsToMonitor
oBC
0target
=GL
nGJ
1HJ

leng
oGH&0channelstomonitorChannelsToMonitor
mJK
kQ
lQQ
lQQHB if keywords is empty, we're successful and we display the message
lQQNH otherwise, only set success if the message contains one of our keywords
ZQ
lQV
=QV
nQT
1RT

leng
oQR0keywords
mTU
rY\
mYZ
boovtrue
o0keywordmatchkeywordMatch
k_
r_b
m_`
boovfals
o0keywordmatchkeywordMatch
Xc
Zs
lsv
Esv
ost
0	thestring
otu0thiskeywordthisKeyword
ry|
myz
boovtrue
o0keywordmatchkeywordMatch0thiskeywordthisKeyword
lfg
ofg0keywords
l
l;5 if the message contains our nick, we will display it
Z
l~
E
o}}
0	thestring
o||
0mynick~
r
m{
{boovtrue
ozz0keywordmatchkeywordMatchy
lxwxwy
lvuvu
lttmg If the message is coming from a valid channel, and we got success in matching either keywords or nick,
lss display an alert
Zrq
lp
=
ooo0keywordmatchkeywordMatch
mn
nboovtruep
k
n
Imlkm0
registergrowl
registerGrowllk
fj
O
Iih
i.notifygrnullnullhg
g
titl
l	f
	b

b

oee
0source

m:
odd
0targetfc
c
desc
lb
oaa
0	thestringb`
`
appl
m
Snak_^
_
name
mPublic Message^
m!jrq]
l\[\[]
lZYZYX
lWVWVX
lUTUTS
L
mR
RboovfalsS'
lQPQP !"
!lO#O#(" Log all private messages to growl"$%
$i&'
&IN(MN0privmsg()*
)oLL0con*+,
+oKK
0source,-.
-oJJ0
sourcehost./0
/oII
0target01H
1oGG
0	thestringHM
'kI2234
3lFEFE456
5lD7D7.( Get the name of the topmost application689
8O:;
:r<=
<6>?
>n
@A
@1
C
C
pnam
A4BB
B
prcs
BmAA
?=CD
C1@
@
pisf
Dm?
?boovtrue
=o>>"0nameofactiveappNameOfActiveApp
;m|9EF
El=<=<FGH
GZGIJ;:
IG"KL
KlM9
M>NO
No88"0nameofactiveappNameOfActiveApp
OmPP
Snak9
Ll Q7
Q= RS
Ro6600notifyinbackgroundonlyNotifyInBackgroundOnly
Sm5
5boovfals7
Jk%CTTUV
Un%*WX
WI&*43240
registergrowl
registerGrowl32
Xf%&VY1
YO+CZ[
ZI/B0/\
0.notifygrnullnull/\.]^
.
titl
]l16_-
_b16`a
`b14bc
bo12,,
0source
cm23dd:
ao45++
0target-^*ef
*
desc
el78g)
go78((
0	thestring)f'hi
'
appl
hm9:jj
Snaki&k%
&
name
km;<llPrivate Message%
[m+,!1;:Hm$
mlHH#"#"$%n!
nl  !opqro0
registergrowl
registerGrowl
0pubmsg0privmsgpst0
registergrowl
registerGrowls0allnotesallNotest!

appl

anot

dnot

iapp
.registernullnulllvEO*
Uq)
uv
0pubmsgww

0con
0source0
sourcehost
0target
0	thestring
u0con
0source0
sourcehost
0target
0	thestring&0channelstomonitorChannelsToMonitor0keywords00notifyinbackgroundonlyNotifyInBackgroundOnly"0nameofactiveappNameOfActiveApp
0mynick0keywordmatchkeywordMatch0thiskeywordthisKeywordv|x!

prcs

pnamx

pisf

CONN

NICK

bool

leng

kocl

cobj
.corecnte********0
registergrowl
registerGrowl

titl

desc

appl

name
.notifygrnullnulljvEOjvEOeEO*k/,[,\Ze81EUO
*/,EUO
f&
	,j&,jeEY8fEO![l
kheEYh[OYOeEYhOPOe1)j+O#*aa%%aaaaaaUYhOPYhOPYhOfr'yz0privmsg{{0con
0source0
sourcehost
0target
0	thestringy0con
0source0
sourcehost
0target
0	thestring"0nameofactiveappNameOfActiveApp00notifyinbackgroundonlyNotifyInBackgroundOnlyz|xP!djl

prcs

pnam

pisf

bool0
registergrowl
registerGrowl

titl

desc

appl

name
.notifygrnullnullJ*k/,[,\Ze81EUO
f&#)j+O*%%aUYhOPascrޭ


Added AppleScript doc

Added AppleScript doc

FasdUAS 1.101.10
k
l
i

	I
.aevtoappnull****
o0argv

k;

l
lset argv to {"/Users/lbayes/Projects/CLIXFlashPlayer/exploration/fixtures/9.0.151/Flash Player.app", "Users:lbayes:Projects:CLIXFlashPlayer:exploration:fixtures:SomeProject.swf"}dset argv to {"/Users/lbayes/Projects/CLIXFlashPlayer/exploration/fixtures/9.0.151/Flash Player.app", "Users:lbayes:Projects:CLIXFlashPlayer:exploration:fixtures:SomeProject.swf"}
l
r
n
4

cobj
m
o0argv
o0flashplayerflashPlayer
r

n!"
!4#

cobj
#m

"o0argv
 o0swffileswfFile$%
$l%&'
&O9()
(k8**+,
+I
.miscactvnullnull,-.
-I#/
.aevtodocnullalis
/40

file
0o0swffileswfFile.12
1l$$23
3V$845
4I.36
.sysodelanullnmbr
6m./77?ٙ
5=(-89
8n(+:;
:1)+

prun
;g()
9m+,
boovtrue
)4<

capp
<o0flashplayerflashPlayer'=
=l::>
>l?@?
.aevtoappnull****@
AB
.aevtoappnull****0argvA0argvB
7

cobj0flashplayerflashPlayer0swffileswfFile

capp
.miscactvnullnull

file
.aevtodocnullalis

prun
.sysodelanullnmbr<k/EOl/EO*/%*jO*/jOh*,ej	[OYUOPascrޭ

FasdUAS 1.101.10
k
l
i

	I
.aevtoappnull****
o0argv

k;

l
lset argv to {"/Users/lbayes/Projects/CLIXFlashPlayer/exploration/fixtures/9.0.151/Flash Player.app", "Users:lbayes:Projects:CLIXFlashPlayer:exploration:fixtures:SomeProject.swf"}dset argv to {"/Users/lbayes/Projects/CLIXFlashPlayer/exploration/fixtures/9.0.151/Flash Player.app", "Users:lbayes:Projects:CLIXFlashPlayer:exploration:fixtures:SomeProject.swf"}
l
r
n
4

cobj
m
o0argv
o0flashplayerflashPlayer
r

n!"
!4#

cobj
#m

"o0argv
 o0swffileswfFile$%
$l%&'
&O9()
(k8**+,
+I
.miscactvnullnull,-.
-I#/
.aevtodocnullalis
/40

file
0o0swffileswfFile.12
1l$$23
3V$845
4I.36
.sysodelanullnmbr
6m./77?ٙ
5=(-89
8n(+:;
:1)+

prun
;g()
9m+,
boovtrue
)4<

capp
<o0flashplayerflashPlayer'=
=l::>
>l?@AB?
.aevtoappnull****0flashplayerflashPlayer0swffileswfFile@
CD
.aevtoappnull****0argvC0argvD
7

cobj0flashplayerflashPlayer0swffileswfFile

capp
.miscactvnullnull

file
.aevtodocnullalis

prun
.sysodelanullnmbr<k/EOl/EO*/%*jO*/jOh*,ej	[OYUOPAEE/Users/lbayes/Projects/CLIXFlashPlayer/exploration/fixtures/9.0.151/Flash Player.appBFFUsers:lbayes:Projects:CLIXFlashPlayer:exploration:fixtures:SomeProject.swfascrޭ


Fixed TO and CC field extraction

Fixed TO and CC field extraction

Change-Id: I379bbc2d676611a6de18be481c7b7d42b403052c
Signed-off-by: Falko Zurell <553d907fcdd96929d5363dc3b6e443669c7e54a8@zurell.de>

set this_file to (((path to home folder) as string) & "MailLog.log")

on write_to_file(this_data, target_file, append_data)
	try
		set the target_file to the target_file as string
		set the open_target_file to open for access file target_file with write permission
		if append_data is false then set eof of the open_target_file to 0
		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 replace_chars(this_text, search_string, replacement_string)
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to ""
	return this_text
end replace_chars

-- This code is triggered if you manually run the script in AppleScript Editor. It retreives any selected messages and then processes them. This is good for testing.
tell application "Microsoft Outlook"
	set theMessages to current messages
	--(plain text content of (item 1 of theMessages))
	--return paragraphs of result
end tell

-- Count the messages received from Outlook.
set theMessageCount to count theMessages

-- Loop through the messages received from Outlook.
tell application "Microsoft Outlook"
	repeat with a from 1 to theMessageCount
		-- Target the current message in the loop.
		tell item a of theMessages
			-- Retrieve the name of the current message's sender.
			set theSender to sender

			try
				set theSenderName to name of theSender

			on error
				set theSenderName to address of theSender
			end try
			set theSenderAddress to address of theSender
			-- Retrieve the current message's subject.
			set theSubject to subject
			set timeReceived to time received
			set timeSent to time sent
			set thePriority to priority
			set theSource to source as text
			set theSize to length of theSource

			-- extract CC recipients
			set theCC to cc recipients
			set CCList to ""
			repeat with rcp in theCC
				set recipientEMail to email address of rcp
				set CCList to CCList & address of recipientEMail as text
				set CCList to CCList & ","
			end repeat

			-- extract the TO recipients
			set theTO to to recipients
			set TOList to ""
			repeat with rcp in theTO
				set recipientEMail to email address of rcp
				set TOList to TOList & address of recipientEMail as text
				set TOList to TOList & ","
			end repeat

			if thePriority = priority normal then
				set mailPriority to "normal"
			else if thePriority = priority high then
				set mailPriority to "high"
			else if thePriority = priority low then
				set mailPriority to "low"
			else
				set mailPriority to "none"
			end if

			set isMeeting to is meeting
		end tell

		set theSubject to my replace_chars(theSubject, "|", "--")
		set output to timeReceived & "|" & timeSent & "|" & theSenderAddress & "|" & TOList & "|" & CCList & "|" & theSubject & "|" & mailPriority & "|" & isMeeting & "|" & theSize & return

		my write_to_file(output as string, this_file, true)

	end repeat
end tell

set this_file to (((path to home folder) as string) & "MailLog.log")

on write_to_file(this_data, target_file, append_data)
	try
		set the target_file to the target_file as string
		set the open_target_file to open for access file target_file with write permission
		if append_data is false then set eof of the open_target_file to 0
		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 replace_chars(this_text, search_string, replacement_string)
	set AppleScript's text item delimiters to the search_string
	set the item_list to every text item of this_text
	set AppleScript's text item delimiters to the replacement_string
	set this_text to the item_list as string
	set AppleScript's text item delimiters to ""
	return this_text
end replace_chars

-- This code is triggered if you manually run the script in AppleScript Editor. It retreives any selected messages and then processes them. This is good for testing.
tell application "Microsoft Outlook"
	set theMessages to current messages
	--(plain text content of (item 1 of theMessages))
	--return paragraphs of result
end tell

-- Count the messages received from Outlook.
set theMessageCount to count theMessages

-- Loop through the messages received from Outlook.
tell application "Microsoft Outlook"
	repeat with a from 1 to theMessageCount
		-- Target the current message in the loop.
		tell item a of theMessages
			-- Retrieve the name of the current message's sender.
			set theSender to sender
			set theCC to cc recipients
			set theTO to to recipients
			try
				set theSenderName to name of theSender

			on error
				set theSenderName to address of theSender
			end try
			set theSenderAddress to address of theSender
			-- Retrieve the current message's subject.
			set theSubject to subject
			set timeReceived to time received
			set timeSent to time sent
			set thePriority to priority
			set theSource to source as text
			set theSize to length of theSource
			set CCList to ""
			repeat with rcp in theCC
				log address of rcp
				get address of email address of rcp
				set recipientAddress to address of email address of rcp
				set CCList to CCList & "," & recipient as text
			end repeat
			if thePriority = priority normal then
				set mailPriority to "normal"
			else if thePriority = priority high then
				set mailPriority to "high"
			else if thePriority = priority low then
				set mailPriority to "low"
			else
				set mailPriority to "none"
			end if

			set isMeeting to is meeting
		end tell

		set theSubject to my replace_chars(theSubject, "|", "--")
		set output to timeReceived & "|" & timeSent & "|" & theSenderAddress & "|" & theSubject & "|" & mailPriority & "|" & isMeeting & "|" & theSize & return

		my write_to_file(output as string, this_file, true)

	end repeat
end tell