Freitag, August 10, 2012

XMonad and Org-Mode

After a while playing with XMonad and Org-Mode in Emacs I wrote a function for XMonad to start a Note-File with Emacs in XMonad.

First of all I will have a prompt which shows me all the current org-files in a given directory and then I will select one of the shown files or create a new one.

The following function will produce this prompt and shows me alle available org-files in a given directory.

firingOrgPrompt :: FilePath -> X ()
firingOrgPrompt path = do
  files <- liftIO $ getDirectoryContents path
  inputPromptWithCompl defaultXP "Org" 
    (mkComplFunFromList $ filterOrg files) ?+ (openOrgFile path)
    where openOrgFile p f = spawn (emacsClient ++ p ++ "/" ++ f)
          filterOrg f = filter (endswith ".org") f

After writing this function you will define some keyboard shortcuts in your xmonad.hs file.

myKeys = \c -> newKeys c `M.union` keys defaultConfig c
newKeys (XConfig {modMask = modm}) = M.fromList $
   [ ((modm, xK_n), firingOrgPrompt (wikiRootPath ++ "notes")) ]

After that you have to define the variable emacsClient and wikiRootPath. The variable emacsClient could alse be the function getEditor.

After reloading your XMonad you could hit M-n and you get a prompt where you could select one of those org-files.

Montag, Juni 18, 2012

Labels in Mutt

Nachdem ich wieder zu Mutt gewechselt bin, wollte ich jetzt endlich meine Emails auch über Labels verwalten. Leider funktioniert das in Mutt nicht out-of-the-box, aber auch nicht schwer umzusetzen.

Mutt unterstützt seit einiger Zeit das Arbeiten mit dem Header X-Label. Das heißt man kann nach diesem mit ~y filtern und auch über %y diese Labels im Index anzeigen lassen. Das heißt es muß nur noch eine Möglichkeit geschaffen werden diese Labels zu setzen. Es gibt auch einen Patch dazu für Mutt aber ich wollte meinen Mutt nicht patchen und deshalb entschied ich mich zu einer selbst geschriebenen Lösung. Folgendes stellt ein ganz einfaches Skript dar dies umzusetzen.

file=$1
tmpfile=$file.$$

old_labels=`formail -x "X-Label:" < $file | tr -d '\n' | sed 's/^[ \t]*//'`

read -e -p "Edit Labels: " -i "$old_labels" new_labels

formail -I "X-Label: $new_labels" < $file > $tmpfile
mv $tmpfile $file

Hier wird mit dem Programm formail gearbeitet, das mit procmail mitgeliefert wird und das Bearbeiten von Emails unterstützt. Hier werden zunächst alle Labels die in diesem Email gesetzt sind ermittelt und danach von der Kommandozeile gefragt welche Labels hinzugefügt werden sollen. Danach werden diese gesammelten Labels wieder in dieser Nachricht geschrieben.

Jetzt muß man Mutt nur noch einen Keyboard-Shortcut lernen damit man mit diesem Script arbeiten kann.

macro index Y ':set editor=mutt_label_editor<return><edit>:set \
editor="emacsclient -c"<return><sync-mailbox>' "edit X-Label for message"

Diese definiert ein Macro in Mutt, welches man mit Y aufruft. Hier wird dann das Skript muttlabeleditor aufgerufen, das den obigen Inhalt hat. Wichtig zu erwähnen ist hier noch das ich am Schluß auch noch die Mailbox synchronisiere. Das kann zu Problemen führen wenn vor dem Starten dieses Skriptes schon Nachrichten zum löschen markiert wurden. Diese sind danach gelöscht. Wenn man nun folgende Zeile in die .muttrc einträgt sieht man auch die definierten Labels im Index.

set index_format="%4C|%?M?+& ?%2M|%Z|%2N|%D| %-30.30F %s %> %?y?%.30y?|%4c"

Danach kann man schon recht komfortabel mit den Labels arbeiten.

Back to Mutt

Nachdem ich von Vim auf Emacs umgestiegen bin, wollte ich natürlich auch meine Emails mit Emacs schreiben, betrachten und vor allem verwalten. Ich hatte in den letzten Monaten einige Email-Clients für Emacs ausprobiert, dazu gehören Gnus, RMail, VM und Wanderlust.

