#!/bin/bash
#
# Updates the current user's settings to my preferred state.
#
# This script is idempotent, so it can be run repeatedly on the same machine
# and account.
#
# This should be run from Terminal.app, with iTerm2 not running. If iTerm2 is
# running, that prevents its preferences from being properly updated.
# (TODO: See if CFPreferencesAppSynchronize can fix that.)
#
# The coding style has a lot of copy-and-paste instead of being factored in to
# functions. This is intentional, to allow easy interactive copy-and-pasting of
# individual commands to the terminal. A "defaults-write" call may be replaced with
# "defaults write" at the command line.

# Load JXL. See "Loading JXL" in dots/README.md.
source "$(cd "$(dirname "$0")" && pwd -P)/../dots/all-os/flat/dotlib/jxl-lib.sh" \
    || { echo >&2 "ERROR: failed to load jxl-lib.sh"; exit 1; }

# errexit stays off: some of these defaults-writes fail on Mojave, and the run should
# carry on past them.
jxl::init_script --no-errexit
jxl::use_short_names

MYDIR="$( dirname "${BASH_SOURCE[0]}" )"
DROPBOX="$HOME/Dropbox"
DOTFILES_REPO_PATH="$DROPBOX/#repos/dotfiles"
MANUAL_SETTINGS_PATH="$DOTFILES_REPO_PATH/manual-settings"
SERIALS_DIR="$DROPBOX/records/licenses and serials"
WALLPAPER_FILE="/Library/Desktop Pictures/Wave.jpg"
: "${ITERM_PREFERENCES_SET:=12pt}"

DO_KILL=0
OPT_TRACE=0

function usage() {
  cat <<EOF
$PROGRAM_NAME - Set up system settings according to apjanke's preferences

Usage:
  $PROGRAM_NAME [--trace] [--verbose] [--kill]
  $PROGRAM_NAME --help

Options:
    -k, --kill      kill affected programs after updating settings
    -x, --trace     trace program execution
$(jxl::std_options_help)

Environment:
  ITERM_PREFERENCES_SET  - name of preferences set (leaf shared preferences dir)
EOF
}

