Sane PATH variable in Emacs on Mac OS X

On Mac OS X the system PATH variable is not recognized by emacs. This means that one can not simply type

mysql

in the emacs shell to get into the database. The emacs shell complains about “binary not found”.

Indeed

echo $PATH

reveals that emacs just looks into /bin, /usr/bin, /sbin and /usr/sbin.

To set the $PATH variable inside emacs one can append the following lines to the .emacs file (found on github, hattip Alex Payne):

; sane path
(setq path "/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/mysql/bin")
(setenv "PATH" path)

Next time Emacs starts one can go to the shell and

mysql

presents the database prompt.

Advertisements

Match and replace TAB

I am using the terminal inside emacs to modify and clean textfiles (colon separated) for import into MySQL – mostly with SED, GREP, AWK.
Replacing TAB in a textfile with SED was not as straightforward as I thought. So Google came up with an excellent post on macworld.com and here especially one post suggesting perl as a solution. It turned out perl behaves inside the pipe the same way as SED/AWK.

Replacing TAB ‘\t‘ with colon ‘,‘ in a textfile ‘SomeFile.txt‘ can be done with:

perl -pi -e 's/\t/,/g' SomeFile.txt

or using the pipe, which can be combined with grep, sed, awk, tr, head, tail, etc…

cat SomeFile.txt | perl -pi -e 's/\t/,/g'

*Very* similar to the sed invocation, except for the flags. “-pi” for “*print* every line out after making the changes, while editing *inplace*. That is, no backup file is kept. In reality, a temp file is written, and if all is well (ie the operation succeeds), the temp file is shifted “onto” the original file, giving the appearance of an in-place edit.

Emacs as MySQL frontend

After working quite a time with some minor MySQL databases in the (Emacs-) Terminal I just looked up the preinstalled SQL related emacs functions. Just entered M-x sql TAB and indeed the autocompletion showed a function sql-mysql, as expected…

I gave it a try with
M-x sql-mysql
and after prompting for database, servername, username and password Emacs connected to the database and presented the MySQL shell. So I bound sql-mysql to some keyboard shortcut, BUT entering the whole connection parameters each and every time was not acceptable.

Atomized.org has a really nice post on Enhancing Emacs’ SQL Mode (you can have a look, but you cannot read the post before pasting the content to a text editor). There I found some excellent functions which would provide a solution:

(setq sql-connection-alist
'((pool-a
(sql-product 'mysql)
(sql-server "1.2.3.4")
(sql-user "me")
(sql-password "mypassword")
(sql-database "thedb")
(sql-port 3306))
(pool-b
(sql-product 'mysql)
(sql-server "1.2.3.4")
(sql-user "me")
(sql-password "mypassword")
(sql-database "thedb")
(sql-port 3307))))

(defun sql-connect-preset (name)
"Connect to a predefined SQL connection listed in `sql-connection-alist'"
(eval `(let ,(cdr (assoc name sql-connection-alist))
(flet ((sql-get-login (&rest what)))
(sql-product-interactive sql-product)))))

(defun sql-pool-a ()
(interactive)
(sql-connect-preset 'pool-a))

Now, you can just run sql-pool-a and get connected right away. Because the buffers have good names, you can easily fire up many connections.

I included it in my .emacs file and appended
(DefGlobKey "s-a" 'sql-pool-a)
and with a keystroke the database promt appears.

Thx, atomized.org, but what’s that webpage giving you an epileptic fit looking at it?!. Excellent page 🙂

Sending Email from Emacs

Since Emacs is my main workhorse it comes handy to send plain text email straight from an Emacs buffer. Like for example this blog post directly from Emacs to the Rforge blog.

Emacs needs some configuration to do this, which I found on GNU.org’s Emacs Speaks SMTP:

First you need a helper application which enables Emacs to use a crypted connection to an IMAP server like e.g. starttls:

sudo aptitude install starttls

Then include the following into your ~/.emacs file to setup the outgoing mail server (SMTP):

;; Emacs Speaks SMTP (gnu.org) using the default mail agent ;; If you use the default mail user agent.
(setq send-mail-function 'smtpmail-send-it)
;; Send mail using SMTP via gmail.
(setq smtpmail-smtp-server "smtp.gmail.com")
;; Send mail using SMTP on the mail submission port 587.
(setq smtpmail-smtp-service 587)
;; Authenticate using this username and password against smtp.gmail.com. (setq smtpmail-auth-credentials
'(("smtp.gmail.com" 587 "captain.cheese" nil)))
;; Use STARTTLS against the server.
(setq smtpmail-starttls-credentials
'(("smtp.gmail.com" 587 "captain.cheese" nil)))

when you are not using gmail, you have to find out which SMTP server and port your provider uses and captain.cheese has to be changed to your user account. Note that nil can be changed to your passphrase, which I do not recommend since the .emacs file is plain text so it is possible to read your passphrase…

The standard Emacs keys to open an empty email formular is Control-x m, which I found to awkward, so I changed it to Hyper-c (this requires having CapsLock redefined as “Hyper”-key, which is another story and highly recommendable): (DefGlobKey "H-c" 'compose-mail)
(DefGlobKey "H-M-c" 'mail-send-and-exit)

Now H-c opens an email and after writing it H-M-c sends it.

Using the Directory Editor in Emacs

Emacs autocompletes path names when opening a file. Just hit TAB. When I forget the correct name of the file I am looking for I just stop at some place in the path and hit ENTER.

A list of files and folders in the directory show up and Emacs says (Dired by name). I just recently found out that Emacs offers full control over the listed files and directories in this so called Dired (directory editor) mode.

A look at the manual showed some straighforward commands, which work while Emacs is Dired. Move to the line listing the file/folder and hit

  • D to delete this file or folder
  • d to flagg this file/folder for deletion
  • u to unflagg this file/folder to prevent deletion
  • x to delete the files flagged for deletion
  • R Rename the specified file
  • C Copy the specified file(s). Emacs asks for the directory (and filename) where to copy to.

.emacs

Here goes my mighty dot-emacs file. The mighty key-bindings are courtesy of Andre Polonsky – thanks for that mate!!


(menu-bar-mode -1)
(toggle-scroll-bar -1)
(tool-bar-mode -1)
(blink-cursor-mode 0) ; don't blink cursor

(transient-mark-mode t) ; make the current 'selection' visible
(delete-selection-mode t) ; delete the selection area with a keypress
(setq search-highlight t ; highlight when searching...
query-replace-highlight t) ; ...and replacing
(fset 'yes-or-no-p 'y-or-n-p) ; enable one letter y/n answers to yes/no

;; don't show startup messages
(setq inhibit-startup-message t
inhibit-startup-echo-area-message t)

;; set frame title / icon title using filename or buffername and current date
;; little trick to replace /home/foo with ~ (www.emacswiki.org/cgi-bin/wiki/ShadyTrees)
(defun djcb-title-format ()
(if buffer-file-name
(replace-regexp-in-string "\\\\" "/"
(replace-regexp-in-string (regexp-quote (getenv "HOME")) "~"
(convert-standard-filename buffer-file-name)))
(buffer-name)))

(setq
frame-title-format '(:eval (concat (url-get-normalized-date) " " (djcb-title-format)))
icon-title-format '(:eval (concat "emacs:" (djcb-title-format))))

;; Backups
(setq make-backup-files t ; do make backups
backup-by-copying t ; and copy them ...
backup-directory-alist '(("." . "~/.emacs.d/backup/")) ; ... here
version-control t
kept-new-versions 2
kept-old-versions 5
delete-old-versions t)

;; full-screen mode
;; based on http://www.emacswiki.org/cgi-bin/wiki/WriteRoom
;; toggle full screen with custom keybinding; require 'wmctrl'
;; http://stevenpoole.net/blog/goodbye-cruel-word/
(defun djcb-full-screen-toggle ()
(interactive)
(shell-command "wmctrl -r :ACTIVE: -b toggle,fullscreen"))

(defun djcb-maximize-screen-toggle ()
(interactive)
(shell-command "wmctrl -r :ACTIVE: -b toggle,maximized_vert,maximized_horz"))

;; change caps- to hyper-key
(shell-command "xmodmap -e 'remove lock = Caps_Lock' && xmodmap -e 'keycode 66 = Hyper_L' && xmodmap -e 'add mod3 = Hyper_L'")

;; org-mode / remember-mode
;; we use org-mode as the backend for remember
(add-to-list 'auto-mode-alist '("\\.org$" . org-mode))

;(org-remember-insinuate)
(setq org-directory "~/.emacs.d/org/")
(setq org-default-notes-file (concat org-directory "/notes.org")
org-agenda-files (list (expand-file-name org-directory)
(concat (expand-file-name org-directory) "/todo.org"))
org-agenda-include-diary t)

;; org-latex.el
(autoload 'org-export-as-latex-batch "org-export-latex")
(autoload 'org-export-as-latex-to-buffer "org-export-latex"
"Call `org-exort-as-latex` with output to a temporary buffer" t)
(autoload 'org-replace-region-by-latex "org-export-latex"
"Replace the region from BEG to END with its LaTeX export." t)
(autoload 'org-export-region-as-latex "org-export-latex"
"Convert region from BEG to END in `org-mode' buffer to LaTeX." t)
(autoload 'org-export-as-latex "org-export-latex"
"Export current buffer to a LaTeX file." t)

;; start with my todo-list
(find-file "~/.emacs.d/org/todo.org")

;; Custom Colors from Dirk Binnema
; (set-background-color "black")
; (set-foreground-color "lightblue")
;
; (set-face-foreground 'font-lock-string-face "#123467") ;
; (set-face-foreground 'font-lock-comment-face "#aaaaaa") ;
; (make-face-italic 'font-lock-comment-face)
;
; (set-face-foreground 'font-lock-keyword-face "lemonchiffon") ;
; (make-face-bold 'font-lock-keyword-face)
;
; (set-face-foreground 'font-lock-string-face "#ffffff") ;
; (set-face-foreground 'font-lock-preprocessor-face "red") ;
; (set-face-foreground 'font-lock-constant-face "green") ;
;
; (set-face-foreground 'font-lock-type-face "lightblue")
; (make-face-bold 'font-lock-type-face)
;
; (set-face-foreground 'font-lock-function-name-face "darkcyan")
; (set-face-foreground 'font-lock-variable-name-face "darkgreen")
;
; (set-face-foreground 'font-lock-warning-face "yellow")
; (set-face-underline 'font-lock-warning-face "red")
;
(set-face-background 'region "#777777")

(set-face-foreground 'mode-line "#777777")
(set-face-background 'mode-line "#333333")

;; The Sane Emacs Keybindings

; I included the bindings directly into my .emacs, so the load-file is no longer necessary
;(load-file "~/.emacs.d/bindings.el")

;; auxiliary functions

(defun DefGlobKey (k b)
(define-key global-map (read-kbd-macro k) b) )
(defun DefSrchKey (k b)
(define-key isearch-mode-map (read-kbd-macro k) b) )

(defun other-other-window ()
(interactive)
(other-window -1))
(defun yank-push ()
(interactive)
(yank-pop -1))
(defun move-n-lines (n)
(scroll-up n))

(setq scroll-preserve-screen-position t)

(defun scroll-one-left ()
(interactive)
(backward-char)
(scroll-left -1))
(defun scroll-one-right ()
(interactive)
(forward-char)
(scroll-right -1))
(defun scroll-one-up ()
(interactive)
(move-n-lines -1))
(defun scroll-one-down ()
(interactive)
(move-n-lines 1))
(defun page-up ()
(interactive)
(move-n-lines (- 1 (window-height))))
(defun page-down ()
(interactive)
(move-n-lines (- (window-height) 1)))

;; basic movement

(DefGlobKey "H-j" 'backward-char)
(DefGlobKey "H-l" 'forward-char)
(DefGlobKey "H-i" 'previous-line)
(DefGlobKey "H-k" 'next-line)
(DefGlobKey "H-u" 'beginning-of-line)
(DefGlobKey "H-o" 'end-of-line)

(DefGlobKey "H-M-j" 'backward-word)
(DefGlobKey "H-M-l" 'forward-word)
(DefGlobKey "H-M-i" 'backward-paragraph)
(DefGlobKey "H-M-k" 'forward-paragraph)
(DefGlobKey "H-M-u" 'page-up)
(DefGlobKey "H-M-o" 'page-down)

(DefGlobKey "H-J" 'scroll-one-left)
(DefGlobKey "H-L" 'scroll-one-right)
(DefGlobKey "H-I" 'scroll-one-up)
(DefGlobKey "H-K" 'scroll-one-down)
(DefGlobKey "H-U" 'beginning-of-buffer)
(DefGlobKey "H-O" 'end-of-buffer)

(DefGlobKey "H-." 'isearch-forward)
(DefGlobKey "H-m" 'isearch-backward)
(DefGlobKey "H-M-." 'isearch-forward-regexp)
(DefGlobKey "H-M-m" 'isearch-backward-regexp)

(DefGlobKey "H-M-," 'recenter)

;; basic editing

(DefGlobKey "H-æ" 'advertised-undo)
(DefGlobKey "H-M-æ" 'redo)
(DefGlobKey "H-ø" 'backward-delete-char-untabify)
(DefGlobKey "H-M-ø" 'delete-char)
(DefGlobKey "H-p" 'kill-whole-line)
(DefGlobKey "H-M-p" 'kill-line)

(DefGlobKey "H-" 'set-mark-command)
(DefGlobKey "H-M-" 'exchange-point-and-mark)
(DefGlobKey "H-M-å" 'mark-paragraph)
(DefGlobKey "H-å" 'mark-whole-buffer)

(DefGlobKey "H-M-h" 'kill-region)
(DefGlobKey "H-h" 'kill-ring-save)
(DefGlobKey "H-y" 'yank)
(DefGlobKey "H-M-y" 'yank-pop)
(DefGlobKey "H-Y" 'yank-push)
(DefGlobKey "H-n" 'replace-string)
(DefGlobKey "H-M-n" 'replace-regexp)

(DefGlobKey "H-_" 'fill-region)

;; basic control

(DefGlobKey "H-q" 'save-buffer)
(DefGlobKey "H-M-q" 'write-file)
(DefGlobKey "H-w" 'find-file)
(DefGlobKey "H-r" 'switch-to-buffer)
(DefGlobKey "H-M-r" 'next-buffer)
(DefGlobKey "H-e" 'kill-this-buffer)
(DefGlobKey "H-M-e" 'save-buffers-kill-emacs)

(DefGlobKey "M-E" 'kill-this-buffer)
(DefGlobKey "M-J" 'previous-buffer)
(DefGlobKey "M-L" 'next-buffer)

(DefGlobKey "H-M-s" 'ess-eval-buffer-and-go)
(DefGlobKey "H-s" 'ess-eval-region-and-go)
(DefGlobKey "H-t" 'tex-compile)
(DefGlobKey "H-a" 'term)
(DefGlobKey "H-A" 'shell)

(DefGlobKey "H-F" 'djcb-maximize-screen-toggle)
(DefGlobKey "H-f" 'djcb-full-screen-toggle)
(DefGlobKey "H-M-z" 'split-window-horizontally)
(DefGlobKey "H-z" 'split-window-vertically)
(DefGlobKey "H-x" 'delete-window)
(DefGlobKey "H-M-x" 'delete-other-windows)
(define-key global-map [H-tab] 'other-window)
(define-key global-map [H-M-tab] 'other-other-window)

;; search mode

(DefSrchKey "H-m" 'isearch-repeat-backward)
(DefSrchKey "H-." 'isearch-repeat-forward)
(DefSrchKey "H-M-m" 'isearch-repeat-backward)
(DefSrchKey "H-M-." 'isearch-repeat-forward)
(DefSrchKey "H-," 'isearch-query-replace)
(DefSrchKey "H-M-," 'isearch-query-replace-regexp)

(DefSrchKey "H-/" 'isearch-complete)
(DefSrchKey "H-M-/" 'isearch-toggle-case-fold)
(DefSrchKey "H-?" 'isearch-toggle-regexp)

(DefSrchKey "H-n" 'isearch-cancel)
(DefSrchKey "H-M-n" 'isearch-exit)

;; other features

;;help
;(DefGlobKey "H-f" 'describe-key)
;(DefGlobKey "H-M-f" 'describe-function)

;; I do not use Lisp yet, but constantly get into the evaluation queue, so I comment away these
;lisp
;(DefGlobKey "H-" 'eval-defun)
;(DefGlobKey "H-M-" 'eval-region)