Begonnen hatte ich mit Gnus. Es ist meiner Meinung der bekannteste Email-Client für Emacs und läßt sich auch äußerst gut konfigurieren. Man kann so ziemlich alles was man sich wünscht damit anstellen. Manche Dinge gehen leichter und manche wieder umständlicher. Nachdem Gnus immer langsamer wurde und ich auch nach Monaten noch keine zufriedenstellende Konfiguration für mich hatte sah ich mich um Alternativen um. Wie schon oben erwähnt sah ich mir danach RMail, VM und Wanderlust an.

RMail ist in Emacs standardmäßig enthalten und verwendet standardmäßig, seit Emacs 23, das mbox-Format. Hier habe ich es nicht geschafft eine für mich arbeitsfähige Konfiguration zu erstellen, damit ich gut mit RMail arbeiten konnte.

Danach sah ich mir VM an. VM sollte RMail ablösen und dieses verbessern und auch noch Wanderlust, welches eine sehr gute IMAP-Unterstützung haben soll. Da ich diese aber nicht brauche, weil ich meine Emails per POP auf meinen Rechner hole war dies nicht relevant für mich.

Alles in Allem kam ich aber mit keinen der genannten Mailclients zurecht. Entweder unterstützte einer das von mir gewünschte Format nicht oder die Konfiguration war zu umständlich. Das hieß ich wechselte wieder zurück zu der Kombination procmail, mutt und Emacs als Editor. In Gnus habe ich die Emails direkt in Gnus in verschiedenste Ordner einsortiert, dies geschieht jetzt wieder mit procmail und ich bin sehr zufrieden damit weil ich z.B. durch folgende Regel allen Emails die von einer speziellen Mailingliste kommen einen Header-Eintrag hinzufügen.

:0
* ^(TO|CC).*mailing-list.*
{
   LABELS=`formail -x "X-Label:" | tr -d '\n'`
   :0
   | /usr/bin/formail -I"X-Label: $LABELS lists" \
   >> $MAILDIR/inbox
}

In dieser Rule wird von einer bestimmten Mailinglist der Header nach X-Label durchsucht und diese Labels gespeichert und ein neuer Header-Eintrag erstellt mit den alten Labels und einen neuen Label lists.

Mutt habe ich schon sehr lange verwendet und diesen auch sehr gerne genutzt. Da ich von Vim auf Emacs gewechselt bin wollte ich mir auch einen Email-Client ansehen der direkt in elisp geschrieben wurde. Leider bin ich mit keinen dieser klar gekommen und bin jetzt wieder sehr zufriedener Mutt-User. Als Editor für neue Emails verwende ich nach wie vor Emacs. Wenn man folgende Einstellung in der .muttrc macht wird auch der Emacs schnell gestartet.

set editor = "emacsclient -c"

Hier wird Emacs in einem neuen Frame gestartet und dies geschieht bei einer laufenden Emacs-Instanz sehr schnell.

Mittwoch, April 04, 2012

Scrum und Org-Mode II

Ich habe zuletzt einen Artikel geschrieben, wie man mit dem org-Mode von Emacs mit Scrum arbeiten kann. Da Bilder so etwas erstaunliches haben, möchte ich hier einen Screenshot posten von einem Testprojekt wie ich mit Scrum und dem org-Mode von Emacs arbeite.
Hier kann man sehen wie ich einen Sprint angegt habe, dazu sämtliche Informationen in dieser Datei sammle und auch den Product-Backlog mitführe. Auf der rechten Seite sieht man das Burndown-Chart eines laufenden Sprintes. Dieses Chart ist mit Gnuplot erstellt worden und man sieht den Inline-Code am Screenshot.

Freitag, März 23, 2012

Landesführertagung der PfadfinderInnen NÖ

Am Wochenende ist Landesführertagung (LFT) und ich freue mich schon auf ein nettes und umfangreiches Programm und interessante Diskussionen. Die Landesführertagung in diesem Jahr steht ganz im Zeichen unseres Bundesthemas Fünf vor 12.

Das Programm für diese Landesführertagung findet ihr auf der Homepage des Landesverbandes NÖ.

Scrum und Org-Mode

Um Scrum in der Entwicklung durchführen zu können benötigt man 3 unterschiedliche Phasen.

  • Sprint Planung
  • Sprint Review
  • Daily Scrum

Hier möchte ich mich mit der dritten Phase, dem Daily Scrum, beschäftigen und wie man mit Emacs und dem Org-Mode diese Prozess durchführen kann. Es gibt sicherlich verschiedenste Ansätze, hier nur ein möglicher. Für das 'Daily Scrum' wird als Werkzeug das Taskboard verwendet, wo alle Tasks eines Sprintes aufgelistet werden. Ein Task ist eine Aufgabe die eine oder mehrer Personen durchführen können.

Ein Task hat einen Titel, eine oder mehrere Personen die diesen Task durchführen und einen Sprint dem er eingeordnet ist. Ein Sprint ist eine zeitliche Abgrenzung von mehreren Tasks. Überlicherweise dauert ein Sprint 2 oder 3 Wochen.

Wir müssen zunächst den Status eines Tasks definieren. Der Status eines Tasks kann sein Planing, Processing oder Done. Also 'In Planung', 'In Arbeit' oder 'Erledigt'. Diese können wir jetzt in einer Datei folgendermaßen definieren:

#+TODO: Planning(p!) Processing(r!) | Done(d!)

Zusätzlich muß man die Personen die an einem Projekt arbeiten mitführen. Dies mache ich über Tags. Die Tasks kann man auf global für eine Datei festlegen mit

#+TAGS: odi(o) franz(f) max(m)

Danach bekommt man immer eine Auswahl von Personen wenn man ein Tag einem Task zuordnet. Jetzt können wir unseren ersten Sprint planen und legen einen ersten Sprint an und fügen ihm ein Tag mit C-c C-q mit dem Namen 'sprint1' hinzu.

* Sprint 1 [/]        :sprint1:

Das Element '[/]' wird durch die Anzahl von Tasks die in dem Sprint vorhanden sind bzw alle erledigten ersetzt. Das geschieht automatisch. Das kann dann folgendermaßen aussehen:

* Sprint 1 [1/1]      :sprint1:
** Planning Aufgabe 1     :odi:
** Done Aufgabe 2         :max:

Jetzt kann man alle Tasks die man anlegt und verschiedene Stati haben auswerten. Das kann man mit der Tastenkombination C-c a t machen. Damit kommt man in die Agenda-View wo man nach allen möglichen Aspekten filtern kann. Man kann sich z.B. ansehen Welche Tasks in dem Sprint 1 gerade in Arbeit sind.

C-c a t / <TAB> sprint1 2 r

Zusätzlich kann man dann natürlich auch noch nach den einzelnen Personen filtern die gerade Tasks in diesem Sprint in Arbeit haben.

Mythos Motivation

Für alle sich mit Motivation von MitarbeiternInnen beschäftigen oder beschäftigen müssen möchte ich folgendes Buch ans Herz legen.

Mythos Motivation - Reinhard K. Sprenger - ISBN13: 9783593368948

Reinhard K. Sprenger geht hier seinen ganz eigenen Weg bezüglich der Motivation und Motivierung von Menschen. Er zeigt auch auf warum Anreizsysteme böse sind und was es mit den Begriffen Motivation, Motivierung und Demotivation bzw Manipulation auf sich hat.

Es war für mich auf jeden Fall sehr lesenswert.

Vim vs Emacs

Wenn man über die beiden Editoren Vim und Emacs spricht kommt über kurz oder lang auch das Thema Startzeit auf. Hier möchte ich zeigen das auch der Emacs sehr schnell starten kann. Man muß nur die Philosophie der beiden verstehen und anwenden.

Ich möchte mit dem Vim beginnen und einen Datei starten und diesen gleich wieder beenden und dabei die Zeit messen. Das mache ich mit folgendem Befehl

% time vim -c :q file
vim -c :q test  0.07s user 0.03s system 14% cpu 0.692 total

In der zweite Zeile sieht man die Zeit die Vim gebraucht hat um diese Datei zu öffnen und wieder zu schließen. Nun möchte ich die gleiche Datei mit Emacs öffnen

% time emacs -nw -f "save-buffers-kill-terminal" file
emacs -nw -f "save-buffers-kill-terminal" test  0.66s user 0.10s system 51% cpu 1.467 total

Wow. Das ist ja mal deutlich langsamer. Die Philosophie von Emacs ist es aber den Editor einmal zu starten und dann alles was man möchte darin zu öffnen oder zu schließen. Dafür gibt es einen emacsclient der sich mit dem Server verbinden kann und dort dann Dateien öffnen. Dazu muß man in einem Emacs den Server starten mit M-x server-start danach kann man mit

% emacsclient -n file

eine Datei öffnen. Dabei sieht man wie schnell Emacs eine Datei öffnet.

% emacsclient -n test
emacsclient -n test  0.00s user 0.00s system 0% cpu 0.015 total

Man sieht das dies wesentlich schneller geht, da hier keine Funktionen mehr geladen werden müssen und damit kann man schon sagen das der Emacs schnell startet.