function main() {

OSX_VERSION=$(sw_vers -productVersion)
plistbuddy=/usr/libexec/PlistBuddy

################################################
# Dock
################################################

CHANGED=0

# Left side of screen
defaults-write com.apple.dock orientation -string left
defaults-write com.apple.dock pinning -string middle

# Dim icons of hidden apps
defaults-write com.apple.dock showhidden -bool true

# Dock icon size
defaults-write com.apple.dock tilesize -float 32

# Autohide dock
defaults-write com.apple.dock autohide -bool true
# Auto-hiding delay
# (I prefer a bit of delay, so I'm leaving it in)
#defaults-write com.apple.dock autohide-delay -float 0
defaults-delete com.apple.dock autohide-delay
# Remove the animation when hiding/showing the Dock
defaults-write com.apple.dock autohide-time-modifier -float 0
#defaults-delete com.apple.dock autohide-time-modifier

# Change minimize/maximize window effect
defaults-write com.apple.dock mineffect -string "scale"

# Don’t animate opening applications from the Dock
defaults-write com.apple.dock launchanim -bool false

# Speed up Mission Control animations
defaults-write com.apple.dock expose-animation-duration -float 0.1

# Don’t group windows by application in Mission Control
# (i.e. use the old Exposé behavior instead)
defaults-write com.apple.dock expose-group-by-app -bool false

# Make icons of hidden applications translucent
defaults write com.apple.dock showhidden -bool true

# Disable Dashboard
defaults-write com.apple.dashboard mcx-disabled -bool true

# Don’t show Dashboard as a Space
defaults-write com.apple.dock dashboard-in-overlay -bool true

# Remove unwanted apps
unwanted_apps=(
  Launchpad
  Mail
  Contacts
  Notes
  Reminders
  Maps
  Messages
  FaceTime
  iBooks
  "App Store"
  "Photo Booth"
  "System Preferences"
  Pages
  Numbers
  Keynote
  Photos
  "Microsoft Excel"
  "Microsoft Word"
  "Microsoft Outlook"
  "Microsoft PowerPoint"
  "Microsoft Document Connection"
  )
for app in "${unwanted_apps[@]}"; do
  remove-dock-persistent-app "$app"
done

if [[ $CHANGED == 1 ]]; then
  killall Dock 2> /dev/null
fi

################################################
# Misc OS UI stuff
################################################

# Hot corners
# Key names: wvous-<loc>-corner, wvous-<loc>-modifier
#   where <loc> may be: tl, tr, bl, br
# Possible "corner" values:
#  0: no-op
#  2: Mission Control
#  3: Show application windows
#  4: Desktop
#  5: Start screen saver
#  6: Disable screen saver
#  7: Dashboard
# 10: Put display to sleep
# 11: Launchpad
# 12: Notification Center

# Top left screen corner → Start screen saver
defaults-write com.apple.dock wvous-tl-corner -int 5
defaults-write com.apple.dock wvous-tl-modifier -int 0
# Top right screen corner → Desktop
defaults-write com.apple.dock wvous-tr-corner -int 4
defaults-write com.apple.dock wvous-tr-modifier -int 0

# Disable transparency in the menu bar and elsewhere on Yosemite
defaults-write com.apple.universalaccess reduceTransparency -bool true

# Set sidebar icon size to medium
defaults-write NSGlobalDomain NSTableViewDefaultSizeMode -int 1

# Increase window resize speed for Cocoa applications
defaults-write NSGlobalDomain NSWindowResizeTime -float 0.001

# Expand save panel by default
defaults-write NSGlobalDomain NSNavPanelExpandedStateForSaveMode -bool true
defaults-write NSGlobalDomain NSNavPanelExpandedStateForSaveMode2 -bool true

# Expand print panel by default
defaults-write NSGlobalDomain PMPrintingExpandedStateForPrint -bool true
defaults-write NSGlobalDomain PMPrintingExpandedStateForPrint2 -bool true

# Save to disk (not to iCloud) by default
defaults-write NSGlobalDomain NSDocumentSaveNewDocumentsToCloud -bool false

# Disable Application Resume
defaults-write com.apple.systempreferences NSQuitAlwaysKeepsWindows -bool false

# Disable the over-the-top focus ring animation
defaults-write NSGlobalDomain NSUseAnimatedFocusRing -bool false

# Automatically quit printer app once the print jobs complete
defaults-write com.apple.print.PrintingPrefs "Quit When Finished" -bool true

# Disable the “Are you sure you want to open this application?” dialog
#defaults-write com.apple.LaunchServices LSQuarantine -bool false

# Disable automatic termination of inactive apps
defaults-write NSGlobalDomain NSDisableAutomaticTermination -bool true

# Set Help Viewer windows to non-floating mode
defaults-write com.apple.helpviewer DevMode -bool true

# Check for software updates daily, not just once per week
defaults-write com.apple.SoftwareUpdate ScheduleFrequency -int 1

# Enable snap-to-grid for desktop icons
/usr/libexec/PlistBuddy -c "Set :DesktopViewSettings:IconViewSettings:arrangeBy grid" ~/Library/Preferences/com.apple.finder.plist

################################################
# Trackpad, mouse, keyboard, and other HCI peripheral stuff
################################################

# Trackpad: enable tap to click for this user and for the login screen
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad Clicking -bool true
defaults -currentHost write NSGlobalDomain com.apple.mouse.tapBehavior -int 1
defaults-write NSGlobalDomain com.apple.mouse.tapBehavior -int 1

# Note: the pinch-to-zoom and two-finger-rotate settings here seem to work, but they may
# not be reflected in the System Preferences thing. Running this seems to disable the behavior for
# me, but the boxes are still checked in System Preferences > Trackpad
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad UserPreferences -int 1
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadFiveFingerPinchGesture -int 2
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadPinch -bool false
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadRightClick -int 1
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadRotate -bool false
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadTwoFingerDoubleTapGesture -bool false
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadTwoFingerFromRightEdgeSwipeGesture -int 0
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadThreeFingerDrag -bool true
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadThreeFingerHorizSwipeGesture -int 0
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadThreeFingerTapGesture -int 0
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadThreeFingerVertSwipeGesture -int 0
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadFourFingerHorizSwipeGesture -int 2
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadFourFingerPinchGesture -int 2
defaults-write com.apple.driver.AppleBluetoothMultitouch.trackpad TrackpadFourFingerVertSwipeGesture -int 2

defaults-write com.apple.AppleMultitouchTrackpad UserPreferences -int 1
defaults-write com.apple.AppleMultitouchTrackpad TrackpadRotate -bool false
defaults-write com.apple.AppleMultitouchTrackpad TrackpadPinch -bool false
defaults-write com.apple.AppleMultitouchTrackpad TrackpadThreeFingerDrag -bool true
defaults-write com.apple.AppleMultitouchTrackpad TrackpadTwoFingerDoubleTapGesture -int 0
defaults-write com.apple.AppleMultitouchTrackpad TrackpadTwoFingerFromRightEdgeSwipeGesture -int 0
defaults-write com.apple.AppleMultitouchTrackpad TrackpadThreeFingerHorizSwipeGesture -int 0
defaults-write com.apple.AppleMultitouchTrackpad TrackpadThreeFingerVertSwipeGesture -int 0
defaults-write com.apple.AppleMultitouchTrackpad TrackpadThreeFingerTapGesture -int 0
defaults-write com.apple.AppleMultitouchTrackpad TrackpadFiveFingerPinchGesture -int 2
defaults-write com.apple.AppleMultitouchTrackpad TrackpadFourFingerHorizSwipeGesture -int 2
defaults-write com.apple.AppleMultitouchTrackpad TrackpadFourFingerPinchGesture -int 2
defaults-write com.apple.AppleMultitouchTrackpad TrackpadFourFingerHorizSwipeGesture -int 0
defaults-write com.apple.AppleMultitouchTrackpad TrackpadFourFingerVertSwipeGesture -int 2

defaults-write com.apple.AppleMultitouchTrackpad UserPreferences -int 1

defaults-write com.apple.dock showMissionControlGestureEnabled -bool true
defaults-write com.apple.dock showAppExposeGestureEnabled -bool true
defaults-write com.apple.dock showDesktopGestureEnabled -bool true
defaults-write com.apple.dock showLaunchpadGestureEnabled -bool false

# Smart zoom disabled (this doesn't seem to actually work)
defaults-write com.apple.driver.AppleBluetoothMultitouch.mouse MouseOneFingerDoubleTapGesture -int 0
# Double-tap to define disabled (this doesn't seem to actually work)
defaults-write com.apple.driver.AppleBluetoothMultitouch.mouse MouseTwoFingerDoubleTapGesture -int 0

# Disable “natural” (Lion-style) scrolling
# (In VMware guest VMs, re-enable it, since it doesn't interact well there)
defaults-write NSGlobalDomain com.apple.swipescrolldirection -bool false

# Always show scrollbars
# Possible values: 'WhenScrolling', 'Automatic' and 'Always'
defaults-write NSGlobalDomain AppleShowScrollBars -string "Always"

# Swipe between pages with two fingers
defaults-write NSGlobalDomain AppleEnableSwipeNavigateWithScrolls -bool false

# Enable full keyboard access for all controls
# (e.g. enable Tab in modal dialogs)
defaults-write NSGlobalDomain AppleKeyboardUIMode -int 3

# Use F1, F2, etc. as standard function keys
defaults-write NSGlobalDomain com.apple.keyboard.fnState -bool true

# Analog clock in menu bar
defaults-write com.apple.menuextra.clock IsAnalog -bool true

# Remove duplicates in the “Open With” menu
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill -r -domain local -domain system -domain user

# Increase sound quality for Bluetooth headphones/headsets
defaults-write com.apple.BluetoothAudioAgent "Apple Bitpool Min (editable)" -int 40

###############################################################################
# Screen                                                                      #
###############################################################################

# Require password immediately after sleep or screen saver begins
defaults-write com.apple.screensaver askForPassword -int 1
defaults-write com.apple.screensaver askForPasswordDelay -int 0

# Configure screen saver
# (Careful with this; it seems to break things)
if false; then
  defaults-delete com.apple.screensaver moduleDict
  defaults-write com.apple.screensaver "CleanExit" -string "YES"
  defaults-write com.apple.screensaver "PrefsVersion" -int 100
  defaults-write com.apple.screensaver moduleDict -dict-add "displayName" -string Random
  defaults-write com.apple.screensaver moduleDict -dict-add "moduleName" -string Random
  defaults-write com.apple.screensaver moduleDict -dict-add "path" -string "/System/Library/Screen Savers/Random.saver"
  defaults-write com.apple.screensaver moduleDict -dict-add "type" -int 8
fi

# Shadow in screenshots
defaults-write com.apple.screencapture disable-shadow -bool true

# Spring loading for directories
defaults-write NSGlobalDomain com.apple.springing.enabled -bool false

# Avoid creating .DS_Store files on network volumes
defaults-write com.apple.desktopservices DSDontWriteNetworkStores -bool true

# Desktop wallpaper
osascript -e "tell application \"Finder\" to set desktop picture to POSIX file \"$WALLPAPER_FILE\""

################################################
# Finder & Spotlight
################################################

# Finder: disable window animations and Get Info animations
defaults-write com.apple.finder DisableAllAnimations -bool true

# Finder: show status bar
defaults-write com.apple.finder ShowStatusBar -bool true

# Finder: show path bar
defaults-write com.apple.finder ShowPathbar -bool true

# Do not display tags
defaults-write com.apple.finder ShowRecentTags -boolean false

# Use list view in all Finder windows by default
# Modes: 'Nlsv' = list, 'icnv', `clmv` = column, 'Flwv'
defaults-write com.apple.finder FXPreferredViewStyle -string "Nlsv"

# Set default location for new Finder windows
# For home dir, use "PfHm"
# For desktop, use "PfDe"
# For arbitrary paths, use "PfLo" and `file:///full/path/here/`
defaults-write com.apple.finder NewWindowTarget -string "PfHm"
defaults-write com.apple.finder NewWindowTargetPath -string "file:///Users/$USER/"

# Don't show icons for hard drives, servers, and removable media on the desktop
defaults-write com.apple.finder ShowExternalHardDrivesOnDesktop -bool false
defaults-write com.apple.finder ShowHardDrivesOnDesktop -bool false
defaults-write com.apple.finder ShowMountedServersOnDesktop -bool false
defaults-write com.apple.finder ShowRemovableMediaOnDesktop -bool false

# Finder: show hidden files by default
#defaults-write com.apple.finder AppleShowAllFiles -bool true

# Finder: show all filename extensions
#defaults-write NSGlobalDomain AppleShowAllExtensions -bool true

# Disable the warning before emptying the Trash
defaults-write com.apple.finder WarnOnEmptyTrash -bool false

# Disable the warning when changing a file extension
defaults-write com.apple.finder FXEnableExtensionChangeWarning -bool false

# Spring loading for directories
defaults-write NSGlobalDomain com.apple.springing.enabled -bool false

# Show the ~/Library folder
chflags nohidden ~/Library

# Remove Dropbox’s green checkmark icons in Finder
#file=/Applications/Dropbox.app/Contents/Resources/emblem-dropbox-uptodate.icns
#[ -e "${file}" ] && mv -f "${file}" "${file}.bak"

# Expand the following File Info panes:
# “General”, “Open with”, and “Sharing & Permissions”
defaults-write com.apple.finder FXInfoPanesExpanded -dict \
  General -bool true \
  OpenWith -bool true \
  Privileges -bool true

# Change indexing order and disable some search results
# Yosemite-specific search results (remove them if you are using OS X 10.9 or older):
#   MENU_DEFINITION
#   MENU_CONVERSION
#   MENU_EXPRESSION
#   MENU_SPOTLIGHT_SUGGESTIONS (send search queries to Apple)
#   MENU_WEBSEARCH             (send search queries to Apple)
#   MENU_OTHER
spotlight_items=(
  '{"enabled" = 1;"name" = "APPLICATIONS";}'
  '{"enabled" = 1;"name" = "SYSTEM_PREFS";}'
  '{"enabled" = 1;"name" = "DIRECTORIES";}'
  '{"enabled" = 1;"name" = "PDF";}'
  '{"enabled" = 1;"name" = "CONTACT";}'
  '{"enabled" = 1;"name" = "EVENT_TODO";}'
  '{"enabled" = 1;"name" = "IMAGES";}'
  '{"enabled" = 1;"name" = "MESSAGES";}'
  '{"enabled" = 1;"name" = "DOCUMENTS";}'
  '{"enabled" = 1;"name" = "BOOKMARKS";}'
  '{"enabled" = 1;"name" = "PRESENTATIONS";}'
  '{"enabled" = 0;"name" = "FONTS";}'
  '{"enabled" = 0;"name" = "MUSIC";}'
  '{"enabled" = 0;"name" = "MOVIES";}'
  '{"enabled" = 0;"name" = "SPREADSHEETS";}'
  '{"enabled" = 0;"name" = "SOURCE";}'
  )
# If Yosemite or later:
if [[ $OSX_VERSION == 10.1* ]]; then
  spotlight_items=("${spotlight_items[@]}"
  '{"enabled" = 0;"name" = "MENU_DEFINITION";}' \
  '{"enabled" = 0;"name" = "MENU_OTHER";}' \
  '{"enabled" = 0;"name" = "MENU_CONVERSION";}' \
  '{"enabled" = 0;"name" = "MENU_EXPRESSION";}' \
  '{"enabled" = 0;"name" = "MENU_WEBSEARCH";}' \
  '{"enabled" = 0;"name" = "MENU_SPOTLIGHT_SUGGESTIONS";}'
  )
fi
#TODO: force reindexing if item set was changed
defaults-write com.apple.spotlight orderedItems -array "${spotlight_items[@]}"

################################################
# Safari & WebKit
################################################

# Enable Safari’s debug menu
defaults-write com.apple.Safari IncludeInternalDebugMenu -bool true

# Make Safari’s search banners default to Contains instead of Starts With
defaults-write com.apple.Safari FindOnPageMatchesWordStartsOnly -bool false

# Remove useless icons from Safari’s bookmarks bar
defaults-write com.apple.Safari ProxiesInBookmarksBar "()"

# Enable the Develop menu and the Web Inspector in Safari
defaults-write com.apple.Safari IncludeDevelopMenu -bool true
defaults-write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool true
defaults-write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled -bool true

# Add a context menu item for showing the Web Inspector in web views
defaults-write NSGlobalDomain WebKitDeveloperExtras -bool true

# Safari opens with: A new window
defaults-write com.apple.Safari AlwaysRestoreSessionAtLaunch -bool false

# New windows open with: Empty Page
defaults-write com.apple.Safari NewWindowBehavior -int 1

# New tabs open with: Empty Page
defaults-write com.apple.Safari NewTabBehavior -int 1

# Homepage
defaults-write com.apple.Safari HomePage -string "about:blank"

# Open pages in tabs instead of windows: automatically
defaults-write com.apple.Safari TabCreationPolicy -int 1

# Don't make new tabs active
defaults-write com.apple.Safari OpenNewTabsInFront -bool false

# Command-clicking a link creates tabs
defaults-write com.apple.Safari CommandClickMakesTabs -bool true

# Do not track
defaults-write com.apple.Safari SendDoNotTrackHTTPHeader -bool true

# Don't even ask about the push notifications
defaults-write com.apple.Safari CanPromptForPushNotifications -bool false

# Enable the Develop menu and the Web Inspector in Safari
defaults-write com.apple.Safari IncludeDevelopMenu -bool true
defaults-write com.apple.Safari WebKitDeveloperExtrasEnabledPreferenceKey -bool true
defaults-write com.apple.Safari com.apple.Safari.ContentPageGroupIdentifier.WebKit2DeveloperExtrasEnabled -bool true

# Add a context menu item for showing the Web Inspector in web views
defaults-write NSGlobalDomain WebKitDeveloperExtras -bool true

################################################
# Mail.app
################################################

# Disable send and reply animations in Mail.app
defaults-write com.apple.mail DisableReplyAnimations -bool true
defaults-write com.apple.mail DisableSendAnimations -bool true

# Copy email addresses as `foo@example.com` instead of `Foo Bar <foo@example.com>` in Mail.app
defaults-write com.apple.mail AddressesIncludeNameOnPasteboard -bool false

# Add the keyboard shortcut ⌘ + Enter to send an email in Mail.app
defaults-write com.apple.mail NSUserKeyEquivalents -dict-add "Send" -string "@\\U21a9"

################################################
# iTerm2
################################################

# Don’t display the annoying prompt when quitting iTerm
defaults-write com.googlecode.iterm2 PromptOnQuit -bool false
# Load preferences from custom folder
CHANGED=0
function update_iterm_prefs() {
local ITERM_PREFS_DIR="$DOTFILES_REPO_PATH/iTerm2/$ITERM_PREFERENCES_SET"
if [[ ! -d "$ITERM_PREFS_DIR" ]]; then
  echo >&2 "WARNING: Not updating iTerm2 shared prefs dir because dir does not exist: '$ITERM_PREFS_DIR'"
  return
fi
if pgrep -q iTerm; then
  if [[ $(defaults read com.googlecode.iterm2 PrefsCustomFolder) != "$ITERM_PREFS_DIR" ]]; then
    echo >&2 "WARNING: Cannot change iTerm2 preferences shared folder while iTerm2 is running."
    echo >&2 "WARNING: iTerm2 preferences folder was not updated."
  fi
else
  defaults-write com.googlecode.iterm2 PrefsCustomFolder "$ITERM_PREFS_DIR"
fi
defaults-write com.googlecode.iterm2 LoadPrefsFromCustomFolder -bool true
}
update_iterm_prefs

################################################
# Time Machine
################################################

# Prevent Time Machine from prompting to use new hard drives as backup volume
defaults-write com.apple.TimeMachine DoNotOfferNewDisksForBackup -bool true

################################################
# Activity Monitor
################################################

# Show all processes in Activity Monitor
defaults-write com.apple.ActivityMonitor ShowCategory -int 0

# Update Frequency: Often (2 sec)
defaults-write com.apple.ActivityMonitor UpdatePeriod -int 2

################################################
# Tweetbot
################################################

# Display only username
defaults-write com.tapbots.TweetbotMac displayNameType -int 1

# Don't pin timeline to top
defaults-write com.tapbots.TweetbotMac streamingPinToTopEnabled -bool false

# No sounds
defaults-write com.tapbots.TweetbotMac soundType -int 2

# Image Thumbnails: Small
defaults-write com.tapbots.TweetbotMac statusViewImageType -int 1

# Bypass the annoyingly slow t.co URL shortener
defaults-write com.tapbots.TweetbotMac OpenURLsDirectly -bool true

################################################
# Terminal.app
################################################

# Create a "Basic Improved" profile based on "Basic"
improved=":Window\ Settings:Basic\ Improved"
terminalPrefsFile="${HOME}/Library/Preferences/com.apple.Terminal.plist"
# Assume any existing "Improved" profile is set up correctly
if ! $plistbuddy -c "Print $improved" "$terminalPrefsFile" &>/dev/null; then
  $plistbuddy -c "Copy :Window\ Settings:Basic $improved" "$terminalPrefsFile"
  $plistbuddy -c "Set $improved:name Basic\ Improved" "$terminalPrefsFile"
  # Close if the shell exited cleanly
  $plistbuddy -c "Add $improved:shellExitAction integer 1" "$terminalPrefsFile"
  # Make the window a bit larger
  $plistbuddy -c "Add $improved:columnCount integer 100" "$terminalPrefsFile"
  $plistbuddy -c "Add $improved:rowCount integer 30" "$terminalPrefsFile"
fi

CHANGED=0

# Set "Basic Improved" as the default profile
defaults-write com.apple.Terminal "Startup Window Settings" -string "Basic Improved"
defaults-write com.apple.Terminal "Default Window Settings" -string "Basic Improved"

# Open with: default login shell
defaults-write com.apple.Terminal Shell -string ""

# Disable the line/prompt marker display (El Capitan+)
defaults-write com.apple.Terminal ShowLineMarks -bool false

if [[ $CHANGED == 1 ]]; then
  CFPreferencesAppSynchronize "com.apple.Terminal"
fi

################################################
# Miscellaneous
################################################

# Use plain text mode for new TextEdit documents
defaults-write com.apple.TextEdit RichText -int 0
# Open and save files as UTF-8 in TextEdit
defaults-write com.apple.TextEdit PlainTextEncoding -int 4
defaults-write com.apple.TextEdit PlainTextEncodingForWrite -int 4

# Enable the debug menu in Disk Utility
defaults-write com.apple.DiskUtility DUDebugMenuEnabled -bool true
defaults-write com.apple.DiskUtility advanced-image-options -bool true

# Enable Debug Menu in the Mac App Store
defaults-write com.apple.appstore ShowDebugMenu -bool true

# Enable the WebKit Developer Tools in the Mac App Store
defaults-write com.apple.appstore WebKitDeveloperExtras -bool true

# UI sound effects
# (requires logout and some time to take effect)
defaults-write com.apple.systemsound com.apple.sound.uiaudio.enabled -int 0

################################################
# Google Chrome & Google Chrome Canary
################################################

# Disable the all too sensitive backswipe on trackpads
defaults-write com.google.Chrome AppleEnableSwipeNavigateWithScrolls -bool false
defaults-write com.google.Chrome.canary AppleEnableSwipeNavigateWithScrolls -bool false

# Disable the all too sensitive backswipe on Magic Mouse
defaults-write com.google.Chrome AppleEnableMouseSwipeNavigateWithScrolls -bool false
defaults-write com.google.Chrome.canary AppleEnableMouseSwipeNavigateWithScrolls -bool false

# Use the system-native print preview dialog
defaults-write com.google.Chrome DisablePrintPreview -bool true
defaults-write com.google.Chrome.canary DisablePrintPreview -bool true

# Expand the print dialog by default
defaults-write com.google.Chrome PMPrintingExpandedStateForPrint2 -bool true
defaults-write com.google.Chrome.canary PMPrintingExpandedStateForPrint2 -bool true

# No birthdays in Calendar
defaults-write com.apple.iCal "display birthdays calendar" -bool false

################################################
# Transmission.app
################################################

# Hide the donate message
defaults-write org.m0k.transmission WarningDonate -bool false
# Hide the legal disclaimer
defaults-write org.m0k.transmission WarningLegal -bool false

################################################
# Sublime Text
################################################

ST2_PREFS_DIR="$HOME/Library/Application Support/Sublime Text 2"
mkdir -p "$ST2_PREFS_DIR/Packages/User"
cp "$MYDIR/../manual-settings/Sublime Text 2/Preferences.sublime-settings" "$ST2_PREFS_DIR/Packages/User"
mkdir -p "$ST2_PREFS_DIR/Settings"
ST2_LICENSE_FILE="$SERIALS_DIR/Sublime Text 2 license.txt"
if [[ -e "$ST2_LICENSE_FILE" ]]; then
  cp "$ST2_LICENSE_FILE" "$ST2_PREFS_DIR/Settings/License.sublime_license"
fi

################################################
# BBEdit
################################################

BBEDIT_SERIAL_FILE="$SERIALS_DIR/BBEdit 11 license.txt"
if [[ -e "$BBEDIT_SERIAL_FILE" ]]; then
  BBEDIT_SERIAL=$(cat "$BBEDIT_SERIAL_FILE")
  defaults-write com.barebones.bbedit BBEditSerialNumber:11.0 "$BBEDIT_SERIAL"
fi

# I configure BBEdit for editing prose documents instead of source code.
# People using BBEdit as a code editor will probably want different settings.

# Do not check spelling as you type
defaults-write com.barebones.bbedit EditorCheckSpellingAsYouType 0
# Soft wrap text
defaults-write com.barebones.bbedit EditorSoftWrap 1
# Soft wrap at window width (not page guide or fixed column)
defaults-write com.barebones.bbedit SoftWrapStyle 2
# Disable Emacs key binding emulation
defaults-write com.barebones.bbedit EmulateEmacsKeyBindings 0
# Home and End move to beginning and end of line
defaults-write com.barebones.bbedit HomeAndEndKeys 2
# Disable insertion point highlighting
defaults-write com.barebones.bbedit HighlightInsertionPoint 0
# Disable page guide
defaults-write com.barebones.bbedit EditingWindowShowPageGuide 0
# Do nothing on startup (not open a new document)
defaults-write com.barebones.bbedit StartupAndResumeAction 1
# Autocomplete only on manual request (not after pause in typing)
defaults-write com.barebones.bbedit TextCompletionTrigger 2
# Ensure trailing line break
defaults-write com.barebones.bbedit EnsureTrailingLineBreak 1

# Some of the BBEdit preferences are blobs or complex lists. We don't set those,
# so you'll still need to do some manual configuration of: 
#  * font  (I like Helvetica Neue)
#  * hidden menus  (I disable all development menus)
#  * selected color scheme (because it includes a full path) (I like BBEdit Light)

################################################
# F.lux
################################################

defaults-write org.herf.Flux disable-com.apple.Aperture -int 1
defaults-write org.herf.Flux lateColorTemp -int 3500
defaults-write org.herf.Flux lateLoc -int 0
defaults-write org.herf.Flux location -int 11231
defaults-write org.herf.Flux locationTextField -string "11231"
defaults-write org.herf.Flux locationType -string "Z"
defaults-write org.herf.Flux nightColorTemp -float 4030
defaults-write org.herf.Flux steptime -int 40
defaults-write org.herf.Flux wakeTime -int 600

################################################
# Rubymine
################################################

mkdir -p ~/local/RubymineProjects
if [[ ! -e "$HOME/local/RubymineProjects/Homebrew-local" ]]; then
  if [[ -e "$MANUAL_SETTINGS_PATH/Rubymine/rubymine-homebrew-local.tgz" ]]; then
    (
      cd ~/local/RubymineProjects || return
      tar xf "$MANUAL_SETTINGS_PATH/Rubymine/rubymine-homebrew-local.tgz"
    )
  fi
fi

################################################
# Oh My Zsh
################################################

"$MYDIR"/src/setup-ohmyzsh

################################################
# Prezto
################################################

if [[ -d "$HOME/Dropbox/#repos/prezto" ]]; then
  ln -s "$HOME/Dropbox/#repos/prezto" "$HOME/.zprezto"
elif [[ -d "$HOME/repos/prezto" ]]; then
  ln -s "$HOME/repos/prezto" "$HOME/.zprezto"
else
  echo "No prezto repo found; not linking to ~/.zprezto."
fi

################################################
# File associations
################################################

if which duti >/dev/null; then
  if [[ -e "/Applications/BBEdit.app" ]]; then 
    duti -s com.barebones.bbedit .txt all
  fi
else
  echo "WARNING: duti is not installed. Not setting file associations."
fi

################################################
# My conventional directories
################################################

mkdir -p ~/local
mkdir -p ~/local/opp
mkdir -p ~/local/RubymineProjects

################################################
# VM Guest specific stuff
################################################

# User settings for when running as a guest inside a VM

if pkgutil --pkg-info com.vmware.tools.macos.pkg.files &>/dev/null; then
  # Re-enable “natural” (Lion-style) scrolling
  # This will end up having old-style scrolling in effect, because of interaction
  # with the host's scrolling setup and/or the VM's mouse driver
  defaults-write NSGlobalDomain com.apple.swipescrolldirection -bool true
fi

################################################
# Kill affected applications
################################################

if [[ $DO_KILL == 1 ]]; then
  for app in "Activity Monitor" "Address Book" "Calendar" "Contacts" "cfprefsd" \
      "Dock" "Finder" "Google Chrome" "Google Chrome Canary" "Mail" "Messages" \
      "Opera" "Safari" "SizeUp" "Spectacle" "SystemUIServer" \
      "Transmission" "Twitter" "iCal"; do
    killall "${app}" > /dev/null 2>&1; true
  done
fi

if [[ $ANY_CHANGED == 1 ]]; then 
  echo "Done. Some of these changes may require a logout/restart to take effect."
fi

}

