Skip to content

Latest commit

 

History

History
621 lines (532 loc) · 24.3 KB

emacs24.hacky.org

File metadata and controls

621 lines (532 loc) · 24.3 KB

Hacky Functions

;; For reference, the difference between symbol and lambda form of the macros:
;; http://stackoverflow.com/questions/753459/emacs-getting-readable-keyboard-macros
;; You always want symbol form, i.e. name-last-kbd-macro

;; only show matches
(defun occurrences (regexp &rest ignore)
  "Show all matches for REGEXP in an `occur' buffer."
  ;; keep text covered by occur-prefix and match text-properties
  (interactive (occur-read-primary-args))
  (occur regexp)
  (with-current-buffer (get-buffer "*Occur*")
    (let ((inhibit-read-only t)
          delete-from
          pos)
      (save-excursion
        (while (setq pos (next-property-change (point)))
          (goto-char pos)
          (if (not (or (get-text-property (point) 'occur-prefix)
                       (get-text-property (point) 'occur-match)))
              (if delete-from
                  (delete-region delete-from (point))
                (setq delete-from (point)))
            (when delete-from
              (delete-region delete-from (point))
              (if (get-text-property (point) 'occur-prefix)
                  (insert "\n")
                (insert " ")))
            (setq delete-from nil)))))))


(fset 'org-clocktable-daystep-remove-table-formula
      [?\C-s ?# ?+ ?T ?B ?L ?F ?M ?\C-a ?\C-k ?\C-k ?\C-k ?| ?- tab])

(fset 'org-clocktable-daystep-add-date-column
      [?\C-s ?d ?a ?i ?l ?y ?  ?r ?e ?p ?o ?r ?t ?: return ?\C-a ?\C-  ?\C-\M-f ?\C-\M-f ?\C-f ?\C-f ?\C-w ?\C-  ?\C-e ?\C-w ?\C-n ?\C-f M-S-right ?\C-y tab C-down C-up])

(fset 'org-clocktable-daystep-remove-headline
      [?\C-s ?h ?e ?a ?d ?l ?i ?n ?e ?\C-a ?\C-  ?\C-n ?\C-n ?\C-w])


(fset 'ce 'calc-eval)

;; Eval the region at the cursor point (i.e. just the variable)
(fset 'eval-at-cursor "\243\C-c\C-r\C-f\C-b")

;; Enclose a region in an anonymous function
(fset 'javascript-region-2-anonymous-function
      [?\C-w ?f ?u ?n ?c ?t ?i ?o ?n ?\( ?\C-f ?  ?\{ return ?\C-y return ?\C-f ?\; left ?\C-\M-p ?\C-f ?\C-f ?r ?e ?t ?u ?r ?n ?\M-  tab])

;; Delete matched pair of parentheses
(fset 'unnest-enclosed-parens
      [?\C-  ?\C-\M-n ?\C-g backspace ?\C-x ?\C-x ?\C-g ?\C-d])

;; Enclose the sexp in front of the cursor within round brackets
(fset 'nest-outer-round-parens
      [?\C-  ?\C-\M-f ?\( ?\C-\M-b ?\C-f])

;; Enclose the sexp in front of the cursor within square brackets
(fset 'nest-outer-square-parens
      [?\C-  ?\C-\M-n ?\[])

;; Enclose the sexp in front of the cursor within curly brackets
(fset 'nest-outer-curly-parens
      [?\C-  ?\C-\M-n ?\{])

;; Add another quoted argument (separated by comma)
(fset 'add-quoted-argument
      "\C-f, \"")

(fset 'add-single-quoted-argument
      "\C-f, '")

;; Old version with kill-visual-line
;;(fset 'copy-line-and-replace
;;   [?\C-a ?\C-k ?\C-y return ?\C-y ?\C-x ?\C-x ?\M-% ?\C-u ?\C-x ?q return ?\C-u ?\C-x ?q return ?! ?\C-a])

;; Copy the entire line that you're on and query replace
(fset 'copy-line-and-replace
      [?\C-a ?\M-x ?k ?i ?l ?l ?- ?w ?h ?o ?l ?e ?- ?l ?i ?n ?e ?\C-m ?\C-y return ?\C-y ?\C-x ?\C-x ?\M-% ?\C-u ?\C-x ?q return ?\C-u ?\C-x ?q return ?! ?\C-a])

;; Version with no replace
(fset 'copy-line
      [?\C-a ?\M-x ?k ?i ?l ?l ?- ?w ?h ?o ?l ?e ?- ?l ?i ?n ?e ?\C-m ?\C-y return ?\C-y ?\C-x ?\C-x ?\C-a])

;; Eval a line in bash and print to new buffer
(fset 'shell-eval-line
      [?\C-a ?\C-  ?\C-e ?\M-w ?\C-a ?\M-! ?\C-y return])

;; Obsolete
;; (fset 'unix2date
;;       (lambda (&optional arg) "Convert Unixtime to a date string. Example: Thu Mar  1 00:00:00 PST 2012 -> 1330588800"
;;         (interactive "p")
;;         (kmacro-exec-ring-item (quote ([67108896 5 134217847 32 45 32 21 134217761 100 97 116 101 32 45 45 100 97 116 101 32 34 64 25 5 13 5 6 4] 0 "%d")) arg)))
;; (put 'unix2date 'kmacro t)

(fset 'date2unix
      (lambda (&optional arg) "Convert simple date string to unixtime. Example: 1330588800 -> Thu Mar  1 00:00:00 PST 2012"
        (interactive "p")
        (kmacro-exec-ring-item
         (quote ([67108896 5 134217847 32 45 32 21 134217761 100 97 116 101 32 45 100 32 34 25 5 32 43 37 115 13 5 6 4] 0 "%d")) arg)))

(fset 'date2unix
      (lambda (&optional arg) "Convert simple date string to unixtime. Example: 1330588800 -> Thu Mar  1 00:00:00 PST 2012"
        (interactive "p")
        (message (current-time-string (seconds-to-time arg)))))
(put 'date2unix 'kmacro t)



(defun unix2date (arg)
  (interactive "p")
  (insert (concat " - " (current-time-string (seconds-to-time (string-to-number (buffer-substring (region-beginning) (region-end))))))))

(defun unixtime2date (arg)
  (interactive "p")
  (message (format-time-string "%B %d, %Y %T UTC" (seconds-to-time (string-to-number (buffer-substring (region-beginning) (region-end)))))))

(defun date2unixtime (arg)
  (interactive "p")
  (message (current-time-string (encode-time 0 0 0  (string-to-number (substring (buffer-substring (region-beginning) (region-end)) 8 10)) (string-to-number (substring (buffer-substring (region-beginning) (region-end)) 5 7)) (string-to-number (substring (buffer-substring (region-beginning) (region-end)) 0 4))))))

                                        ; Older send-lin macro
                                        ;(fset 'python-shell-send-line
                                        ;   [?\C-a ?\C-  ?\C-e ?\C-c ?\C-r ?\C-g ?\C-a])

(fset 'slime-copy-to-process
      [?\C-a ?\C-  ?\C-e ?\M-w ?\C-\] ?\C-y return ?\C-\M-\] ?\C-a])

(defun eval-and-replace ()
  "Replace the preceding sexp with its value."
  (interactive)
  (backward-kill-sexp)
  (prin1 (eval (read (current-kill 0)))
         (current-buffer)))

                                        ; This macro is supposed to send the region but it seems to act a little dodgy.
(fset 'send-region-macro
      [C-up ?\C-  C-down ?\C-c ?\C-r ?\C-g])

;; Custom vc-git-annotate-command
;; original uses date=iso
;; (defun vc-git-annotate-command (file buf &optional rev)
;;   (let ((name (file-relative-name file)))
;;     (vc-git-command buf 'async nil "blame" "--date=short" "-C" "-C" rev "--" name)))
;; can't be used properly by vc-annotate, I guess it's expecting a specific format

(fset 'envelop-parentheses
      [?\( ?\C-\)])

(defun save-macro (name)
  "save a macro. Take a name as argument
     and save the last defined macro under
     this name at the end of your .emacs"
  (interactive "SName of the macro :")  ; ask for the name of the macro
  (name-last-kbd-macro name)         ; use this name for the macro
  (find-file "/media/sf_Conor/Dropbox/emacs/emacs24/elisp/emacs24.el")                   ; open ~/.emacs or other user init file
  (goto-char (point-max))               ; go to the end of the .emacs
  (newline)                             ; insert a newline
  (insert-kbd-macro name)               ; copy the macro
  (newline)                             ; insert a newline
  (switch-to-buffer nil))               ; return to the initial buffer

;; Count the words in the entire document
(defun count-words-buffer ()
  "Count all the words in the buffer"
  (interactive)
  (count-words-region (point-min) (point-max)))

(defun remove-cr-and-lf ()
  (interactive)
  (end-of-line)
  (delete-char 1)
  (just-one-space)
  (beginning-of-line))

(defun copy-line (&optional arg)
  "Do a kill-line but copy rather than kill.  This function directly calls
kill-line, so see documentation of kill-line for how to use it including prefix
argument and relevant variables. This function works by temporarily making the
buffer read-only, so I suggest setting kill-read-only-ok to t."
  (interactive "P")
  (toggle-read-only 1)
  (kill-line arg)
  (toggle-read-only 0))

(setq-default kill-read-only-ok t)

(defun zero-pad (&optional arg)
  "When the cursor is placed in front of a number, augment the number to have zero-padding prefixing the number so that the number becomes 9 digits long."
  (interactive "p")
  (kill-word arg)
  (insert (format "%009d" (string-to-number (car kill-ring-yank-pointer)))))

(defun back-window (&optional arg)
  (interactive "P")
  (other-window -1))

(defun remove-line-breaks ()
  "Remove line endings in a paragraph."
  (interactive)
  (let ((fill-column (point-max)))
    (fill-paragraph nil)))

(defun zap-to-regexp (arg regexp)
  "Same as zap-to-char except that it zaps to the given regexp
instead of a char."
  (interactive "p\nsZap to regexp: ")
  (kill-region (point)
               (progn
                 (re-search-forward regexp nil nil arg)
                 (point))))

(defun my-insert-file-name (filename &optional args)
  "Insert name of file FILENAME into buffer after point.

  Prefixed with \\[universal-argument], expand the file name to
  its fully canocalized path.  See `expand-file-name'.

  Prefixed with \\[negative-argument], use relative path to file
  name from current directory, `default-directory'.  See
  `file-relative-name'.

  The default with no prefix is to insert the file name exactly as
  it appears in the minibuffer prompt."
  ;; Based on insert-file in Emacs -- ashawley 20080926
  (interactive "*fInsert file name: \nP")
  (cond ((eq '- args)
         (insert (file-relative-name filename)))
        ((not (null args))
         (insert (expand-file-name filename)))
        (t
         (insert filename))))

;; code borrowed from http://emacs-fu.blogspot.com/2010/01/duplicating-lines-and-commenting-them.html
(defun djcb-duplicate-line (&optional commentfirst)
  "comment line at point; if COMMENTFIRST is non-nil, comment the
original" (interactive)
  (beginning-of-line)
  (push-mark)
  (end-of-line)
  (let ((str (buffer-substring (region-beginning) (region-end))))
    (when commentfirst
      (comment-region (region-beginning) (region-end)))
    (insert
     (concat (if (= 0 (forward-line 1)) "" "\n") str "\n"))
    (forward-line -1)))
(defun my-skewer-eval-line (vis)
  "Send the current line to the inferior ESS process.
Arg has same meaning as for `ess-eval-region'."
  (interactive "P")
  (save-excursion
    (end-of-line)
    (let ((end (point)))
      (beginning-of-line)
      (princ (concat "Loading line:") t)
      (skewer-input-sender (skewer-repl-process) (buffer-substring (point) end)))))

(defun my-skewer-eval-region (vis)
  (interactive "P")
  (save-excursion
    (let ((end (point)))
      (princ (concat "Loading line:") t)
      (skewer-input-sender (skewer-repl-process) (buffer-substring (region-beginning) (region-end))))))


(defun move-text-internal (arg)
  (cond
   ((and mark-active transient-mark-mode)
    (if (> (point) (mark))
        (exchange-point-and-mark))
    (let ((column (current-column))
          (text (delete-and-extract-region (point) (mark))))
      (forward-line arg)
      (move-to-column column t)
      (set-mark (point))
      (insert text)
      (exchange-point-and-mark)
      (setq deactivate-mark nil)))
   (t
    (let ((column (current-column)))
      (beginning-of-line)
      (when (or (> arg 0) (not (bobp)))
        (forward-line)
        (when (or (< arg 0) (not (eobp)))
          (transpose-lines arg))
        (forward-line -1))
      (move-to-column column t)))))

(defun move-text-down (arg)
  "Move region (transient-mark-mode active) or current line
  arg lines down."
  (interactive "*p")
  (move-text-internal arg))

(defun move-text-up (arg)
  "Move region (transient-mark-mode active) or current line
  arg lines up."
  (interactive "*p")
  (move-text-internal (- arg))
  ;; (vertical-motion -1)
  )


(defun conor-mydelete ()
  "Delete the failed portion of the search string, or the last char if successful. Stolen from http://emacs.stackexchange.com/q/10359/6866"
  (interactive)
  (with-isearch-suspended
   (setq isearch-new-string
         (substring
          isearch-string 0 (or (isearch-fail-pos) (1- (length isearch-string))))
         isearch-new-message
         (mapconcat 'isearch-text-char-description isearch-new-string ""))))

;; This is to allow highlighting in compiliation buffers
;; stolen from http://stackoverflow.com/a/3072831/77298
;; (use-package ansi-color)
;; (defun colorize-compilation-buffer ()
;;   (toggle-read-only)
;;   (ansi-color-apply-on-region (point-min) (point-max))
;;   (toggle-read-only))
;; (add-hook 'compilation-filter-hook 'colorize-compilation-buffer)


(defun my/vsplit-last-buffer (prefix)
  "Split the window vertically and display the previous buffer."
  (interactive "p")
  (split-window-vertically)
  (other-window 1 nil)
  (if (= prefix 1)
      (switch-to-next-buffer)))

(defun my/hsplit-last-buffer (prefix)
  "Split the window horizontally and display the previous buffer."
  (interactive "p")
  (split-window-horizontally)
  (other-window 1 nil)
  (if (= prefix 1) (switch-to-next-buffer)))


(defun my/smarter-move-beginning-of-line (arg)
  "Move point back to indentation of beginning of line.

Move point to the first non-whitespace character on this line.
If point is already there, move to the beginning of the line.
Effectively toggle between the first non-whitespace character and
the beginning of the line.

If ARG is not nil or 1, move forward ARG - 1 lines first.  If
point reaches the beginning or end of the buffer, stop there."
  (interactive "^p")
  (setq arg (or arg 1))

  ;; Move lines first
  (when (/= arg 1)
    (let ((line-move-visual nil))
      (forward-line (1- arg))))

  (let ((orig-point (point)))
    (back-to-indentation)
    (when (= orig-point (point))
      (move-beginning-of-line 1))))


(defun camel-to-dot ()
  "Convert camelCase to dot.separated"
  (interactive)
  (progn
    (replace-regexp "\\([A-Z]\\)" ".\\1" nil (region-beginning) (region-end))
    (downcase-region (region-beginning) (region-end))))

(defun camel-to-snake ()
  "Convert camelCase to snake_case"
  (interactive)
  (progn
    (replace-regexp "\\([a-z]+\\)\\([A-Z]\\)" "\\1_\\2" nil (region-beginning) (region-end))
    (downcase-region (region-beginning) (region-end))))

(defun snake-to-camel (prefix)
  "Convert snake_case to camelCase"
  (interactive "p")
  (save-excursion
    (let ((reg-beg (region-beginning))
          (reg-end (region-end)))
      (progn
        (replace-regexp "_" " " nil reg-beg reg-end)
        (capitalize-region reg-beg reg-end)
        (if (= prefix 4)
            (progn 
              (goto-char reg-beg)
              (insert "\"")
              (goto-char (+ 1 reg-end))
              (insert "\"")))))))

(defvar conornash/say-what-im-doing-common-commands
  '(
    backward-char
    delete-backward-char
    execute-extended-command
    forward-char
    keyboard-quit
    newline
    next-line
    previous-line
    self-insert-command
    )
  "These comands will not be spoken out loud, as they occur so frequently and repeatedly.")

(defvar conornash/say-what-im-doing-shell-command "say"
  "This is the command-line program that will be used for text-to-speech.")

(defun conornash/say-what-im-doing-command-hook ()
  "This is the function that will be added to `post-command-hook'."
  (if (not (member this-command conornash/say-what-im-doing-common-commands))
      (start-process "my_process"
                     nil conornash/say-what-im-doing-shell-command
                     (replace-regexp-in-string "-" " " (format "%s" this-command)))))

;;;###autoload
(define-minor-mode conornash/say-what-im-doing-mode
  "This is a mode to make emacs say every command you invoke out
  loud. This uses OS X's \"say\" by default, but can be
  configured to use a different command line program - see
  conornash/say-what-im-doing-shell-command."
  :lighter " say"
  :global t
  (if conornash/say-what-im-doing-mode
      (add-hook 'post-command-hook 'conornash/say-what-im-doing-command-hook)
    (remove-hook 'post-command-hook 'conornash/say-what-im-doing-command-hook)))

(provide 'conornash/say-what-im-doing-mode)



(defun org-dblock-write:rangereport (params)
  "Display day-by-day time reports."
  (let* ((ts (plist-get params :tstart))
         (te (plist-get params :tend))
         (start (time-to-seconds
                 (apply 'encode-time (org-parse-time-string ts))))
         (end (time-to-seconds
               (apply 'encode-time (org-parse-time-string te))))
         day-numbers)
    (setq params (plist-put params :tstart nil))
    (setq params (plist-put params :end nil))
    (while (<= start end)
      (save-excursion
        (setq inner-time (org-clock-sum
                          (format-time-string (car org-time-stamp-formats) (seconds-to-time start))
                          (format-time-string (car org-time-stamp-formats) (seconds-to-time end))))
        (insert "\n"
                (concat (format-time-string (car org-time-stamp-formats)
                                            (seconds-to-time start)) " | "  (int-to-string inner-time)))
        (setq start (+ 86400 start)
              inner-time 0)))))


(defun conornash/org-clock-get-table-data (file params)
  "Get the clocktable data for file FILE, with parameters PARAMS.
FILE is only for identification - this function assumes that
the correct buffer is current, and that the wanted restriction is
in place.
The return value will be a list with the file name and the total
file time (in minutes) as 1st and 2nd elements.  The third element
of this list will be a list of headline entries.  Each entry has the
following structure:

  (LEVEL HEADLINE TIMESTAMP TIME)

LEVEL:     The level of the headline, as an integer.  This will be
       the reduced leve, so 1,2,3,... even if only odd levels
       are being used.
HEADLINE:  The text of the headline.  Depending on PARAMS, this may
       already be formatted like a link.
TIMESTAMP: If PARAMS require it, this will be a time stamp found in the
       entry, any of SCHEDULED, DEADLINE, NORMAL, or first inactive,
       in this sequence.
TIME:      The sum of all time spend in this tree, in minutes.  This time
       will of cause be restricted to the time block and tags match
       specified in PARAMS."
  (let* ((maxlevel (or (plist-get params :maxlevel) 3))
         (timestamp (plist-get params :timestamp))
         (ts (plist-get params :tstart))
         (te (plist-get params :tend))
         (ws (plist-get params :wstart))
         (ms (plist-get params :mstart))
         (block (plist-get params :block))
         (link (plist-get params :link))
         (tags (plist-get params :tags))
         (properties (plist-get params :properties))
         (inherit-property-p (plist-get params :inherit-props))
         todo-only
         (matcher (if tags (cdr (org-make-tags-matcher tags))))
         cc range-text st p time level hdl props tsp tbl)

    (setq org-clock-file-total-minutes nil)
    (when block
      (setq cc (org-clock-special-range block nil t ws ms)
            ts (car cc) te (nth 1 cc) range-text (nth 2 cc)))
    (when (integerp ts) (setq ts (calendar-gregorian-from-absolute ts)))
    (when (integerp te) (setq te (calendar-gregorian-from-absolute te)))
    (when (and ts (listp ts))
      (setq ts (format "%4d-%02d-%02d" (nth 2 ts) (car ts) (nth 1 ts))))
    (when (and te (listp te))
      (setq te (format "%4d-%02d-%02d" (nth 2 te) (car te) (nth 1 te))))
    ;; Now the times are strings we can parse.
    (if ts (setq ts (org-matcher-time ts)))
    (if te (setq te (org-matcher-time te)))
    (save-excursion
      (org-clock-sum ts te
                     (unless (null matcher)
                       (lambda ()
                         (let* ((tags-list (org-get-tags-at))
                                (org-scanner-tags tags-list)
                                (org-trust-scanner-tags t))
                           (eval matcher)))))
      (goto-char (point-min))
      (setq st t)
      (while (or (and (bobp) (prog1 st (setq st nil))
                      (get-text-property (point) :org-clock-minutes)
                      (setq p (point-min)))
                 (setq p (next-single-property-change
                          (point) :org-clock-minutes)))
        (goto-char p)
        (when (setq time (get-text-property p :org-clock-minutes))
          (save-excursion
            (beginning-of-line 1)
            (when (and (looking-at "\\(\\*+\\)[ \t]+\\(.*?\\)\\([ \t]+:[[:alnum:]_@#%:]+:\\)?[ \t]*$")
                       (setq level (org-reduced-level
                                    (- (match-end 1) (match-beginning 1))))
                       (<= level maxlevel))
              (setq hdl (if (not link)
                            (match-string 2)
                          (org-make-link-string
                           (format "file:%s::%s"
                                   (buffer-file-name)
                                   (save-match-data
                                     (match-string 2)))
                           (org-make-org-heading-search-string
                            (replace-regexp-in-string
                             org-bracket-link-regexp
                             (lambda (m) (or (match-string 3 m)
                                             (match-string 1 m)))
                             (match-string 2)))))
                    tsp (when timestamp
                          (setq props (org-entry-properties (point)))
                          (or (cdr (assoc "SCHEDULED" props))
                              (cdr (assoc "DEADLINE" props))
                              (cdr (assoc "TIMESTAMP" props))
                              (cdr (assoc "TIMESTAMP_IA" props))))
                    props (when properties
                            (remove nil
                                    (mapcar
                                     (lambda (p)
                                       (when (org-entry-get (point) p inherit-property-p)
                                         (cons p (org-entry-get (point) p inherit-property-p))))
                                     properties))))
              (when (> time 0) (push (list level hdl tsp time props) tbl))))))
      (setq tbl (nreverse tbl))
      (list file org-clock-file-total-minutes tbl))))

(defun conornash/shell-command-do-it (pointed marked)
  (interactive "r")
  (shell-command (buffer-substring pointed marked)))

(defun dired-grep-marked-files ()
  "`i` case insensitive; `n` print line number;
`I` ignore binary files; `E` extended regular expressions."
  (interactive)
  (let* ((files (dired-get-marked-files))
         (search-term (read-string "regex:  "))
         (grep-command
          (concat
           grep-program
           " "
           "-inIE --color=always -C2"
           " "
           search-term
           " "
           (mapconcat 'shell-quote-argument files " "))))
    (when (and files search-term grep-command)
      (compilation-start grep-command 'grep-mode (lambda (mode) "*grep*") nil))))

(require 'server)
(defun generate-secure-password ()
  (interactive)
  (let* ((raw-auth-key (server-generate-key))
         (replaced-auth-key (s-replace-regexp "[][%/\\\"'`,.(){}]" "" raw-auth-key))
         (auth-key (s-left 16 replaced-auth-key)))
    (if (called-interactively-p 'interactive)
        (progn (insert auth-key)
               (kill-new auth-key)))
    auth-key))

Negative occur

(defun noccur ()
  (interactive)
  (let ((orig-re-search-forward (symbol-function 're-search-forward)))
    (fset 're-search-forward 'noccur-re-search-forward)
    (unwind-protect
        (call-interactively 'occur)
      (fset 're-search-forward orig-re-search-forward))))


(defun noccur-re-search-forward (regexp bound noerror &optional count)
  (unless (eq (aref regexp 0) ?^)
    (setq regexp (concat ".*" regexp)))

  (while (and (not (eobp))
              (looking-at regexp))
    (forward-line 1))

  (if (eobp)
      nil
    (set-match-data (list (line-beginning-position)
                          (line-end-position)))
    (line-end-position)))