Was man hingegen schon bemerken muß, ist der Speicherverbrauch den die beiden Editoren benötigen. Hier hat der Vim die Nase vorne und verbraucht wesentlich weniger Speicher.

#vim
% pmap 9113 | grep total
 total            32180K
#emacs
% pmap 21265 | grep total
 total           178736K

Wenn man aber bedenkt das hinter Emacs eine andere Philosophie steckt und dieser wesentlich mehr Features mit sich bringt, ist der Speicherverbrauch zu relativieren.

Donnerstag, März 22, 2012

Emacs Jabber.el und XMonad

Ich habe schon sehr lange irssi mit irssi-xmpp als meinen Jabber-Client verwendet. Jetzt verwende ich aber seit einiger Zeit sehr gerne Emacs und dieser verfügt über sehr viel Funktionalitäten. Man kann mit ihm auch per Jabber kommunizieren.

Wenn man ein Debian-System verwendet kann man Jabber für Emacs folgendermaßen installieren:

$ aptitude install emacs-jabber

Danach kann Jabber schon verwendet wenn man einige Grundeinstellungen trifft. Man muß z.B. den Server angeben.

(setq jabber-account-list
      '(("user.name@gmail.com/emacs"
         (:network-server . "talk.google.com")
         (:connection-type . ssl))))

Wenn man nun Emacs startet kann man mit jabber-connect sich mit diesem Server verbinden, man muß lediglich noch das Paßwort eingeben. Das Problem bei dieser Lösung ist es, das der Window-Manager nicht mitbekommt wenn sich ein Event ereignet im Emacs. Hier kann man sich eine Funktion schreiben die mir in XMonad behilflich ist. Ich verwende dazu dzen2 und erstelle folgendes Skript:

#!/bin/bash
echo $1 | dzen2 -p $2

Dieses Skript kann man dann mit 2 Parametern aufrufen. Der erste Parameter ist der Text der angezeigt werden soll und der zweite ist die Zeit wie lange diese Nachricht angezeigt werden soll. Jetzt muß man Emacs nur noch sagen, das er diese Funktion aufrufen soll wenn eine neue Nachricht über Jabber eintrifft.

Hier verwenden wir die Liste jabber-alert-message-hooks. Hier kann man alle Funktionen angeben die aufgerufen werden wenn so ein Event auftritt. Zunächst schreiben wir uns eine Funktion die das Shell-Skript aufruft.

(setq jabber-dzen2-notify-time 4)

(defun jabber-dzen2-notify (message)
  (start-process "notify" nil "notify.sh" message
                 (number-to-string jabber-dzen2-notify-time)))

(defun jabber-message-dzen2 (from buffer text proposed-alert)
  (jabber-dzen2-notify (concat "[" (jabber-jid-displayname from) "]: "
  text)))

Wenn ein Event eintritt soll jetzt die Funktion jabber-message-dzen2 aufgerufen werden, die wiederum die Funktion jabber-dzen2-notify aufruft die eine dzen2-Nachricht auf dem Bildschirm darstellt. Jetzt muß man nur mehr diese Funktion dem Hook mitteilen.

(add-to-list 'jabber-alert-message-hooks 'jabber-message-dzen2)

Danach sieht man immer eine dzen2-Nachricht wenn eine neue Nachricht über Jabber kommt.

Bloggen mit Emacs

Ich verwende sehr oft Emacs mit dem Org-Mode und möchte natürlich auch meine Blogpost damit erstellen. Das geht ganz einfach und man geht folgendermaßen vor.

Zunächst muß man in dem Stylesheet von Blogger folgendes hinzufügen, damit man den preformatierten Text hervorheben kann. Diese Werte kann man natürlich ganz nach seinem belieben ändern.

pre {
  border: 1pt solid #66dd87;
  background-color: #ddffe6;
  padding: 5pt;
  font-family: droid, monospace;
  font-size: 90%;
  overflow: auto;
}

Danach kann man seinen Artikel nach belieben im Emacs mit dem Org-Mode verfassen. Wenn man z.B. eine Code irgendwo im Text hervorheben möchte so schreibt man einfach:

#+BEGIN_SRC
#+END_SRC

Diesem Block kann man auch angeben welche Sprache verwendet wird zwischen den Blockzeilen. Man kann z.B. lisp oder haskell verwenden. Der Vorteil ist, das man das ganze Repertoire verwenden kann wie z.B. auch eine Tabelle exportieren. Wenn man die Zeilennummern auch angeben möchte bei den Sourcecodes muß man z.B. folgendes schreiben:

