diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..10f9a50 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,20 @@ +Scripts +======= + +Handy scripts for ease of use + +* applygitconfig - Treat the contents of stdin as a gitconfig file and apply + them to the global config (~/.gitconfig) +* backup - Folder backup utility script +* beep - Sound a beep after executing the given command line +* deploy - Deploy a set of files from a git repository to a destination folder +* dircolortest - Test the contents of stdin as a .dir_colors file +* git-branch-parent - Attempt to determine the branch root SHA +* mkiso - Make ISO file from CD/DVD image suitable for burning +* mkpasswd - Generate a random alphanumeric password of any length +* mlog - Logging utility script +* note - Note taking utility script +* settitle - Set the terminal/tmux window title +* smartwd - Print the current working directory for the command prompt +* stardate - Print the current Stardate + diff --git a/scripts/applygitconfig b/scripts/applygitconfig new file mode 100755 index 0000000..dab208e --- /dev/null +++ b/scripts/applygitconfig @@ -0,0 +1,27 @@ +#!/usr/bin/env perl +# Script to apply git configuration to global gitconfig + +my $section = 'unknown'; +my $variable; +my $value; +my $command; + +while(<>) { + chomp; + if (m/^\[(\w+)\]$/) { + $section = $1; + #print "Section: $section\n"; + } elsif (m/^\[(\w+) +"(\w+)"\]/) { + $section = "$1.$2"; + #print "Section: $section\n"; + } elsif (m/(\w+) += +(.+)$/) { + $variable = $1; + $value = $2; + + $value =~ s/"/\\"/g; + #print "\t$section.$variable = \"$value\"\n"; + $command = "git config --global $section.$variable \"$value\""; + print "$command\n"; + system($command); + } +} diff --git a/scripts/backup b/scripts/backup new file mode 100755 index 0000000..60b7a82 --- /dev/null +++ b/scripts/backup @@ -0,0 +1,202 @@ +#!/bin/bash +# Script to backup folders to either a tarball or a Git repository +# Script expects to run at most on a daily basis. Any faster, and you risk +# overwriting a previous backup. + +# Default environment variables used +BACKUP_METHOD=git +BACKUP_TS=$(date +%F) +BACKUP_DEBUG=false +BACKUP_SRC='' +BACKUP_DST='' +BACKUP_DB='' + +APP=$(basename $0) + +# Usage function will display the usage +usage() +{ + local backup=$APP + local exit_code=$1 + + [[ -z $exit_code ]] && exit_code=0 + + echo "Usage: $backup [options] " + echo "Options:" + echo " -s tar Save to a tarball, format is backup-%Y-%m-%d.tar.gz" + echo " This is the default." + echo " -s git Save to a git repository and tag the commit" + echo + echo " -t Specify the path to save the backup to. If omitted," + echo " it defaults to ~/backups/\$(basename )" + echo + echo " -d Specify a MySQL database to backup in addition to" + echo " the files in the source path. This requires you to" + echo " save the MySQL root password in ~/.my.cnf" + echo + echo " -h Display this help message" + + exit $exit_code +} + +# Die function will print the error message to stderr and abort the script +die() +{ + local exit_code=$1 + local backup=$APP + shift + + for msg in "$@" + do + echo -e "$backup: $msg" >&2 + done + + exit $exit_code +} + +# Sanity check +backup_sanity() +{ + if [[ -z $BACKUP_SRC ]] + then + die 1 "Need to specify a source" + fi + + # Run basic sanity checks on env variables + if [[ -z $BACKUP_DST ]] + then + BACKUP_DST=$HOME/backups/$(basename $BACKUP_SRC) + fi + + mkdir -p $BACKUP_DST + if [[ $? != 0 ]] + then + die 2 "Error creating backup folder" + fi +} + +# Retrieve data using rsync +backup_data() +{ + # Don't rsync if we are using tar as the backup method + if [[ "$BACKUP_METHOD" != "tar" ]] + then + rsync -a $BACKUP_SRC $BACKUP_DST + + if [[ $? != 0 ]] + then + die 2 "Error syncing data from source $BACKUP_SRC" + fi + fi +} + +# Backup the database +backup_db() +{ + if [[ ! -z $BACKUP_DB ]] + then + # Dump using mysqldump + mysqldump -u root $BACKUP_DB >$BACKUP_DST/$BACKUP_DB.sql 2>/dev/null + + if [[ $? != 0 ]] + then + die 2 "Error dumping database $BACKUP_DB" + fi + fi +} + +# Save the files to git repo or tarball +backup_save() +{ + if [[ "$BACKUP_METHOD" == "tar" ]] + then + cd $BACKUP_SRC + local daily=$BACKUP_DST/backup-daily-$BACKUP_TS.tar.gz + tar czf $daily . + + # Weekly tarballs every Sunday + if [[ $(date +%w) == "0" ]] + then + local weekly=$BACKUP_DST/backup-weekly-$(date +%Y-%U).tar.gz + ln $daily $weekly + fi + + # Monthly tarballs on the first of every month + if [[ $(date +%-d) == "1" ]] + then + local monthly=$BACKUP_DST/backup-monthly-$(date +%Y-%m).tar.gz + ln $daily $monthly + fi + else + cd $BACKUP_DST + git init -q + git config core.safecrlf false + git add . + git commit -m "Backup of $BACKUP_SRC on $BACKUP_TS" + git tag -am "Daily ($BACKUP_TS) backup of $BACKUP_SRC" daily-$BACKUP_TS + + # Weekly tags every Sunday + if [[ $(date +%w) == "0" ]] + then + local week=$(date +%Y-%U) + git tag -am "Weekly ($week) backup of $BACKUP_SRC" weekly-$week + fi + + # Monthly tags on the first of every month + if [[ $(date +%-d) == "1" ]] + then + local month=$(date +%Y-%m) + git tag -am "Monthly ($month) backup of $BACKUP_SRC" monthly-$month + fi + fi +} + +while getopts :hs:t:d: OPTION +do + case $OPTION in + h) + # Help + usage 0 + ;; + + s) + # Backup method + if [[ "$OPTARG" == "git" || "$OPTARG" == "tar" ]] + then + BACKUP_METHOD=$OPTARG + else + die 1 "Backup method must be one of git or tar" + fi + ;; + t) + # Target folder + BACKUP_DST=$OPTARG + ;; + + d) + # Database + BACKUP_DB=$OPTARG + ;; + + :) + # Missing required argument + die 1 "Missing argument for option -$OPTARG" + ;; + + \?) + # Invalid option + die 1 "Invalid option: -$OPTARG" + ;; + + esac +done + +# Shift away the options +shift $(($OPTIND - 1)) + +BACKUP_SRC=$1 +backup_sanity +backup_data +backup_db +backup_save + diff --git a/scripts/beep b/scripts/beep new file mode 100755 index 0000000..4739c4d --- /dev/null +++ b/scripts/beep @@ -0,0 +1,8 @@ +#!/bin/bash + +if [[ $# -gt 0 ]] +then + eval "$@" +fi + +echo -e "\007" diff --git a/scripts/deploy b/scripts/deploy new file mode 100755 index 0000000..fb16888 --- /dev/null +++ b/scripts/deploy @@ -0,0 +1,195 @@ +#!/bin/bash +# Script to copy files from a Git repository to a destination +# Reads deployment instructions from a file and acts accordingly +# +# File Format +# =========== +# +# Comments begin with a # character and terminate at the end of the line. +# +# The keyword 'repo' specifies the path to the repository. The repository must +# be accessible locally without having to resort to ssh, https or git protocols. +# Usage: repo +# +# The keyword 'target' specifies the location to which to deploy. If omitted, it +# defaults to the current folder. Folders can be specified relative to the +# current folder, relative to the home directory, or relative to the root, using +# ./ or ../, ~/ and / as prefixes respectively. The parameter must be a valid +# directory. +# Usage: target +# +# The keyword 'file' specifies the file location relative to the root of the +# Git repository, along with the version to install and an optional rename +# argument which allows you to rename the destination file. If the version is +# omitted, it defaults to HEAD. If the rename-to parameter is omitted, the +# filename is the same as the name within the repository. +# Usage: file [version [rename-to]] + +# Default environment variables used +DEPLOY_GIT='' +DEPLOY_TGT=$(pwd) +DEPLOY_SRC='' +DEPLOY_LST='' +DEPLOY_DEBUG=false + +# Usage function will display the usage +usage() +{ + local deploy=$(basename $0) + echo "Usage: $deploy ..." + exit 0 +} + +# Die function will print the error message to stderr and abort the script +die() +{ + local exit_code=$1 + local deploy=$(basename $0) + shift + + for msg in "$@" + do + echo -e "$deploy: $msg" >&2 + done + + if [[ $exit_code != 128 && $exit_code != 0 ]] + then + echo -e "\tError in file $DEPLOY_SRC line ${BASH_LINENO[1]}" >&2 + fi + + exit $exit_code +} + +# Debug function will display all data, but only if debugs are enabled +debug() +{ + $DEPLOY_DEBUG && echo "$@" +} + +# Repo function checks if it is a valid Git repo and sets the DEPLOY_GIT +repo() +{ + if [[ $# != 1 ]] + then + die 4 "Invalid usage of repo command" "Usage: repo " + fi + + if [[ -d "$1" ]] + then + cd "$1" + local gtl=$(git rev-parse --show-toplevel 2>/dev/null) + + if [[ -z $gtl ]] + then + die 3 "Path $1 is not a valid Git repository!" + else + debug "Using repository $gtl" + DEPLOY_GIT="$gtl" + fi + else + die 1 "Path $1 does not exist!" + fi +} + +# Target function checks if it is a valid directory and sets the DEPLOY_TGT +target() +{ + if [[ $# != 1 ]] + then + die 4 "Invalid usage of target command" "Usage: target " + fi + + if [[ -d "$1" ]] + then + debug "Target folder $1" + DEPLOY_TGT="$1" + else + die 1 "Path $1 does not exist!" + fi +} + +# File command selects a file to deploy +file() +{ + if [[ $# == 0 || $# > 3 ]] + then + die 4 "Invalid usage of file command" \ + "Usage: file [ [] ]" + fi + + if [[ -z $DEPLOY_GIT ]] + then + die 2 "Must specify repo before file!" + fi + + if [[ -z $DEPLOY_TGT ]] + then + die 2 "Must specify target before file!" + fi + + local file=$1 + local ver=$2 + local rename=$3 + + debug "file $@" + + # Sanity check on ver + [[ -z $ver ]] && ver=HEAD + + # Sanity check on rename + [[ -z $rename ]] && rename=$(basename $file) + + cd $DEPLOY_GIT + + # Check to make sure that version is a sane version + git rev-parse $ver &>/dev/null + + if [[ $? != 0 ]] + then + die 3 "Version $ver does not exist in the repository $DEPLOY_GIT" + fi + + local vercheck=$(git rev-parse $ver 2>/dev/null) + debug "Using version $vercheck" + + # Check to make sure that the file is valid in the specified version + git show $vercheck:$file &>/dev/null + + if [[ $? != 0 ]] + then + die 3 "File $file does not exist in version $ver of the repo $DEPLOY_GIT" + else + debug "Using file $file" + # Build the commands to extract the file and set the + # executable permissions bit in the deployed file. + local cmd="cd $DEPLOY_GIT" + cmd="$cmd; git show $vercheck:$file > $DEPLOY_TGT/$rename" + cmd="$cmd; chmod +x $DEPLOY_TGT/$rename;" + DEPLOY_LST="$DEPLOY_LST $cmd" + fi + +} + +if [[ $# == 0 ]] +then + usage +else + for i in "$@" + do + if [[ -f $i && -r $i ]] + then + DEPLOY_SRC=$i + source $i + else + die 128 "Deploy file $i does not exist or is not readable!" + fi + done +fi + +if [[ ! -z $DEPLOY_LST ]] +then + eval $DEPLOY_LST +else + die 0 "No files to deploy!" +fi + diff --git a/scripts/dircolortest b/scripts/dircolortest new file mode 100755 index 0000000..d79d412 --- /dev/null +++ b/scripts/dircolortest @@ -0,0 +1,56 @@ +#!/usr/bin/perl +# A utility script to test out dircolors settings without reloading +# Usage: dircolortest + +if ($#ARGV < 0) { + die "Usage: $0 \n"; +} + +if ($#ARGV > 0) { + warn "Ignoring additional command line arguments\n"; +} + +# Open the file and get the handle +open DCFILE, $ARGV[0] or + die "Cannot open dircolors file $ARGV[0]! $!\n"; + +$line_counter = 0; + +while ($line = ) { + chomp $line; + + # Strip off any comments + $line =~ s/#.*$//; + + # Strip off leading and trailing whitespace + $line =~ s/^\s*//; + $line =~ s/\s*$//; + + if ($line ne '') { + ($type, $format) = split /\s+/, $line; + + # Ignore the following lines, we don't care about them here + next if (($type eq 'TERM') || ($type eq 'COLOR') || + ($type eq 'OPTIONS') || ($type eq 'EIGHTBIT')); + + # Just a little enhancement, if the type begins with a . + if ($type =~ m/^\./) { + $type = "*$type"; + } + + print "\033[${format}m$type\033[m"; + + $line_counter = $line_counter + 1; + + if ($line_counter == 8) { + print "\n"; + $line_counter = 0; + } else { + print "\t"; + } + } +} + +print "\n" if ($line_counter != 0); + +close DCFILE; diff --git a/scripts/git/git-branch-parent b/scripts/git/git-branch-parent new file mode 100755 index 0000000..f83767f --- /dev/null +++ b/scripts/git/git-branch-parent @@ -0,0 +1,28 @@ +#!/bin/bash +# +# Support script to find the commit from which the given branch was spawned. +# Takes one or two arguments, the first argument is mandatory and specifies +# the child branch while the second argument is optional and specifies the +# parent branch. If omitted, the parent branch defaults to 'master' + +CHILD=$1 +PARENT=$2 + +USAGE="Usage: $0 " + +if [ "$CHILD" == "" ] +then + echo $USAGE + exit +fi + +if [ "$PARENT" == "" ] +then + PARENT="master" +fi + +PCOMMIT=`diff -u <(git rev-list --first-parent $CHILD) \ + <(git rev-list --first-parent $PARENT) | sed -ne 's/^ //p' | head -1` + +git show --pretty="%H %an | %s" $PCOMMIT | head -1 + diff --git a/scripts/mkcscope b/scripts/mkcscope new file mode 100755 index 0000000..c8c202e --- /dev/null +++ b/scripts/mkcscope @@ -0,0 +1,207 @@ +#!/bin/bash +# Script to create cscope.out file for any workspace +# Script expects to see a .mkcscope.conf file in either the current working +# directory or in your $HOME. The format of the file is as follows: +# +# This is essentially a Bash script, using a structured language as follows: +# target foo bar +# desc Description for foo +# files +# +# The above segment shows a sample target 'foo', which depends on a different +# target 'bar'. The desc line is a description for use in the help, while the +# files command specifies a directory relative to the current directory and +# the file patterns to search for and add to the cscope file list. The script +# expects to run from the base folder for the project workspace, and the +# directories in the files command are relative to this base folder. +# +# Example: +# -------- +# target tmux ncurses +# desc tmux Source code +# files tmux *.[ch] *.[cpp] +# +# target ncurses +# desc ncurses source code +# files ncurses *.[ch] + +APP=$(basename $0) +VERSION='1.0.1' +MAKEFILE=/dev/null +CONFFILE='.mkcscope.conf' + +declare -a TARGETS=() + +usage() +{ + echo "$APP v$VERSION" + echo "Usage: $APP [options] " + echo + echo "Options:" + echo "--------" + echo " -h Show this help screen" + echo " -l List targets" + echo " -r Rebuild cscope DB without regenerating files" + echo " -c Create a blank config file in the current directory" + echo +} + +files() +{ + local dir=$1 + shift + for patt in "$@" + do + echo -e "\t@find $PWD/$dir -name \"$patt\" -print >> $CSCOPE_FILES" >> $MAKEFILE + done +} + +desc() +{ + echo -e "\t@echo $@" >> $MAKEFILE +} + +target() +{ + local tgt=$1 + shift + + echo "$tgt: $@" >> $MAKEFILE + + TARGETS=(${TARGETS[@]} $tgt) +} + +list_targets() +{ + echo "Supported targets:" + echo "------------------" + for tgt in ${TARGETS[@]} + do + echo " - $tgt" + done +} + +gen_makefile() +{ + MAKEFILE=$(mktemp --tmpdir cscope-$USER-XXXXXXXX.mk) + CSCOPE_FILES=$PWD/cscope.files +} + +gen_cscope() +{ + cscope -bqv +} + +gen_targets() +{ + set -f + + if [[ -r "$PWD/$CONFFILE" ]] + then + source "$PWD/$CONFFILE" + elif [[ -r "$HOME/$CONFFILE" ]] + then + source "$HOME/$CONFFILE" + else + echo "Unable to find a configuration file!" >&2 + echo "Expect to find a $CONFFILE in either of:" >&2 + echo " $PWD" >&2 + echo " $HOME" >&2 + exit 1 + fi +} + +gen_config() +{ + (cat <<-EOM +# Configuration for mkcscope +# This is essentially a Bash script, using a structured language as follows: +# target foo bar +# desc Description for foo +# files +# +# The above segment shows a sample target 'foo', which depends on a different +# target 'bar'. The desc line is a description for use in the help, while the +# files command specifies a directory relative to the current directory and +# the file patterns to search for and add to the cscope file list. The script +# expects to run from the base folder for the project workspace, and the +# directories in the files command are relative to this base folder. + +# Sample configuration +# target foo bar +# desc Target 'foo' depends on 'bar' +# # Files are in the folder foo relative to \$PWD +# files foo *.[ch] *.cpp +# +# target bar baz +# desc Target 'bar' depends on 'baz' +# # Multiple files +# files bar/folder1 *.s +# files bar/folder2 *.h +# +# target baz +# desc Target 'baz' does not depend on anything +# files baz/*.c + +EOM + ) > "$PWD/$CONFFILE" +} + +cleanup() +{ + rm $MAKEFILE +} + +trap cleanup "EXIT" + +gen_makefile +gen_targets + +while getopts "hlrc" OPTION +do + case $OPTION in + h) + usage + exit 0 + ;; + + l) + list_targets + exit 0 + ;; + + r) + echo "Rebuilding existing cscope database" + gen_cscope + exit 0 + ;; + + c) + echo "Creating blank configuration" + gen_config + exit 0 + ;; + + \?) + echo "Invalid option -$OPTARG" + exit 1 + ;; + esac +done + +shift $(($OPTIND - 1)) + +if [[ -n "$1" ]] +then + rm -f $CSCOPE_FILES + make -f $MAKEFILE "$@" + + if [[ ! -s $CSCOPE_FILES ]] + then + echo "$APP: Must specify targets to generate file list!" >&2 + exit 1 + fi + + gen_cscope +fi + diff --git a/scripts/mkiso b/scripts/mkiso new file mode 100755 index 0000000..ac84873 --- /dev/null +++ b/scripts/mkiso @@ -0,0 +1,72 @@ +#!/bin/bash +# Make an ISO/Joliet compatible image from a CDR image on OS X +# Developed based on http://forums.macrumors.com/showthread.php?t=220740 + +APP=$(echo $0 | sed 's#^.*/##') + +usage() +{ + echo " +$APP converts an image into ISO/Joliet compatible format suitable for +burning onto a CD/DVD and having it cross-compatible with Win32/OSX/*NIX + +Usage: $APP [-o ] +" +} + +while getopts :ho: OPTION +do + case $OPTION in + h) + # Help + usage + exit 0 + ;; + + o) + # Output file + OUTFILE=$OPTARG + ;; + + :) + # Missing required argument + echo "$APP: Missing argument for option -$OPTARG" >&2 + exit 1 + ;; + + \?) + # Invalid option + echo "$APP: Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac +done + +# Shift away the options +shift $(($OPTIND - 1)) + +INFILE=$1 + +if [[ -z $INFILE ]] +then + usage + exit 1 +fi + +if [[ ! -r $INFILE ]] +then + echo "$APP: Unable to read input file $INFILE" >&2 + exit 1 +fi + +if [[ -z $OUTFILE ]] +then + OUTFILE=$(echo $INFILE | sed -E 's#\.[^\.]+$#\.iso#') +fi + +echo "Input file = $INFILE" +echo "Output file = $OUTFILE" + +hdiutil makehybrid -iso -joliet -o "$OUTFILE" "$INFILE" + +exit $? diff --git a/scripts/mkpasswd b/scripts/mkpasswd new file mode 100755 index 0000000..5039351 --- /dev/null +++ b/scripts/mkpasswd @@ -0,0 +1,5 @@ +#!/bin/bash + +len=$1 +[[ "$len" == "" ]] && len=16 +LC_CTYPE=C tr -dc "[:alnum:]" < /dev/urandom | head -c ${len} | xargs diff --git a/scripts/mlog b/scripts/mlog new file mode 100755 index 0000000..b9e3444 --- /dev/null +++ b/scripts/mlog @@ -0,0 +1,52 @@ +#!/bin/bash +# Monthly logging script +# Call mlog and it will update a log file + +# Set the default mlog folder +[[ -z $MLOG_FOLDER ]] && MLOG_FOLDER="$HOME/mlog" + +# Make sure that the folder exists +[[ ! -d $MLOG_FOLDER ]] && mkdir -pv $MLOG_FOLDER + +# Make sure that we have a valid TMPDIR +[[ -z $TMPDIR ]] && TMPDIR='/tmp' + +# Make sure that we have a valid EDITOR +[[ -z $EDITOR ]] && EDITOR=vim + +MLOG_HDR='' +MLOG_TS="[$(date)]" +MLOG_LOG="$MLOG_FOLDER/$(date +%Y-%m)" +MLOG_FILE="$TMPDIR/mlog-tmp-$$" + +if [[ -x $HOME/bin/stardate ]] +then + [[ -z $MLOG_RANK ]] && MLOG_RANK='Chief Engineer' + + MLOG_HDR=`echo "$MLOG_RANK's log, Stardate $($HOME/bin/stardate)" | sed 's/.$//'` + + if [[ -e $MLOG_LOG ]] + then + MLOG_LAST=$(grep Stardate $MLOG_LOG | tail -1) + + if [[ "$MLOG_LAST" == "$MLOG_HDR" ]] + then + MLOG_HDR="$MLOG_RANK's log, supplemental" + fi + fi +fi + +$EDITOR $MLOG_FILE + +[[ ! -s $MLOG_FILE ]] && rm -f $MLOG_FILE && exit 0 + + +echo "$MLOG_HDR" >> $MLOG_LOG +echo "$MLOG_TS" >> $MLOG_LOG +echo >> $MLOG_LOG # Empty line +cat $MLOG_FILE >> $MLOG_LOG +echo -en "\n----------------------------------------" >> $MLOG_LOG +echo -e "----------------------------------------\n" >> $MLOG_LOG + +rm -f $MLOG_FILE + diff --git a/scripts/newsh b/scripts/newsh new file mode 100755 index 0000000..f9100aa --- /dev/null +++ b/scripts/newsh @@ -0,0 +1,140 @@ +#!/bin/bash +# Script to create a new shell script and open it for editing + +APP=$(basename $0) + +####################################################################### +# Set default options +####################################################################### +NEWSH_SCRIPT_TYPE=bash +NEWSH_USE_ABS_PATH=0 +NEWSH_NO_EXEC_FLAG=0 +NEWSH_TRUNC_SCRIPT=0 +NEWSH_SCRIPT_FILE= + +####################################################################### +# Usage information +####################################################################### +usage() +{ + cat <<-EOM +Usage: $APP OPTIONS + +OPTIONS + -t Type of script to create (bash/python/ruby/expect) + -a Use absolute path to binary instead of the env wrapper + -x Don't make the file executable + -f Overwrite the script file if it already exists + -h Display this help message + +$APP will abort if the specified filename already exists +EOM +} + +####################################################################### +# Get path to binary +####################################################################### +get_binary_path() +{ + local binary=$1 + local env_path=$(which env) + local bin_path=$(which $binary) + + if [[ -z "$bin_path" ]] + then + echo "$APP: fatal: Cannot find $binary" >&2 + exit 1 + fi + + case "$NEWSH_USE_ABS_PATH" in + 0) + # Use env as the path specifier + NEWSH_BINARY_PATH="$env_path $binary" + ;; + + 1) + # Use absolute path to the binary as the path specifier + NEWSH_BINARY_PATH="$bin_path" + ;; + + *) + echo "$APP: fatal: Corrupted internal state!" >&2 + echo "$APP: USE_ABS_PATH=$NEWSH_USE_ABS_PATH" >&2 + exit 2 + ;; + esac +} + + +####################################################################### +# Verify command line switches +####################################################################### +while getopts "t:axfh" OPTION +do + case "$OPTION" in + h) + usage + exit 0 + ;; + + t) + NEWSH_SCRIPT_TYPE=$OPTARG + ;; + + a) + NEWSH_USE_ABS_PATH=1 + ;; + + x) + NEWSH_NO_EXEC_FLAG=1 + ;; + + f) + NEWSH_TRUNC_SCRIPT=1 + ;; + + \?) + exit 1 + ;; + + :) + echo "$APP: Option -$OPTARG requires an argument" >&2 + exit 1 + ;; + esac +done + +shift $((OPTIND - 1)) +NEWSH_SCRIPT_FILE=$1 + +if [[ -z "$NEWSH_SCRIPT_FILE" ]] +then + echo "$APP: fatal: Missing script file!" >&2 + exit 1 +fi + +if [[ -e "$NEWSH_SCRIPT_FILE" ]] +then + if [[ "$NEWSH_TRUNC_SCRIPT" == "0" ]] + then + echo "$APP: fatal: Existing script file $NEWSH_SCRIPT_FILE" >&2 + exit 1 + elif [[ "$NEWSH_TRUNC_SCRIPT" == "1" ]] + then + echo "$APP: overwriting existing script file $NEWSH_SCRIPT_FILE" >&2 + fi +fi + +get_binary_path $NEWSH_SCRIPT_TYPE +(cat <<-EOF +#!$NEWSH_BINARY_PATH +# Autogenerated by $APP on $(date +%F) at $(date +%T%z) + +EOF +) > "$NEWSH_SCRIPT_FILE" + +# Check and make file executable +if [[ "$NEWSH_NO_EXEC_FLAG" == "0" ]] +then + chmod +x "$NEWSH_SCRIPT_FILE" +fi diff --git a/scripts/note b/scripts/note new file mode 100755 index 0000000..c398315 --- /dev/null +++ b/scripts/note @@ -0,0 +1,330 @@ +#!/bin/bash +# Notes manager for the command line + +NOTES_VER="0.1a" +NOTES_DIR="$HOME/.notes" + +# Initialize with the default editor +[ -z "$EDITOR" ] && EDITOR="/usr/bin/vim" + +dprint() { + if [ ! -z $NOTES_DEBUG ]; then + echo $* + fi +} + +notes_init() { + # Check if the notes folder exists, if not, create it + if [ ! -d $NOTES_DIR ] + then + echo -n "Creating notes folder..." + mkdir -p $NOTES_DIR + cd $NOTES_DIR + echo "done." + + git init . + else + echo "Notes has already been initialized." + fi +} + +make_title() { + echo "$*" | sed 's/[^A-Za-z0-9_]\+/-/g' | \ + sed 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' +} + +title_to_name() { + note_file=$NOTES_DIR/$(make_title $note_arg) +} + +check_arg() { + if [ -z "$note_arg" ] + then + echo "Must specify a note title!" + exit + fi +} + +note_exists() { + [[ -f "$note_file" ]] +} + +check_md5() { + if [[ "$note_old_md5" == "$note_new_md5" ]] + then + echo "No changes to '$note_arg'" + + if [[ ! -z "$1" ]] + then + rm -f $1 + fi + + exit + fi +} + +check_empty() { + if [[ ! -s "$note_file" ]] + then + if [[ "$1" == "restore" ]] + then + cd "$NOTES_DIR" + gitfile=$(basename "$note_file") + git checkout $gitfile + echo "Restored empty note '$note_arg'" + elif [[ "$1" == "delete" ]] + then + rm -f $note_file + echo "Deleted empty note '$note_arg'" + fi + + exit + fi +} + +check_dir() { + if [[ ! -d "$NOTES_DIR" ]] + then + echo "Notes not initialized. Run init first!" + exit + fi +} + +md5_sum() { + openssl dgst -md5 $* +} + +help_cmd() { + echo ' +Notes Manager for the Command Line +================================== + +This is a bash script that lets you take notes which are maintained in a +Git repository. You can run this script by typing the following command +at the command line: + +Usage: note + +Commands +-------- +You can use the first letter of each command as a shortcut key. + + Command Usage + ------- ----- + new Follow this with the note name to create a new note + edit Follow this with the note name to edit an existing note + show Follow this with the note name to display an existing note + delete Follow this with the note name to delete a note + find Prints the list of available notes + log Displays the note history + grep Finds all notes with the specified keyword in the text + init Run this the very first time to set up the folders + help Prints this help message + version Prints the version information +' +} + +version_info() { + echo "Notes Manager version $NOTES_VER" +} + +note_new() { + check_dir + check_arg + title_to_name + + if note_exists + then + echo "Note '$note_arg' already exists! Use edit instead." + exit + fi + + echo "$note_arg" > $note_file + note_old_md5=$(md5_sum $note_file) + + $EDITOR $note_file + + note_new_title=$(head -1 $note_file) + note_new_md5=$(md5_sum $note_file) + note_new_file=$NOTES_DIR/$(make_title $note_new_title) + check_md5 $note_file + check_empty delete + + dprint "Original filename = " $note_file + dprint "New filename = " $note_new_file + + # Check for a title rename + if [[ "$note_file" != "$note_new_file" ]] + then + mv -f $note_file $note_new_file + fi + + cd $NOTES_DIR + gitfile=$(basename $note_new_file) + + git add $gitfile + git commit -m "Create note '$note_new_title'" + echo "Created note '$note_new_title'" +} + +note_edit() { + check_dir + check_arg + title_to_name + if ! note_exists + then + echo "Cannot find note '$note_arg'!" + exit + fi + + note_old_title=$(head -1 $note_file) + note_old_md5=$(md5_sum $note_file) + + $EDITOR $note_file + + note_new_title=$(head -1 $note_file) + note_new_md5=$(md5_sum $note_file) + + check_md5 + check_empty restore + + cd $NOTES_DIR + gitfile=$(basename $note_file) + commit_msg="Update note '$note_new_title'" + if [[ "$note_old_title" != "$note_new_title" ]] + then + note_new_file=$(make_title $note_new_title) + + git mv $gitfile $note_new_file + git add $note_new_file + commit_msg="$commit_msg. Rename from '$note_old_title'" + else + git add $gitfile + fi + + git commit -m "$commit_msg" + echo "Updated note '$note_new_title'" +} + +note_show() { + check_dir + check_arg + title_to_name + if ! note_exists + then + echo "Cannot find note '$note_arg'!" + exit + fi + + less -R $note_file +} + +note_delete() { + check_dir + check_arg + title_to_name + if ! note_exists + then + echo "Cannot find note '$note_arg'!" + exit + fi + + cd $NOTES_DIR + gitfile=$(basename $note_file) + git rm $gitfile + git commit -m "Delete note '$note_arg'" + echo "Deleted note '$note_arg'" +} + +note_history() { + check_dir + cd $NOTES_DIR + git log --pretty=format:'%ai - %s' -- $note_arg +} + +note_list() { + check_dir + cd $NOTES_DIR + if [[ -z "$1" ]] + then + ls -1 + else + ls -1 | grep -i $1 + fi +} + +note_search() { + check_dir + + if [[ -z "$1" ]]; then + echo "Must specify a pattern to search titles!" + exit + fi + + cd $NOTES_DIR + for file in * + do + grep --color=always -il "$1" $file + grep --color=always -inhT -m2 -C1 "$1" $file + done +} + +parse_args() { + note_cmd=$1 + shift + note_arg="$*" + + case "$note_cmd" in + "h" | "help") + help_cmd + ;; + + "n" | "new") + note_new + ;; + + "e" | "edit") + note_edit + ;; + + "s" | "show") + note_show + ;; + + "d" | "delete") + note_delete + ;; + + "l" | "log") + note_history + ;; + + "i" | "init") + notes_init + ;; + + "f" | "find") + note_list $1 + ;; + + "g" | "grep") + note_search $1 + ;; + + "v" | "version") + version_info + ;; + + *) + echo "Unrecognized command '$note_cmd'. Use help." + ;; + esac +} + +if [[ $# -lt 1 ]] +then + echo "Usage: note " + echo "Type 'note help' for detailed help" +else + parse_args $* +fi diff --git a/scripts/settitle b/scripts/settitle new file mode 100755 index 0000000..8cbaa10 --- /dev/null +++ b/scripts/settitle @@ -0,0 +1,10 @@ +#!/bin/bash +# Set the Xterm/Tmux pane title + +if [[ -z $TMUX ]] +then + echo -e "\033]0;$*\007" +else + echo -e "\033k$*\033\\" +fi + diff --git a/scripts/smartwd b/scripts/smartwd new file mode 100755 index 0000000..47c148b --- /dev/null +++ b/scripts/smartwd @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# Script to smartly chop off portions of the current working directory for +# use in the shell prompt + +import os + +# Constants used to decide when to start chopping +DIRLIM = 5 +DIR_L = 3 +DIR_R = 2 +PWDLEN = 14 + +def smartwd(): + username = os.environ['USER'] + homedir = os.environ['HOME'] + pwd = os.environ['PWD'] + + path = pwd.split('/') + + # Ignore the root path + if len(path) == 1: + return pwd + + try: + username_index = path.index(username) + except ValueError: + username_index = None + + if username_index is not None: + prefix = '/'.join(path[:username_index+1]) + + if prefix == homedir : + pre_path = '~' + else: + # The first element is always the empty string. + # We want the first 4 characters of the second element + pre_path = path[1][:4] + '~' + + del path[:username_index] + path[0] = pre_path + + pwd = '/'.join(path) + + # If we exceed the dirlimit and the length of the joined pwd, + # replace the pwd with left and right elements, with ellipses + # in between to simulate a long path. + if len(path) > DIRLIM and len(pwd) > PWDLEN: + newpwd = '/'.join(path[:DIR_L] + ['...'] + path[-DIR_R:]) + + if len(newpwd) < len(pwd): + pwd = newpwd + + return pwd + +if __name__ == "__main__": + print smartwd() + diff --git a/scripts/stardate b/scripts/stardate new file mode 100755 index 0000000..c1a7c37 --- /dev/null +++ b/scripts/stardate @@ -0,0 +1,16 @@ +#!/usr/bin/env python +""" Calculate the Julian Date """ + +import time +import math + +t = time.time() + +""" Technically, we should be adding 2440587.5, + however, since we are trying to stick to the stardate + concept, we add only 40587.5""" +jd = (t / 86400.0 + 40587.5) + +# Use the idea that 1 Julian day is equal to 1 stardate +print ("%05.9f" % jd)[:-7] +