Showing posts with label scripting. Show all posts
Showing posts with label scripting. Show all posts

08 October 2009

Emacs -> Sprunge

Woo code! I got bored and wrote a function for Emacs that posts the current buffer to sprunge. Since I'm usually pasting IRC snippets, I also threw together a major mode with 4 regexps to syntax highlight IRC. Behold:



Here's the elisp source. The hash table maps major mode names to the corresponding pygments lexer name, which sprunge uses for syntax highlighting; if the mode of the buffer you post is in the map, the sprunge link will include the correct argument to syntax highlight it the same way

(setq sprunge-suffixes (make-hash-table :test 'equal))
(puthash "Python" "py" sprunge-suffixes)
(puthash "Shell-script" "sh" sprunge-suffixes)
(puthash "IRC" "irc" sprunge-suffixes)

(defun sprunge ()
"Posts the current buffer to sprunge, and shows the resulting URL in a new buffer"
(interactive)
(if (buffer-file-name) (save-buffer) (write-file "/tmp/sprunge-post"))
(delete-other-windows)
(let ((sprunge-buffer (get-buffer-create "*sprunge*"))
(sprunge-window (split-window-vertically (- (window-height) 5)))
(filename buffer-file-name)
(suffix (if (gethash mode-name sprunge-suffixes) (concat "?" (gethash mode-name sprunge-suffixes)) "")))
(select-window sprunge-window)
(set-window-buffer sprunge-window sprunge-buffer)
(erase-buffer)
(insert (shell-command-to-string (concat "curl -F 'sprunge=<" filename "' http://sprunge.us")))
(delete-char -1) ; Newline after URL
(insert suffix "\n")))

(define-derived-mode irc-mode
text-mode "IRC" "Major mode for IRC logs"
(setq font-lock-defaults
'((("\\[[0-9][0-9]:[0-9][0-9]:[0-9][0-9]\\]" . font-lock-constant-face)
("<.*>" . font-lock-keyword-face)
("[a-zA-Z0-9`^_-]+:" . font-lock-type-face)
(">>> .*" . font-lock-builtin-face)
))))

27 February 2008

Printing PDFs

When I posted my screenshot script I thought of a similar script, which also implements functionality I didn't like. The standard CUPS PDF printer prints to a fixed directory (~/PDF in my case) instead of prompting where you'd like to save it. This annoyed me, so I looked around and discovered the PDF driver's configuration file (/etc/cups/cups-pdf.conf if you use Ubuntu like me) has a directive named PostProcessing. If you set PostProcessing to a script's path, it will run the script after printing the PDF, passing it the printed PDF's filename and the name of the user that printed it. I have mine point to a script I wrote that offers similar functionality as the screenshot script, showing a gnome alert with options to open the PDF or move it somewhere else. Again, I don't write my scripts to be used on other machines, so certain things (like the Adobe Reader icon on line 10) probably won't work for you:

#!/bin/bash
pdf=$1
username=$2
action=${3:-"default"}

export DISPLAY=:0.0

case $action in
default)
notify-more -u low -t 10000 -i /opt/Adobe/Reader8/Resource/Icons/32x32/adobe.pdf.png -n "Open" -x "gnome-open \"$pdf\"" -n "Move" -x "$0 \"$pdf\" \"$username\" move" "PDF Printed" "PDF printed to $pdf" -n "Clipboard" -x "echo -n $pdf | xsel -i -b";;

move)
dest=`zenity --file-selection --title "Save PDF" --save --confirm-overwrite`

if [ "$dest" ]; then
mv "$pdf" "$dest"
if [ -e "$dest" ]; then
notify-more -u low -t 5000 -i /usr/share/icons/gnome/32x32/actions/gtk-paste.png "PDF Saved" "PDF saved to $dest" -n "Open" -x "gnome-open \"$dest\"" -n "Clipboard" -x "echo -n $dest | xsel -i -b"
else
notify-more -u high -t 5000 -i /usr/share/icons/gnome/32x32/emblems/stock_mail-priority-high.png "Save Failed" "Unable to move PDF. The original is stored at $pdf"
fi
fi;;
esac

Screenshots

I've just discovered the most fun command ever:

vncviewer 127.0.0.1


I let my computer recursively explode for a minute before I closed it. I tried to get a screenshot, but I couldn't get my computer to do much until I closed vnc. Speaking of screenshots, however, I figured I'd post my screenshot script. I tried a bunch of different screenshot programs and pretty much hated all of them, so I ended up writing a script that uses ImageMagick's import tool. It depends on two other programs that I use fairly often and really like.

  • Zenity is like a really good version of the standard dialog command. It can show all the same types of dialogs, like calendars and progress bars and whatnot, but they're the standard GTK dialogs so they look good. Most of the time the only dialog type I use is file-selection, which is what the screenshot script uses; I tend to use libnotify to display other types of alerts instead of zenity's info dialogs

  • Notify-more is a python script that uses PyNotify, the python interface to gnome's standard libnotify. Libnotify comes with a command-line tool to access it (notify-send), and notify-more intentionally mirrors it's syntax so you can use them fairly interchangably, but notify-more provides several other features, like the pie display to show when the notification will timeout and buttons that launch commands.


Here's the screenshot script itself. I don't generally write my scripts to be used elsewhere, so it might not be particularly cross-platform. I have PrntScrn bound to launch screenshot root, and Alt+PrntScrn to screenshot window:

#!/bin/bash
action=${1:-"default"}

case $action in
root|window)
echo -n Touching temporary file...
filename=`mktemp /tmp/screenshotXXXX`;
echo done

if [ $action == root ]; then
echo -n Capturing root X window...
import -frame -window root png:$filename
echo done
printText="Captured root window into $filename"
else
echo -n Determining window ID...
windowID=`xdpyinfo | awk '/focus/ {print $3}' | sed s/,//`
echo $windowID

echo -n Capturing window...
import -frame -window $windowID png:$filename
echo done
printText="Captured window $windowID into $filename"
fi

notify-more -u low -t 5000 -i /usr/share/icons/gnome/32x32/devices/video-display.png "Screenshot" "$printText" -n "Open" -x "eog \"$filename\"" -n "Save" -x "$0 save \"$filename\"" -n "GIMP" -x "gimp \"$filename\"";;

save)
filename=$2

if [ "$filename" ]; then
echo -n Getting destination...
newfile=`zenity --file-selection --title "Save Screenshot" --save --confirm-overwrite`
echo done

if [ "$newfile" ]; then
echo -n Moving screenshot to $newfile...
mv "$filename" "$newfile"
echo done

notify-more -u low -t 5000 -i /usr/share/icons/gnome/32x32/devices/video-display.png "Screenshot" "Screenshot saved to $newfile" -n "Open" -x "eog \"$newfile\"" -n "GIMP" -x "gimp \"$newfile\""
fi
fi;;
esac

Water ripple as demands_attention indicator

I came across an interesting effect for Pidgin (or anything else, really). It requires Compiz; specifically, it requires the Water Effect plugin. I'm also pretty sure it requires GNOME. It turns out compiz has a fantastic dbus interface, you can pretty much get, set or trigger anything using it (more info). You can use any language with dbus bindings, but I prefer shell scripting when I can, so I use the included dbus-send program. To trigger the water effect, the command is:

dbus-send --type=method_call --dest=org.freedesktop.compiz /org/freedesktop/compiz/water/allscreens/point org.freedesktop.compiz.activate string:'root' int32:`xwininfo -root | grep id: | awk '{ print $4 }'`


The backtick expression pulls the root window's ID, which all the compiz activation commands require. That command shows a water ripple in the middle of the screen. My goal was to make the Pidgin icon ripple when I got a new message, which I'd noticed in a youtube video once and liked. I found code that uses xwininfo to figure out the location of a gnome panel icon, and combined it with the dbus call to make the ripple effect around a panel icon:

#!/bin/bash
#WINFO=`xwininfo -root -tree | egrep ' (1[2-9]|2[0-4])x(1[2-9]|2[0-4])\+0\+0' | grep "$1" | cut -d ')' -f 2-`
#This WINFO is faster to calculate, but depends on the icon being in the top panel
WINFO=`xwininfo -root -tree -name "Top Expanded Edge Panel"| grep "$1" | cut -d ')' -f 2-`
WIW=`echo $WINFO | cut -d 'x' -f 1`
WIH=`echo $WINFO | cut -d 'x' -f 2 | cut -d '+' -f 1`
WIX=`echo $WINFO | cut -d '+' -f 4`
WIY=`echo $WINFO | cut -d '+' -f 5`
let WAX=WIX+WIW/2
let WAY=WIY+WIH/2

dbus-send --type=method_call --dest=org.freedesktop.compiz /org/freedesktop/compiz/water/allscreens/point org.freedesktop.compiz.activate string:'root' int32:`xwininfo -root | grep id: | awk '{ print $4 }'` string:'amplitude' double:.1 string:'x' int32:$WAX string:'y' int32:$WAY


All that's left is to call the script when a message comes in. The accepted way I found was to change Pidgin's sound settings, but I'd prefer to leave them the way they are. Instead, I wrote a Pidgin plugin (in Perl, because C makes me sad) that waits for the received-im-msg signal and calls the shell script:

use Purple;

%PLUGIN_INFO = (
perl_api_version => 2,
name => "Icon Ripple",
version => "2.0.0",
summary => "Shows water ripples around the Pidgin icon",
description => "Shows water ripples (powered by the Compiz Water Effect plugin) around the Pidgin icon when a message is received",
author => "Michael Mrozek <sysop073\@gmail.com>",
url => "http://pidgin.im",
load => "plugin_load"
);

sub plugin_init {return %PLUGIN_INFO;}

sub plugin_load {
my $plugin = shift;
Purple::Signal::connect(Purple::Conversations::get_handle(), "received-im-msg", $plugin, \&signal_msgin, "");
}

sub signal_msgin { #(account, sender, message, conv, flags)
system("/home/mrozekma/scripts/waterping","Pidgin");
}


This has a side-effect that some may not like of showing the ripple on every received message, not just ones when the window is demanding attention. There's probably a way to change this in the plugin, but I prefer it that way so I haven't explored it.

EDIT: I forgot that I took a screenshot of the ripple effect before I wrote this article, and never included it. It's not very good, but you can see the effect at least: