The kill ring is a nice thing to have. Only the navigation is a bit to uncomfortable (I am refering to doing C-y again and again until the to desired element is found). So this is what I came up with to feel more ‚comfy‘:

(defun pre-process-kill-ring-element (element)
  (replace-regexp-in-string "^[[:space:]]+" ""
                            (replace-regexp-in-string "[[:space:]]+$" "" (substring-no-properties element))))
 
(defun preprocess-kill-ring ()
  (let ((result nil)
        (element nil))
    (dolist (element kill-ring)
      (progn
        (setq element (pre-process-kill-ring-element element))
        (when (not (or
                    (eq 0 (length element))
                    (string-match-p "[\r\n]+" element)))
          (setq result (cons element result)))))
    (reverse result)))
 
(defun browse-kill-ring ()
  (interactive)
  (insert (completing-read "Pick an element: "
                       (preprocess-kill-ring))))
 
(global-set-key (kbd "C-M-y") 'browse-kill-ring)

Einleitung

Wenn man im Zusammenhang von Audio-CD’s von rippen spricht, meint man für gewöhnlich den Vorgang die Daten der CD auf einen Festplatte zu kopieren und sie aus dem wav-Format in dem sie auf der CD vorliegen in ein komprimiertes, sparsameres Format zu konvertieren.

Audio-WAS?

Da Audio CD’s schon seit längerem durch andere Medien überholt wurden und Musik zunehmend über andere Wege verteilt wird, läuft die Kunst zu rippen Gefahr in Vergessenheit zu geraten 🙂 Da es ferner ein Vorgang ist den ich selbst so selten durchführe dass ich jedes mal aufs neue nachsehen muss wie es genau geht. Schreib ich mir hier einfach mal auf wie ich es mache…

Zur Sache

Rippen ist eigentlich ein Vorgang in zwei Schritten:

  1. kopieren
  2. Konvertieren

Kopieren

Zum kopieren bietet sich cdparanoia an – der Beschreibung nach „an audio CD reading utility which includes extra data verification features“. cdparanoia kopiert also die Daten von der CD auf die Festplatte. Nicht mehr. Aber auch nicht weniger 🙂 Folgendes Beispiel ist der manpage entnommen und kopiert die einzelnen Tracks einer CD in das aktuelle Arbeitsverzeichnis:

$ cdparanoia -B # that's all

Konvertieren

Beim konvertieren werden die Daten aus dem ursprünglichen Format in ein anderes Format „übersetzt“. Dieser Aufgabe übernimmt beim mp3 Format zum Beispiel lame. Natürlich gibt es auch Alternativen zu mp3 und zu jedem codec gibt es Tools coder und decoder, die einem helfen die Daten aus dem jeweiligen Format zu lesen bzw zu schreiben.

Die Dateinamen anpassen

Mittlerweile wurden die Daten von der CD kopiert und konvertiert und liegen eigentlich fertig in… Ja, wo eigentlich? In file_01.mp3?
Jetzt wäre es eigentlich an der Zeit einen vernünftigen Dateinamen zu vergeben 🙂 Das kann man natürlich mal eben händisch erledigen – oder schon mal als Option beim konvertieren. Aber wenn man das jetzt für jeden Track erledigen soll, wird das doch irgendwann lästig. Zum Glück wurde das Problem schon erkannt und es gibt einen Weg herauszufinden welche CD da gerade gerippt wird: cddb. Mit Hilfe der CDDB lässt sich der Prozess der Namensvergabe automatisieren.

Die all-in-one Lösung

Rippen ist offensichtlich ein Vorgang der so oft genug durchgeführt, daß die Verwendung einer Software die diese Aufgaben automatisiert erledigt mehr Zeit einspart als die Entwicklung einer solchen in Anspruch nimmt. Wäre Software materiell gäbe es einen Berg von Programmen die kopieren, konvertieren und CDDB abfragen. Ich habe für mich RipIt aus diesem Berg ausgegraben und bin damit ganz zufrieden. Ein DEB-Paket wird mit der Linux Distribution meiner Wahl ausgeliefert – was mir die Installation enorm erleichterte. Es hilft außerdem in den zwei Anwendungsfällen die bei mir des öfteren Vorkommen:

    Musik

    Ich benötige ein Backup von einer verstaubten Musik-CD die ich auf dem Dachboden gefunden habe. Hier sollte möglichst jeder Track einzelnen gerippt werden.

    ripit # los gehts...

    Hörspiele

    Ich möchte ein Backup von einer Hörspiel-CD erstellen (bevor sie im Kinderzimmer so arg verkratzt wird, dass sie nicht mehr funktioniert). Hier soll bitte der ganze Inhalt der CD in einer Datei abgelegt werden.

    ripit --merge 1- # und ab die Post...
    

I am using projectile since a couple of days and really love how I can change to another file in the current project (using C-c p f). However I am facing a little issue when I am generating a tags file for etags. I get

projectile-regenerate-tags: ctags: invalid option — ’e’
Try ’ctags –help’ for a complete list of options.

Whenever I „C-c p R“ even though I have picked etags as my tags program. However after reading this I have constructed a tags command for me like this:

(setq projectile-tags-command "etags -a TAGS \"%s\"")

Ans it looks like now it works nicely…





The Emacs built-in command (garbage-collect) gives detailed information about the data structures that currently consume memory. It is propably not the most usefull information but I wanted to collect the data and plot it. I started with writing functions to access the list returned from (garbage-collect):

(defsubst get-mem-conses (mi)
  (let ((data (nth 0 mi)))
    (/ (* (nth 1 data) (+ (nth 2 data) (nth 3 data))) (* 1024 1024.0))))
 
(defsubst get-mem-symbols (mi)
  (let ((data (nth 1 mi)))
    (/ (* (nth 1 data) (+ (nth 2 data) (nth 3 data))) (* 1024 1024.0))))
 
(defsubst get-mem-misc (mi)
  (let ((data (nth 2 mi)))
    (/ (* (nth 1 data) (+ (nth 2 data) (nth 3 data))) (* 1024 1024.0))))
 
(defsubst get-mem-string-header (mi)
  (let ((data (nth 3 mi)))
    (/ (* (nth 1 data) (+ (nth 2 data) (nth 3 data))) (* 1024 1024.0))))
 
(defsubst get-mem-string-bytes (mi)
  (let ((data (nth 4 mi)))
    (/ (* (nth 1 data) (nth 2 data)) (* 1024 1024.0))))
 
(defsubst get-mem-vector-header (mi)
  (let ((data (nth 5 mi)))
    (/ (* (nth 1 data) (nth 2 data)) (* 1024 1024.0))))
 
(defsubst get-mem-vector-slots (mi)
  (let ((data (nth 6 mi)))
    (/ (* (nth 1 data) (+ (nth 2 data) (nth 3 data))) (* 1024 1024.0))))
 
(defsubst get-mem-floats (mi)
  (let ((data (nth 7 mi)))
    (/ (* (nth 1 data) (+ (nth 2 data) (nth 3 data))) (* 1024 1024.0))))
 
(defsubst get-mem-intervals (mi)
  (let ((data (nth 8 mi)))
    (/ (* (nth 1 data) (+ (nth 2 data) (nth 3 data))) (* 1024 1024.0))))
 
(defsubst get-mem-buffers (mi)
  (let ((data (nth 9 mi)))
    (/ (* (nth 1 data) (nth 2 data)) (* 1024 1024.0))))

Then I had need for a function that will be called periodically. This function will call (garbage-collect) and store the data in the file-system:

(defun collector (filename)
  "Write memory data into file with FILENAME."
  (let ((mi (garbage-collect)))
    (with-temp-buffer
      (insert 
       (format "%f %f %f %f %f %f %f %f %f %f %f\r\n"
               (float-time)
               (get-mem-conses mi)
               (get-mem-symbols mi)
               (get-mem-misc mi)
               (get-mem-string-header mi)
               (get-mem-string-bytes mi)
               (get-mem-vector-header mi)
               (get-mem-vector-slots mi)
               (get-mem-floats mi)
               (get-mem-intervals mi)
               (get-mem-buffers mi)))
      (let ((message-log-max nil))
        (append-to-file (point-min) (point-max) filename)))))

Next I have need for a function that starts the collection process and one that stops it again:

(defvar collector-timer nil)
 
(defun start-collection (filename interval)
  (interactive "FEnter filename:\nMEnter interval: ")
  (setq collector-filename filename
        collector-timer (run-at-time
                         2
                         (string-to-number interval)
                         'collector filename)))
(defun stop-collection ()
  (interactive)
  (when (timerp collector-timer)
    (cancel-timer collector-timer)))

Finally the collected data should be plotted into a nice graph:

(defun plot-data (datafile imagefile)
  (interactive "FEnter data-filename: \nFEnter image-filename:")
  (let ((gnuplot (start-process "gnuplot" "*gnuplot*" "gnuplot")))
    (process-send-string gnuplot "set term png\n")
    (process-send-string gnuplot (format "set output \"%s\"\n" imagefile))
    (process-send-string gnuplot "set grid\n")
    (process-send-string gnuplot "set title \"Emacs memory consumption by category\"\n")
    (process-send-string gnuplot "set xlabel \"interval\"\n")
    (process-send-string gnuplot "set autoscale\n")
    (process-send-string gnuplot "set ylabel \"2^{20} bytes\"\n")
    (process-send-string gnuplot (format "plot \"%s\" using 2 title \"cons cells\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 3 title \"symbols\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 4 title \"\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 5 title \"string header\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 6 title \"string bytes\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 7 title \"vector header\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 8 title \"vector slots\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 9 title \"floats\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 10 title \"intervals\" with lines" datafile))
    (process-send-string gnuplot (format ", \"%s\" using 11 title \"buffers\" with lines\n" datafile))))

Turns out that my emacs usage was really calm in the time when I sampled the data 🙂 In fact I have entered some kilobytes of test data into the scratch buffer with two seconds between two samples:

I recently wanted to have some more information about which of the packages I am using contributes more time to the total (emacs-init-time) I use to keep my emacs init code in a single file and I manually divide the file into sections of related code. A section is opened by entering a carefully prepared comment string and ended by another one so that it looks like this:

;; [ an example section
(some emacs lisp)
(and some more)
;; ]

Starting from here I could alter my init file to write down time values from the stop-clock (And since I also need to know to which section the time value belongs – the section names). Therefore I invoked query-replace-regexp and query-replace to surround my sections with emacs lisp to collect the necessary information:

query replace regexp: ;; []] \(.*\) ➤ ;; [ \1[C-q C-j](add-to-list 'section-names "\1")
query replace: ;; ] ➤  (add-to-list 'init-runtime (get-internal-run-time))[C-q C-j];; ]

My example section would then look like this:

;; [ an example section
(add-to-list 'section-names "an example section")
(some emacs lisp)
(and some more)
(add-to-list 'init-runtime (get-internal-run-time))
;; ]

After the whole file is processed I end up with two lists (I called them section-names and init-runtime). These I then further-process. So I switched to an org-mode buffer and entered


#+NAME: perf_data_names
#+BEGIN_SRC emacs-lisp
(reverse section-names)
#+END_SRC

#+NAME: perf_data_times
#+BEGIN_SRC emacs-lisp
(progn
    (let ((bak-init-times init-runtime)
          (next nil)
          (result '()))
        (while bak-init-times
           (setq next (car bak-init-times))
           (setq bak-init-times (cdr bak-init-times))
           (add-to-list 'result (+ (nth 2 next)
                                   (* (nth 1 next) 1000000))))
      result))
#+END_SRC

#+BEGIN_SRC python :var sections=perf_data_names :var times=perf_data_times :results output
xtics="set xtics ("
numsections=len(sections)
for i, section in enumerate(sections):
    xtics = xtics +  "\"{0}\" {1}".format(section, i+1)
    if i<numsections-1:
      xtics = xtics + ", "
xtics+=")"      
print("set grid")
print(xtics)
print("plot \"-\" using 1:2 title "Stopclock times")
for i, time in enumerate(times):
    print("{0} {1}".format(i+1, time))
print("e")    
#+END_SRC

This results in a snippet of text that can be fed into gnuplot! Gnuplot kindly generates the following image:

It turns out that no one can really be blamed for beeing responsible and it must be taken into consideration that some of the loading may be deferred and is not subject to the analysis (No, I did not look up how exactly use-package is deferring package loading). Some sections take more time then others:

  • packages
  • s
  • global appearance
  • yasnippet
  • org mode
  • java mode
  • elpy python
  • magit

There are a couple of symbols the emacs‘ lisp interpreter gives special meaning to. Since for some reason these never made it into my long-term memory I collect them here for later reference. Quotes are copied from all over the internet (mostly from GNU Emacs Lisp reference). A reference is given in the last column.

Symbol Meaning Reference
# The sharp quote (or function quote, or simply #‘) is an abbreviation for the function form. It is essentially a version of quote (or ‚) which enables byte-compilation, but its actual usefulness has changed throughout the years. reference
` Backquote constructs allow you to quote a list, but selectively evaluate elements of that list. reference
: A symbol whose name starts with a colon (‘:’) is called a keyword symbol. These symbols automatically act as constants, and are normally used only by comparing an unknown symbol with a few specific alternatives. reference
, Unquotes expressions in backquote-constructs. reference
' Prevents its single argument from beeing evaluated reference
? Introduces a „character literal“ (eg ?a). Evaluates to the printed representation of the character. reference
,@ Splice an evaluated value into a list reference
; Introduces a comment. reference

Subversion

Command Description
svn cat -r 1234 path/to/file | less View file from specific revision
svn update -r 1234 path/to/file Update file to some older revision
svn checkout svn://host/path/to/repo Check out a repository
svn commit some/file.cpp -m „Changes!“ Push changes into the central repository
svn update Pull updates from the central repository into the working copy
svn merge -rstart:end svn://host/branch/to/merge Merge changes from revsion start to end (eg HEAD) into current branch.
svn resolved path/to/file/under/svn/vc Mark merge conflict as resolved

rpm

Command Description
rpm2cpio package.rpm | cpio -idmv View package files
rpm -ivh file.rpm Install package file.rpm

  • -i install
  • -v verbose output
  • -h print progress indicator
rpm -qa –last List installed packages. Most recently installed first.
rpm -qi package Print information about installed package
rpm -ql package List files belonging to package
rpm -qf /path/to/some/file Find the package that provides file

There is a couple of packages for emacs that really have application character. Like for example:

  • https://www.emacswiki.org/emacs/Magit
  • https://www.emacswiki.org/emacs/EmacSpeak
  • https://www.emacswiki.org/emacs/GnusTutorial
  • https://github.com/skeeto/elfeed
  • https://emacswiki.org/emacs/Sunrise_Commander

And there are propably some more. Me personally – I did not adopt well to the „App in Emacs“ approach as I use none of the mentioned packages. It’s not a categorical decision, I just did not get used to it. My writings in Emacs Lisp have a much lesser extend: Recently I had need to copy files from one directory to the other and I just love to have this done with two directories showing up side by side as in well known „file commanders“. That said Emacs Lisp comes to the rescue!

(defun mp-dired-2pane-copy-over ()
  (interactive)
    (when (eq 2 (length (window-list)))
      (let ((other-directory nil)
            (file-to-copy (dired-get-filename)))
        (progn
          (other-window 1)
          (setq other-directory (dired-current-directory))
          (other-window 1)
          (copy-file file-to-copy other-directory)
          (other-window 1)
          (revert-buffer)
          (other-window 1)))))

I have customized my ibuffer-format to have the name column width set to 36. This is fine in 99% of the filenames showing up there. However I also have to access a couple of files that have a common prefix that is longer then 36 characters. This way the files cannot be distinguished in ibuffer… Since I am not willing to have the width set to even higher value I have added this little defun to my init.el to deal with the issue:

 
(defun mp/ibuffer-show-filename ()
  (interactive)
  (let ((buf (ibuffer-current-buffer))
        (lsoutput nil))
    (when (file-exists-p (buffer-file-name buf))
      (with-temp-buffer
        (let* ((filename (buffer-file-name buf))
               (default-directory (file-name-directory filename))
               (just-filename (file-name-nondirectory filename)))
          (call-process "/usr/bin/ls" nil t nil "-l" just-filename)
          (setq lsoutput (buffer-substring-no-properties (point-min) (- (point-max) 1))))))
    (message lsoutput)))
 
(define-key ibuffer-mode-map (kbd "f") 'mp/ibuffer-show-filename)

This way I can stick to my column width of 36 and whenever I have need to see the a longer filename I can just press f on the entry and see the name at the bottom of the screen.

Introduction

Software creeping slowly into every day devices and everybody carrying around a device that easily outperforms a couple of 90s supercomputers is a clear indicator for the increased presence of software. The Number of projects hosted on a well known „developer-platform“ also indicates that the amount of software has increaseda lot in the last years. Long story made short: As a software developer there is no need to re-invent the wheel every now and then. Normally there is a library available for one or the other task that one has to solve. Question is how to pull foreign projects into your own python project? There is a couple of options!

pip

pip allows for installation of packages from the python package index which is an extensive repository of python packages. I cannot say what pip stands for, but it is an extremly usefull tool. Using opensuse I had to install it first. The package is called python3-pip for me. Then I can start pulling in packages: Let’s say for some reason I would have to parse some java source codes from a python script. Since I am not willing to spend time on writing a Java Parse now I have a look at pypi and find this. I want to give it a try and pull in the package using pip:

$ pip install javalang

However since pip tries to install the package below /usr/lib/ the installation initially fails since I am not root… So I try again this time looking up in the pip manual that there is an option for installation into my home directory:

$ pip install --user javalang

and this time it works! Now I can start trying out the example code from the javalang github page

#!/usr/bin/python3
 
import javalang
 
tree = javalang.parse.parse("package javalang.brewtab.com; class Test {}")
print(tree)
$ ./javalang-test.py3
CompulationUnit

Which looks like the process of downloading the package and making it available to the python interpreter has worked as expected! Looking up information about the installed package reveals following information:

$ pip show javalang
---
Metadata-Version: 1.1
Name: javalang
Version: 0.10.1
Summary: Pure Python Java parser and tools
Home-page: http://github.com/c2nes/javalang
Author: Chris Thunes
Author-email: cthunes@brewtab.com
License: UNKNOWN
Location: /home/user/pythonbase/lib/python3.4/site-packages
Requires: six

Manual Installation

The process is documented here.