urlview.py

Nicht nur Imperien und diktatorische Regime fallen mitunter wie ein Kartenhaus in sich zusammen, sondern auch alltägliche Probleme. Mein erfolgloser Versuch, urlview durch ein Python-Skript zu ersetzen, war im ersten Anlauf gescheitert an der Herausforderung, zunächst STDIN bis zur Neige zu lesen und anschließend auf demselben Wege eine Auswahl der Nutzerin entgegenzunehmen.

In einer Mischung aus Sturheit und Unglauben stellte ich eine erneute Anfrage (diesmal auf com.lang.python), die zu einem bereits bekannten Vorschlag führte:

message = sys.stdin.read() sys.stdin = open('/dev/tty') selected_index = raw_input('Which URL to open?')

Eine erneute Google-Suche führte dagegen zu einer wesentlich komplexeren – und funktionierenden – Lösung:

#!/usr/bin/python3 # -*- coding: utf-8 -*- import os # Duplicates the standard input into file descriptor 3. # Note that if some file already had file descriptor 3, # it will be closed. Avoid this somehow if needed. os.dup2(0, 3) # Opens a TTY for reading the keyboard. tty = open("/dev/tty", mode="r") # Duplicates the TTY into file descriptor 0 making the # keyboard input standard input. os.dup2(tty.fileno(), 0) # Opens the original duplicated standard input into newInput. newInput = os.fdopen(3, "r")

Nur dem Insistieren eines freundlichen Python-Kenners im o.g. Thread (That's odd. For some reason, I can get away with a simple sys.stdin = open('/dev/tty') and raw_input will merrily read from file descriptor 3.) ist es zu verdanken, dass ich den ursprünglichen Vorschlag erneut ausprobierte. Mit Erfolg. Das milde Lächeln von Herrn Mulder beim Lesen meiner zerknirschten Erfolgsmeldung stelle ich mir aus Selbstachtung lieber nicht vor. Zu dieser Peinlichkeit kam hinzu, dass Herr Peltomaki mir auf meine verblüffte Nachfrage hin noch einmal auf den Unterschied zwischen simultan und konsekutiv erläutern musste.

Um aber die gesamte Episode nicht nur als Lehrstunde für mich zu verbuchen – folgendes Skript extrahiert URLs aus einer E-Mail, bietet sie in zur Auswahl an und öffnet sie im Browser:

#!/usr/bin/python import sys import subprocess import re import os os.system('clear') message = sys.stdin.read() urls = re.findall(r'(?:http|www)\S+', message) sys.stdin = open('/dev/tty') if len(urls) > 1: for index, url in enumerate(urls): print '{0}: {1}\n'.format(index, url) selected_index = raw_input('Which URL to open? ') selected_index = int(selected_index) else: selected_index = 0 try: selected_url = urls[selected_index] if not selected_url.startswith('http'): selected_url = 'http://' + selected_url return_code = subprocess.call(['open', selected_url]) except IndexError: pass

Gegenüber dem ursprünglichen urlview hat diese Version den Vorteil, dass URLs ohne Konkurrenten automatisch geöffnet werden. In .muttrc kann das Skript wie folgt verankert werden:

set pipe_decode=yes set wait_key=no macro pager l "<pipe-entry>urlview.py<enter>"

Der erste Befehl sorgt dafür, dass lesbare (dekodierte) Nachrichten an urlview.py übergeben werden, der zweite führt nach dem Aufrufen eines externen Kommandos unmittelbar zurück zur Nachrichtendarstellung, und der dritte verknüpft die Taste l in der Nachrichtenansicht mit der Übergabe der Nachricht an urlview.py.

Natürlich ist auch diese Idee nicht sonderlich originell. Es gibt sogar eine curses-basierte Version. Ach, Internet, Du altes Desillusionsinstrument.