Skip to content

Instantly share code, notes, and snippets.

@gburca
Last active February 14, 2017 04:12
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 gburca/4a334b61e1c34b438ccd to your computer and use it in GitHub Desktop.
Save gburca/4a334b61e1c34b438ccd to your computer and use it in GitHub Desktop.
#!/bin/bash
# Usage: vim-tail.sh <filename>
#
# This script turns vim into a `tail -f` equivalent, but with syntax
# highlighting and all the other goodies.
#
# A version of vim compiled with +clientserver is required.
# Run `vim --version` to see what options were compiled in.
# On Ubuntu 14.04, vim.tiny, vim.basic and vim.nox won't work.
# vim.gtk is compiled with +clientserver, so `apt-get install vim-gtk`
#
# Author: Gabriel Burca <gburca dash github at ebixio dot com>
# Pick one of: vim|view|gvim|gview, etc...
VI=vim.gtk
# A unique name for the server, in case we monitor multiple files.
SERVER_NAME="TAIL$$"
hash inotifywait &> /dev/null || { echo "I require 'inotifywait' to be installed (apt-get install inotify-tools)"; exit 1; }
hash $VI &> /dev/null || { echo "I require '$VI' to be installed (apt-get install vim-gtk)"; exit 1; }
$VI --version | fgrep -q '+clientserver' || { echo "I require $VI to be compiled with '+clientserver'"; exit 1; }
# In VIM clientserver, the communication between the server and the client goes
# through the X server. That means we need a DISPLAY and permissions to connect
# to it.
if [ -z "$DISPLAY" ]; then
echo "I require the DISPLAY environment variable to be set"
exit 1
fi
# See if we have access to the display
if ! xhost > /dev/null 2>&1 ; then
if [ -n "$SUDO_USER" ]; then
export XAUTHORITY=/home/$SUDO_USER/.Xauthority
elif [ "$USER" == "root" ]; then
su -c 'xhost SI:localuser:root > /dev/null' $SUDO_USER
else
echo "Display access needed."
echo "Try: xhost SI:localuser:$USER"
exit 2
fi
fi
doForever() {
# Give the vim server a chance to start
sleep 2
# Move to the end of the file
$VI -X --servername $SERVER_NAME --remote-send '<C-\><C-N>:edit!<CR>G' > /dev/null 2>&1 || exit
while true; do
# This blocks until the file changes, or the timeout expires
inotifywait --quiet --quiet --timeout 10 --event modify "$1"
# 0 = the file was modified
# 2 = the timeout expired
if (( $? == 0 || $? == 2 )); then
$VI --servername $SERVER_NAME --remote-send '<C-\><C-N>:edit!<CR>G' > /dev/null 2>&1 || exit
else
exit 1
fi
# It's possible for the file to be modified before we loop back to
# `inotifywait`, but we'll pick it up on the next round.
done
}
# Kick off the vim client script in the background
coproc doForever "$1"
# Now start the server
$VI -X -R --servername $SERVER_NAME --remote-silent "$1"
# Nothing below here executes until the `tail` server exits.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment