Skip to content

Instantly share code, notes, and snippets.

@petonic
Last active May 5, 2018 15:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petonic/87271b4a71d64d5429b5e6c7dd0d2da0 to your computer and use it in GitHub Desktop.
Save petonic/87271b4a71d64d5429b5e6c7dd0d2da0 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Name of my laptop to check if we're local editing
master_hostname="kaypro"
local_editor_cmd="atom"
#
# Petonic version {2016-11-20 SUN 12:54}
# Modified for ///READONLY/// auto -f {2016-11-26 SAT 10:01}
# Modified for USE_NFS mountpoint [2017-04-16 SUN 12:57]
#
# rmate
# Copyright (C) 2011-2015 by Harald Lapp <harald@octris.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This script can be found at:
# https://github.com/aurora/rmate
#
#
# This script is a pure bash compatible shell script implementing remote
# textmate functionality
#
#
# Thanks very much to all users and contributors! All bug-reports,
# feature-requests, patches, etc. are greatly appreciated! :-)
#
# init
#
version="0.9.6"
version_date="2015-09-15"
version_string="rmate-sh $version ($version_date)"
# determine hostname
function hostname_command(){
if command -v hostname >/dev/null 2>&1; then
echo "hostname"
else {
HOSTNAME_DESCRIPTOR="/proc/sys/kernel/hostname"
if test -r "$HOSTNAME_DESCRIPTOR"; then
echo "cat $HOSTNAME_DESCRIPTOR"
else
echo "hostname"
fi
}
fi
}
hostname=$($(hostname_command))
readonly=""
[ -n "$SUDO_UID" ] && sudo_string=" ### "
# default configuration
host=localhost
port=52698
function load_config {
local rc_file=$1
local row
local host_pattern="^host(:[[:space:]]+|=)([^ ]+)"
local port_pattern="^port(:[[:space:]]+|=)([0-9]+)"
readonly=""
if [ -f "$rc_file" ]; then
while read row; do
if [[ "$row" =~ $host_pattern ]]; then
host=${BASH_REMATCH[2]}
elif [[ "$row" =~ $port_pattern ]]; then
port=${BASH_REMATCH[2]}
fi
done < "$rc_file"
fi
}
for i in "/etc/${0##*/}" ~/."${0##*/}/${0##*/}.rc" ~/."${0##*/}.rc"; do
load_config $i
done
host="${RMATE_HOST:-$host}"
port="${RMATE_PORT:-$port}"
logger "=--------------- Rmate: start of args"
for i in "$@"; do
logger "rmate arg is <$i>"
done
# misc initialization
filepaths=()
displaynames=()
selections=()
filetypes=()
verbose=false
nowait=true
force=false
check_only=false
use_nfs=true
# process command-line parameters
#
function showusage {
echo "usage: $(basename $0) [arguments] file-path edit specified file
or: $(basename $0) [arguments] - read text from stdin
-H, --host HOST Connect to HOST. Use 'auto' to detect the host from
SSH. Defaults to $host.
-p, --port PORT Port number to use for connection. Defaults to $port.
-w, --[no-]wait Wait for file to be closed by TextMate.
-l, --line LINE Place caret on line number after loading file.
-m, --name NAME The display name shown in TextMate.
-t, --type TYPE Treat file as having specified type.
-n, --new Open in a new window (Sublime Text).
-r, --remote Do not use .atom-nfs config files
-v, --verbose Verbose logging messages.
-h, --help Display this usage information.
-f, --force Force previous App to activate when editing is done
-c, --check Returns immediately. Status set whether RATOM is running.
--version Show version and exit.
"
}
function log {
if [[ $verbose = true ]]; then
echo "$@" 1>&2
fi
logger "$@"
}
function dirpath {
(cd `dirname "$1"` >/dev/null 2>/dev/null; pwd -P)
}
function canonicalize {
filepath="$1"
dir=`dirpath "$filepath"`
if [ -L "$filepath" ]; then
relativepath=`cd "$dir"; readlink \`basename "$filepath"\``
result=`dirpath "$relativepath"`/`basename "$relativepath"`
else
result=`basename "$filepath"`
if [ "$dir" = '/' ]; then
result="$dir$result"
else
result="$dir/$result"
fi
fi
echo $result
}
while test "${1:0:1}" = "-"; do
case $1 in
-)
break
;;
-H|--host)
host=$2
shift
;;
-p|--port)
port=$2
shift
;;
-w|--wait)
nowait=false
;;
--no-wait)
nowait=true
;;
-l|--line)
selections+=($2)
shift
;;
-r|--remote)
use_nfs=false
shift
;;
-m|--name)
displaynames+=("$2")
shift
;;
-t|--type)
filetypes+=($2)
shift
;;
-n|--new)
new=true
;;
-f|--force)
force=true
;;
-c|--check)
check_only=true
;;
-v|--verbose)
verbose=true
;;
--version)
echo $version_string
exit 1
;;
-h|-\?|--help)
showusage
exit 1
;;
*)
showusage
exit 1
;;
esac
shift
done
if [[ "$host" = "auto" && "$SSH_CONNECTION" != "" ]]; then
host=${SSH_CONNECTION%% *}
fi
filepaths=("$@")
if [ "$filepaths" = "" ]; then
if [[ $nowait = false ]]; then
filepaths='-'
else
case "$-" in
*i*)
showusage
exit 1
;;
*)
filepaths='-'
;;
esac
fi
fi
#------------------------------------------------------------
# main
#------------------------------------------------------------
function open_file {
index="$1"
filepath="${filepaths[$index]}"
selection="${selections[$index]}"
filetype="${filetypes[$index]}"
displayname="${displaynames[$index]}"
if [ "$filepath" != "-" ]; then
realpath=`canonicalize "$filepath"`
log $realpath
# Check to see if we're on my laptop
if [[ $hostname = $master_hostname ]]; then
$local_editor_cmd "$filepath"
else
if [ -d "$filepath" -a ! ${use_nfs} ]; then
log "$filepath is a directory and rmate is unable to handle directories."
exit 1
fi
if [ -f "$realpath" -a ! -w "$realpath" ]; then
readonly="///READONLY/// - "
if [[ $verbose = true ]]; then
log "File $filepath is not writable! Opening anyway."
fi
fi
if [ "$displayname" = "" ]; then
displayname="$hostname:$filepath"
fi
fi
else
displayname="$hostname:untitled"
fi
displayname="${readonly}_SSH_${displayname}"
[ "$sudo_string" ] && displayname="${sudo_string} ${displayname} ${sudo_string}"
nfs_pathname=""
if ${use_nfs} ; then
nfs_map="`rnfs ${realpath} 2>/dev/null`" && nfs_pathname="${nfs_map}"
fi
# echo "use_nfs = <$use_nfs>"
# echo "nfs_map = <$nfsmap>"
# echo "nfs_pathname = <$nfs_pathname>"
echo "open" 1>&3
echo "display-name: ///NFS/// $displayname" 1>&3
echo "real-path: NFS_$realpath" 1>&3
echo "data-on-save: yes" 1>&3
echo "re-activate: yes" 1>&3
if [ -n "${nfs_pathname}" ]; then
echo "nfs-open: ${nfs_pathname}" 1>&3
echo "Using NFS-OPEN with <${nfs_pathname}>"
# exit 9
fi
echo "token: $filepath" 1>&3
if [[ $new = true ]]; then
echo "new: yes" 1>&3
fi
if [ "$selection" != "" ]; then
echo "selection: $selection" 1>&3
fi
if [ "$filetype" != "" ]; then
echo "file-type: $filetype" 1>&3
fi
if [ "$filepath" != "-" ] && [ -f "$filepath" ]; then
filesize=`ls -lLn "$realpath" | awk '{print $5}'`
echo "data: $filesize" 1>&3
cat "$realpath" 1>&3
elif [ "$filepath" = "-" ]; then
if [ -t 0 ]; then
echo "Reading from stdin, press ^D to stop"
else
log "Reading from stdin"
fi
# preserve trailing newlines
data=`cat; echo x`
data=${data%x}
filesize=$(echo -ne "$data" | wc -c)
echo "data: $filesize" 1>&3
echo -n "$data" 1>&3
else
echo "data: 0" 1>&3
fi
echo 1>&3
}
function handle_connection {
local cmd
local name
local value
local token
local tmp
while read 0<&3; do
REPLY="${REPLY#"${REPLY%%[![:space:]]*}"}"
REPLY="${REPLY%"${REPLY##*[![:space:]]}"}"
cmd=$REPLY
token=""
tmp=""
while read 0<&3; do
REPLY="${REPLY#"${REPLY%%[![:space:]]*}"}"
REPLY="${REPLY%"${REPLY##*[![:space:]]}"}"
if [ "$REPLY" = "" ]; then
break
fi
name="${REPLY%%:*}"
value="${REPLY##*:}"
value="${value#"${value%%[![:space:]]*}"}" # fix textmate syntax highlighting: "
case $name in
"token")
token=$value
;;
"data")
if [ "$tmp" = "" ]; then
tmp="/tmp/rmate.$RANDOM.$$"
touch "$tmp"
fi
dd bs=1 count=$value <&3 >>"$tmp" 2>/dev/null
;;
*)
;;
esac
done
if [[ "$cmd" = "close" ]]; then
log "Closing $token"
if [[ "$token" == "-" ]]; then
echo -n "$CONTENT"
fi
if [[ "$nowait" != "" ]]; then
printf "\e]1337;StealFocus\a"
fi
elif [[ "$cmd" = "save" ]]; then
log "Saving $token"
if "$force"; then
# If nowait, then any save will restore focus
if [[ "$nowait" = "" ]]; then
printf "\e]1337;StealFocus\a"
fi
fi
if [ "$token" != "-" ]; then
cat "$tmp" > "$token"
else
CONTENT=`cat "$tmp"`
fi
rm "$tmp"
fi
done
if "$force"; then
printf "\e]1337;StealFocus\a"
# khd -p 'cmd - tab' > /dev/null
# khd -p '- return' > /dev/null
fi
log "Done"
}
# connect to textmate and send command
#
exec 3<> /dev/tcp/$host/$port
if [ $? -gt 0 ]; then
echo "Unable to connect to TextMate on $host:$port"
exit 1
fi
# Petonic 2017-04-30: Added the -c flag to check for RMATE server
# connectivity
if "$check_only"; then
echo "check" 1>&3
exit 0
fi
read server_info 0<&3
log $server_info
for i in "${!filepaths[@]}"; do
open_file "$i"
done
echo "." 1>&3
if [[ $nowait = true ]]; then
exec </dev/null 2>/dev/null
( (handle_connection &) &)
else
force=true
handle_connection
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment