jeudi 29 octobre 2015

Delete lines matching a regex; Keep lines matching a regexp

kill-lines-rx will prompt you for a regex and delete all lines matching it. Use with a prefix argument (C-u) to highlight and ask before removing.
(defun kill-lines-rx (&optional ask)
  (interactive "P")
  (save-excursion
    (goto-char (point-min))
    (let ((rx (read-regexp "Rx: ")))
      (while (search-forward-regexp rx nil t)
 (beginning-of-line)
 (set-mark (save-excursion (end-of-line) (point)))
 (when (or (not ask) (y-or-n-p "Kill? "))
   (delete-region (point) (mark))
   (delete-char 1))))))
kill-lines-unless-rx will prompt you for a regex and delete all lines not matching it. Use with a prefix argument (C-u) to highlight and ask before keeping.
(defun kill-lines-unless-rx (&optional ask)
  (interactive "P")
  (let (keep)
    (save-excursion
      (goto-char (point-min))
      (let ((rx (read-regexp "Rx: ")))
 (while (search-forward-regexp rx nil t)
   (beginning-of-line)
   (set-mark (save-excursion (end-of-line) (point)))
   (when (or (not ask) (y-or-n-p "Keep? "))
     (push (buffer-substring (point) (mark)) keep))
   (forward-line))))
    (erase-buffer)
    (dolist (e (nreverse keep))
      (insert e "\n"))))

vendredi 4 septembre 2015

org-mode live html export preview in the browser

Using the MozRepl Firefox extension along with Emacs moz.el package you can export your current org document to html on each buffer change or on each save. There's a bunch of JS code to make Firefox resuse existing tabs instead of opening new ones. Run M-x toggle-live-preview or M-x toggle-preview-on-save depending on what you want.
(defvar moz-useful-functions "
function find_tab_with_url(url) {
    var bs = gBrowser.browsers
    for (var i = 0; i < bs.length; i++) {
 try {
     if (bs[i].currentURI.spec == url)
  return i
 } catch (e) {}
    }
    return -1
}

function select_tab(t) {
    if (gBrowser.selectedTab != t)
        gBrowser.selectedTab = t
}

function add_or_reload_url (url) {
    var i = find_tab_with_url(url)
    var t = ''
    if (i < 0) {
 t = gBrowser.addTab(url)
    } else {
 gBrowser.browsers[i].reload()
        t = gBrowser.tabs[i]
    }
    select_tab(t) 
}
")

(defun preview-buffer-in-firefox ()
  (interactive)
  (require 'moz)
  (moz-send-string moz-useful-functions)
  (let ((fn (org-html-export-to-html)))
    (moz-send-string (concat "add_or_reload_url(\"file://" (expand-file-name fn) "\");\n"))))

(defun live-preview (&optional beg end len)
  (when (or (not (and beg end len)) (and beg end len (/= (1+ (- end beg)) len)))
    (message "%s: update!" (format-time-string "%r"))
    (preview-buffer-in-firefox)))

(defun toggle-live-preview ()
  (interactive)
  (if (memq 'live-preview first-change-hook)
      (remove-hook 'first-change-hook 'live-preview 'buffer-local)
    (add-hook 'first-change-hook 'live-preview nil 'buffer-local)))

(defun toggle-preview-on-save ()
  (interactive)
  (if (memq 'live-preview after-save-hook)
      (remove-hook 'after-save-hook 'live-preview 'buffer-local)
    (add-hook 'after-save-hook 'live-preview nil 'buffer-local)))

lundi 17 août 2015

Quickly edit your init file

Nothing fancy about this, just handy: opens my init file and place cursor at the end.
(defun init ()
  (interactive)
  (find-file "~/.emacs.d/init.el")
  (goto-char (point-max)))

Rename file and buffer

I don't know why this is not built-in...
(defun rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive "sNew name: ")
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not filename)
        (message "Buffer '%s' is not visiting a file!" name)
      (if (get-buffer new-name)
          (message "A buffer named '%s' already exists!" new-name)
        (progn
          (rename-file name new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil))))))

Open current file as root

Don't think I've written this one myself and I don't remember where it comes from. Oh well.
(defun sudo-edit (&optional arg)
  "Edit currently visited file as root.

With a prefix ARG prompt for a file to visit.
Will also prompt for a file to visit if current
buffer is not visiting a file."
  (interactive "P")
  (if (or arg (not buffer-file-name))
      (find-file (concat "/sudo:root@localhost:"
                         (ido-read-file-name "Find file(as root): ")))
    (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))

dimanche 16 août 2015

Number line in region using custom printf-like format

By default starts at zero, but you can use C-u 50 M-x my-number-line to make it start at 50...
The commands asks for a printf format that will be inserted at the start of each line, so you can do right alignment, hex, whatever.

Example region:
Pellentesque tristique imperdiet tortor. Cras placerat accumsan
nulla. Donec hendrerit tempor tellus. Nam a sapien. Nam vestibulum
accumsan nisl. Donec at pede. Pellentesque dapibus suscipit
ligula. Nunc porta vulputate tellus. Nunc aliquet, augue nec
adipiscing interdum, lacus tellus malesuada massa, quis varius mi
purus non odio. Nunc rutrum turpis sed pede. Etiam vel tortor sodales
tellus ultricies commodo.
Mark all lines, M-x my-number-line RET 0x%03x SPC RET and BAM, lines are prefixed with hex line numbers:
0x000 Pellentesque tristique imperdiet tortor. Cras placerat accumsan
0x001 nulla. Donec hendrerit tempor tellus. Nam a sapien. Nam vestibulum
0x002 accumsan nisl. Donec at pede. Pellentesque dapibus suscipit
0x003 ligula. Nunc porta vulputate tellus. Nunc aliquet, augue nec
0x004 adipiscing interdum, lacus tellus malesuada massa, quis varius mi
0x005 purus non odio. Nunc rutrum turpis sed pede. Etiam vel tortor sodales
0x006 tellus ultricies commodo.
(defun my-number-line (arg beg end fmt)
  (interactive "P\nr\nsformat: ")
  (let ((n (if (numberp arg) arg 0)))
    (save-excursion
      (goto-char beg)
      (beginning-of-line)
      (while (< (point) end)
        (beginning-of-line)
        (let ((s (format fmt n)))
          (insert s)
          (incf end (length s)))
        (incf n)
        (forward-line)
        (beginning-of-line)))))

Put readable file encoding and line endings mode in the mode-line

I was never able to decipher the default mode-line information about encoding/line endings so I changed it:

(defvar my-mode-line-coding-format
  '(:eval
    (let* ((code (symbol-name buffer-file-coding-system))
           (eol-type (coding-system-eol-type buffer-file-coding-system))
           (eol (if (eq 0 eol-type) "UNIX"
                  (if (eq 1 eol-type) "DOS"
                    (if (eq 2 eol-type) "MAC"
                      "???")))))
      (concat code " " eol " "))))
(put 'my-mode-line-coding-format 'risky-local-variable t)
(setq-default mode-line-format (substitute 'my-mode-line-coding-format 'mode-line-mule-info mode-line-format))
Now you get "utf-8 UNIX" in place of the cryptic "U*:%" whatever bullshit it was.