#+BEGIN_SRC lisp -n

Hier wird in diesem Block LISP-Code verwendet und die Zeilen werden auch durchnummeriert. Danach exportiert man den erstellten Text in ein HTML-Format mit C-c C-e H und kopiert sich den erzeugten HTML-Code in einen neuen Blogger-Artikel.

Mittwoch, März 21, 2012

Artikel in Gnus löschen

Da ich seit kurzem Emacs verwende um meine Texte und Code zu erstellen, möchte ich auch gerne Emails damit ansehen. Dazu habe ich mir Gnus angesehen. Gnus ist ein Message-Reader, d.h. egal ob man Nachrichten von einem NNTP-Server oder von einer Mailbox holt, Gnus verwaltet diese gleich und macht dabei keinen Unterschied.

Anders als andere Message Readers (MUA - Message User Agents) löscht Gnus keine Nachrichten standardmäßig, außer wenn man ihn auffordert dies zu tun. Nun möchte ich aber nicht immer alle meine Nachrichten in meiner Inbox haben und deswegen habe ich Gnus so konfiguriert, das er nach Ablauf einer bestimmten Zeit, Nachrichten archiviert.

Dazu muß man die Nachrichten als expired markieren. Das kann man mit der Taste E in der Summary-Übersicht machen. Das ist aber sehr umständlich wenn man das mit jeder Nachricht machen muß. Dazu verwende ich folgende Einstellung

(setq gnus-auto-expirable-newsgroups
   "lists\\|inbox")

Hier wird definiert das in den beiden Gruppen 'lists' und 'inbox' automatisch alle Nachrichten als expired markiert werden. Nun ist das schön aber man kann damit noch nicht wirklich viel anfangen, denn Gnus löscht oder verschiebt diese Nachrichten standardmäßig nach 7 Tagen. Hier kann man wieder pro Gruppe einstellen wann diese Nachrichten gelöscht oder verschoben werden