function parse_cli() {
  local arg

  while [[ $# -ge 1 ]]; do
    arg="$1"; shift
    case "$arg" in
      --kill | -k)                  DO_KILL=1 ;;
      --trace | -x)                 OPT_TRACE=1 ;;
      *)
        jxl::std_opt "$arg" \
            || die "Unexpected argument: ${arg}. See '$PROGRAM_NAME --help' for usage"
        if [[ $_JXL_WANT_HELP == 1 ]]; then usage; exit 0; fi
        ;;
    esac
  done

  readonly DO_KILL OPT_TRACE
}

function CFPreferencesAppSynchronize() {
  /usr/bin/python - <<END
from Foundation import CFPreferencesAppSynchronize
CFPreferencesAppSynchronize('$1')
END
}

function changed-something() {
  # This can be reset locally to track groups of changes
  CHANGED=1
  # Don't reset this; it should reflect if any change was made the whole run
  ANY_CHANGED=1
}

function v_echo() {
  # --verbose is JXL's now, so ask it rather than keeping a second copy of the flag.
  if is_verbose; then
    echo "$@"
  fi
}

# Conditionally do a defaults-write
function defaults-write() {
  local domain=$1; key=$2; shift 2
  local value value_type current expected
  if [[ ${1:0:1} == '-' ]]; then
    value="$2"; value_type="${1:1}"
  else
    value="$1"; value_type=string
  fi
  current=$(defaults read "$domain" "$key" 2>/dev/null)
  #echo "current is '$current', want '$value'"
  # booleans are written as true/false, but read back as 1/0
  if [[ "$value_type" == bool ]]; then
    if [[ "$value" == true ]]; then expected=1; else expected=0; fi
  else
    expected="$value"
  fi
  # This changed-value check is not perfect; it gets false positives for complex types
  if [[ "$current" == "$expected" ]]; then
    v_echo "defaults-write: $domain $key is already set: $current"
  else
    defaults write "$domain" "$key" "$@"
    v_echo "defaults-write: wrote defaults $domain $key: $value"
    changed-something
  fi
}

# Delete a default quietly and idempotently
function defaults-delete() {
  local domain="$1"
  local key="$2"
  if defaults read "$domain" "$key" &>/dev/null; then
    defaults delete "$domain" "$key"
    v_echo "Deleted defaults $domain $key"
    changed-something
  else
    v_echo "defaults $domain $key is already deleted"
  fi
}

function remove-dock-persistent-app() {
  local file_label=$1
  local dockPrefsPlistFile ix
  dockPrefsPlistFile="$HOME/Library/Preferences/com.apple.dock.plist"
  ix=$(defaults read com.apple.dock persistent-apps | grep file-label | awk "/$file_label/  {print NR}")
  if [[ -n "$ix" ]]; then
    ix=$(( ix - 1 ))
    /usr/libexec/PlistBuddy -c "Delete persistent-apps:$ix" "$dockPrefsPlistFile"
    v_echo "Deleted persistent Dock app $file_label"
    changed-something
  fi
}

parse_cli "$@"

if [[ $OPT_TRACE == 1 ]]; then
  set -x
fi

main
exit 0