(setq nnmail-expiry-wait-function
   (lambda (group)
      (cond ((string= group "lists") 'immediate)
            (t 40))))

Hier werden alle Nachrichten die in der Gruppe 'lists' sich befinden sofort nachdem die Gruppe verlassen wurde gelöscht und alle anderen Nachrichten in anderen Gruppen erst nach 40 Tagen.

Zusätzlich möchte man vielleicht auch noch steuern wohin diese Nachrichten, die als expiry markiert sind, wandern. Ich würde gerne alle Nachrichten von der Gruppe inbox in das Archiv mail-%Y und alle gesendeten Nachrichten in das Archiv sent-%Y verschieben. Alle andern sollen in den Kübel wandern. Folgende Konfiguration führt dies durch

(defun my-fancy-expiry (group)
   (let* ((target (cond
                  ((equal group "inbox") "nnml+archive:mail-%Y")
                  ((equal group "sent") "nnml+archive:sent-%Y")
                  (t "nnml+archive:trash")))
          (nnmail-fancy-expiry-targets
           `(("from" ".*" , target))))
     (nnmail-fancy-expiry-target group)))

(setq nnmail-expiry-target 'my-fancy-expiry)

Der String '%Y' wird durch das aktuelle Jahr ersetzt. Hier wird definiert das alle Nachrichten die von ".*" kommen und in der Gruppe 'inbox' sich befinden nach Ablauf der expiry-time (40 Tage) in das Archiv mail-%Y wandern. In der Variable nnmail-expiry-target kann man eine Funktion angeben die immer dann ausgeführt werden soll, wenn der Expiryprozess gestartet wird. Dieser wird normalerweise aufgerufen wenn man eine Gruppe verläßt.

Nach dieser Konfiguration braucht man sich um nichts mehr kümmern und die Nachrichten werden automatisch nach einer bestimmten Zeit verschoben.

Booklets aus PDFs erzeugen

Ich bin kein Mensch der gerne Papers am Compter liest. Da ich viel unterwegs bin möchte ich gerne die Zeit nutzen und Papers auf meinen Reisen lesen. Ich liebe es A5 Booklets zu lesen.

In diesem Artikel möchte ich zeigen wie man Booklets aus einem bestehenden PDF erzeugen kann.

Zunächst muß man aus dem PDF ein PS-File erstellen. Dies kann man mit dem Programm pdf2ps tun. Diess Programm findet man in Debian in dem Package ghostscript. Folgender Befehl macht aus einem PDF ein PS:
$ pdf2ps file.pdf
Danach findet man in dem selben Verzeichnis eine Datei file.ps. Mit dieser kann man danach weiter arbeiten. Zunächst muß man die Seiten neu ordnen, damit man ein Booklet erhält. Die Seiten ordnet man mit dem Befehl:
$ psbook file.ps file-booklet.ps
Das Programm psbook findet man in dem Package psutils. Diese Seiten sind aber noch auf A4 ausgelegt, hier muß man noch 2 Seiten auf eine geben damit man ein A5-Booklet erhält. Das geschieht mit folgendem Befehl:
$ psnup -2 file-booklet.ps > file-booklet-2.ps
Danach haben wir ein Booklet wo immer 2 Seiten auf einer A4-Seite zu findet sind. Danach kann man das erhaltene File in ein PDF konvertieren
$ ps2pdf file-booklet-2.ps
und dieses dann im Duplex-Modus ausdrucken. Beim Duplex-Druck ist es wichtig das man auf der kurzen Kante umklappt, ansonsten werden die Seiten auf dem Kopf stehen.

Natürlich macht es Sinn wenn man diese Befehle alle in ein Skript schreibt um komfortabler damit arbeiten zu können.

Freitag, März 16, 2012

Von Vim zu Emacs

Ich weiß der Title klingt schon ein wenig seltsam, denn man wechselt nicht von einem Editor zu dem anderen. Nachdem ich mich in letzter Zeit sehr stark mit funktionaler Programmierung auseinandergesetzt habe, habe ich mir vorgenommen mit einmal Emacs als Editor anzusehen.

Ich habe mir Emacs als Editor angesehen, da dieser eine Programmierschnittstelle in Lisp hat, genauer gesagt in Emacs Lisp. Emacs Lisp ist ein Dialekt der Sprache LISP und damit auch eine funktionale Programmiersprache. Nebenbei auch noch eine der ältersten, noch verbreiteten, Programmiersprachen.

Der Umstieg von Vim auf Emacs ist schon eine große Herausforderung da diese ganz grundsätzlich verschieden sind. Außerdem gehen sie ganz unterschiedlichen Philosopophien nach. Der eine ist ein Editor mit dem man Text bearbeiten kann und der andere möchte eine Arbeitsumgebung sein, mit der man alles mögliche anstellen kann. Ich denke man sollte zumindest einen wirklich gut kennen damit man auch effizient arbeiten kann.

Ich werde mit Sicherheit, hier in diesem Blog, einige Artikel über den Emacs schreiben.

Donnerstag, Februar 23, 2012

Working with ssh-agent

For checking some git repositories it is very uncomfortable to work with public-keys because you have to commit the key every time you want to push, pull or other communications with the git repository.

If you have a lot of git repositories for a project you have to change to the first directory, make a git pull, commit your password for the public key and go to the next directory. For a lot of directories it is very bad style.

This is were ssh-agent comes to the spot. I start the ssh-agent and commit my password for the public key once with ssh-add. After that you can work with all git repositories were you have the same public key committed. The idea of the ssh-agent is to start it once and then you have to put some environment variables into all your shell where you are working. That's not very nice for me so I wrote a zsh-function for that case. Here you can see the function:

 1:  function ssha {
 2:    if [ $# -ne 1 ]; then
 3:      echo "usage: $0 [start|stop]"
 4:      return 1
 5:    fi
 6:    case "$1" in
 7:      start)
 8:        if [ -n "$SSH_AGENT_PID" ]; then
 9:          echo "ssh-agent already running"
10:          return 1
11:        fi
12:        /usr/bin/ssh-agent > /tmp/ssh-agent-pids
13:        . /tmp/ssh-agent-pids > /dev/null
14:        /usr/bin/ssh-add
15:        ;;
16:      stop)
17:        if [ -z "$SSH_AGENT_PID" ]; then
18:          echo "ssh-agent not running"
19:          return 1
20:        fi
21:        /usr/bin/ssh-agent -k > /tmp/ssh-agent-pids
22:        . /tmp/ssh-agent-pids > /dev/null
23:        ;;
24:      *)
25:        echo "usage: $0 [start|stop]"
26:        return 1
27:        ;;
28:    esac
29:  }

You can start and stop the ssh-agent with the same function. If you are working with some git repositories you could start it with ssha start. Then you have to give your password for the public key and you can work in the same shell. After finishing some work with that git repositories you could stop the server with ssha stop.