(message ";;; functions-extra --> Start")
(message ";;; functions-extra --> execute-buffer")
(defun execute-buffer ()
"Execute or compile current file."
(interactive)
(let* ((file-name (shell-quote-argument (buffer-file-name)))
(file-type (shell-command (concat "file " file-name)))
(type-map '(("Lisp" . "clisp")
("bash" . "bash")
("perl" . "perl")
("python" . "python")
("java" . "javac")
("php" . "php")
(" c " . "gcc")))
cmd)
(kill-buffer "*Shell Command Output*")
(delete-other-windows)
(do ((type type-map (cdr type)))
((or (not type) cmd))
(when (search (car type) file-type)
(setq cmd (cdr type))))
(shell-command (concat cmd " " file-name))
))
(message ";;; functions-extra --> file-in-exec-path")
(defun file-in-exec-path (name)
"Return non-nil if NAME is a file found in `exec-path'."
(catch 'found
(dolist (dir exec-path)
(when (file-exists-p (concat (file-name-as-directory dir) name))
(throw 'found t)))
nil))
(defun unicode-shell ()
"Execute the shell buffer in UTF-8 encoding.
\nNote that you need to set the environment variable LANG and
others appropriately."
(interactive)
(let ((coding-system-for-read 'utf-8)
(coding-system-for-write 'utf-8)
(coding-system-require-warning t))
(call-interactively 'shell)))
(message ";;; functions-extra --> grep-elisp")
(defun grep-elisp (&optional query)
"Grep custom elisp directories for QUERY.
Run `grep' COMMAND, where COMMAND is:
`grep-default-command' QUERY FILES
FILES is a list of files generated from the following
files/directories:
~/.emacs
~/.emacs.d
~/.elisp/NAME
NAME is `user-login-name'.
A file matching pattern of `*.el$' is used."
(interactive)
(unless query
(setq query (read-from-minibuffer "Grep custom elisp files: ")))
(let ((paths (nreverse `("~/.emacs" "~/.emacs.d" ,(concat "~/.elisp/" user-login-name))))
path
files)
(while paths
(setq path (expand-file-name (car paths)))
(setq paths (cdr paths))
(if (file-directory-p path)
(dolist (file (nreverse (directory-files path t)))
(unless (string-match "^\\." (file-name-nondirectory file))
(if (file-directory-p file)
(push file paths)
(when (string-match "\\.el$" file)
(push file files)))))
(push path files)))
(let ((cmd (or grep-command "grep -n -H -i -e ")))
(setq cmd (concat cmd " \"" query "\""))
(dolist (file files)
(setq cmd (concat cmd " \"" file "\"")))
(grep cmd))))
(message ";;; functions-extra --> grep-custom-generate")
(defmacro grep-custom-generate (name prompt dirs match)
"Create custom function.
\nNAME is the function name.
PROMPT is displayed if no query is given.
DIRS is a list of the directories to search.
MATCH is the file pattern to match.
\nNote: This macro is not side-effect safe; DIRS and MATCH are
both used more than once and might not work correctly if set to
functions with side-effects."
`(defun ,name (&optional query)
,(concat "Grep custom directories for QUERY.\n\n"
"Run `grep' COMMAND, where COMMAND is:\n\n"
"`grep-default-command' QUERY FILES\n\n"
"FILES is a list of files generated from the following\n"
"files/directories:\n\n"
(concat " " (reduce #'(lambda (x y) (concat x "\n " y)) dirs) "\n\n")
"A file matching pattern of `" match "' is used.")
(interactive)
(unless query
(setq query (read-from-minibuffer ,prompt)))
(let ((paths (nreverse ',dirs))
path
files)
(while paths
(setq path (expand-file-name (car paths)))
(setq paths (cdr paths))
(if (file-directory-p path)
(dolist (file (nreverse (directory-files path t)))
(unless (string-match "^\\." (file-name-nondirectory file))
(if (file-directory-p file)
(push file paths)
(when (string-match ,match file)
(push file files)))))
(push path files)))
(let ((cmd (or grep-command "grep -n -H -i -e ")))
(setq cmd (concat cmd " \"" query "\""))
(dolist (file files)
(setq cmd (concat cmd " \"" file "\"")))
(grep cmd)))))
(message ";;; functions-extra --> grep-clisp")
(grep-custom-generate grep-clisp "Grep CLISP files: " ("~/clisp") "\\.lisp$")
(message ";;; functions-extra --> grep-profile")
(grep-custom-generate grep-profile "Grep shell profile files: "
("~/.bashrc"
"~/.alias" "~/.alias-local" "~/.alias-work"
"~/.funct" "~/.funct-local" "~/.funct-work"
"~/.profile" "~/.profile-local" "~/.profile-work"
) ".*")
(message ";;; functions-extra --> Code Reformatting Functions")
(message ";;; functions --> c-fix-code")
(defun c-fix-code ()
"Clean up c/c++ code."
(interactive "*")
(save-excursion
(remove-tabs)
(remove-trailing-blanks)
(goto-char (point-min))
(while (re-search-forward "([ \t]*" nil t)
(replace-match "(" nil nil))
(goto-char (point-min))
(while (re-search-forward "[ \t]*)" nil t)
(replace-match ")" nil nil))
(goto-char (point-min))
(while (re-search-forward "\\,\\([^ ]\\)" nil t)
(replace-match ", \\1" nil nil))
(goto-char (point-min))
(while (re-search-forward "\n\n\n+" nil t)
(replace-match "\n\n" nil nil))
(goto-char (point-min))
(while (re-search-forward "\n\n[ \t]*{" nil t)
(replace-match "\n{" nil nil)
(indent-according-to-mode))
(indent-region (point-min) (point-max) nil)
))
(message ";;; functions --> ruby-fix-code")
(defun ruby-fix-code ()
"Clean up ruby code."
(interactive "*")
(save-excursion
(remove-tabs)
(remove-trailing-blanks)
(goto-char (point-min))
(while (re-search-forward "([ \t]*\\(.*?\\)[ \t]*)" nil t)
(replace-match "(\\1)" nil nil))
(goto-char (point-min))
(while (re-search-forward "#{[ \t]*\\(.*?\\)[ \t]*}" nil t)
(replace-match "#{\\1}" nil nil))
(goto-char (point-min))
(while (re-search-forward "\\[[ \t]*\\(.*?\\)[ \t]*\\]" nil t)
(replace-match "[\\1]" nil nil))
(goto-char (point-min))
(while (re-search-forward "|[ \t]*\\(.*?\\)[ \t]*|" nil t)
(replace-match "|\\1|" nil nil))
(goto-char (point-min))
(while (re-search-forward "\\,\\([^ ]\\)" nil t)
(replace-match ", \\1" nil nil))
(goto-char (point-min))
(while (re-search-forward "\n\n\n+" nil t)
(replace-match "\n\n" nil nil))
(indent-region (point-min) (point-max) nil)
))
(message ";;; functions --> java-fix-code")
(defun java-fix-code ()
"Clean up Java code."
(interactive "*")
(save-excursion
(remove-tabs)
(remove-trailing-blanks)
(goto-char (point-min))
(while (re-search-forward "([ \t]*" nil t)
(replace-match "(" nil nil))
(goto-char (point-min))
(while (re-search-forward "[ \t]*)" nil t)
(replace-match ")" nil nil))
(goto-char (point-min))
(while (re-search-forward "\\,\\([^ ]\\)" nil t)
(replace-match ", \\1" nil nil))
(dolist (name '("catch" "else" "for" "if" "return"))
(goto-char (point-min))
(while (re-search-forward (concat name "(") nil t)
(replace-match (concat name " (") nil nil)))
(dolist (name '("catch" "else"))
(goto-char (point-min))
(while (re-search-forward (concat "} " name) nil t)
(replace-match (concat "}\n" name) nil nil)
(indent-according-to-mode)))
(goto-char (point-min))
(while (re-search-forward "\n\n\n+" nil t)
(replace-match "\n\n" nil nil))
(goto-char (point-min))
(while (re-search-forward "\n\n[ \t]*{" nil t)
(replace-match "\n{" nil nil)
(indent-according-to-mode))
(indent-region (point-min) (point-max) nil)
))
(message ";;; functions --> xml-format")
(defun xml-format ()
"Format XML buffer.
\nConvert poorly formatted XML into something better."
(interactive "*")
(xml-mode)
(let ((xml-eol "[ \t]*\n[ \t]*")
(xml-tag-end-regexp ">")
(xml-close-tag-regexp "</")
(xml-block-regexp "<[^>]*>[^<]*</[^>]*>"))
(save-excursion
(save-match-data
(goto-char (point-min))
(while (re-search-forward xml-eol nil t)
(replace-match "" nil nil))
(goto-char (point-min))
(while (re-search-forward xml-tag-end-regexp nil t)
(insert "\n")
(when (and
(looking-at xml-block-regexp)
(not (looking-at xml-close-tag-regexp)))
(re-search-forward xml-block-regexp nil t)
(forward-char -1)))
(indent-region (point-min) (point-max))
))))
(message ";;; functions-extra --> Complex Functions")
(message ";;; functions --> fahrenheit/celsius")
(defun fahrenheit-to-celsius (deg)
"Convert fahrenheit degrees to celsius."
(/ (* (- deg 32) 5) 9))
(defun fahrenheit-to-celsius-query (&optional deg)
"Prompt user for fahrenheit degrees to convert to celsius."
(interactive)
(unless deg
(setq deg (string-to-number
(read-from-minibuffer "Fahrenheit degrees: "))))
(setq cel (fahrenheit-to-celsius deg))
(message "Celsius degrees: %s" cel))
(defun celsius-to-fahrenheit (deg)
"Convert celsius degrees to fahrenheit."
(+ (* (/ deg 5) 9) 32))
(defun celsius-to-fahrenheit-query (&optional deg)
"Prompt user for celsius degrees to convert to fahrenheit."
(interactive)
(unless deg
(setq deg (string-to-number
(read-from-minibuffer "Celsius degrees: "))))
(setq cel (celsius-to-fahrenheit deg))
(message "Fahrenheit degrees: %s" cel))
(message ";;; functions --> Web Query Functions")
(defcustom web-query-list
'(("all" . (:google "http://"))
("wikipedia" . (:custom "http://en.wikipedia.org/wiki/Special:Search?search="))
("java" . (:google "http://java.sun.com/javase/6/docs/api/"))
("emacswiki" . (:google "http://www.emacswiki.org/"))
("freshmeat" . (:custom "http://freshmeat.net/search/?section=projects&q="))
("lisp" . (:custom "http://lispdoc.com/?search=Basic+search&q="))
("nullman" . (:google "http://nullman.org/"))
)
"*Association list of names to query type and URL to use with `web-query'.
The following format is used:
((NAME . (TYPE URL))
(...))
NAME is a descriptive name.
TYPE is one of:
:google
:custom
URL is dependent on TYPE as follows:
If :google then URL is used for 'site:'.
If :custom then URL is used as prefix to query string."
:type 'list
:group 'web-query)
(defcustom web-query-lucky
t
"If non-nil, perform Google lucky query instead of normal query."
:type 'boolean
:group 'web-query)
(defvar web-query-name-history
(mapcar 'car web-query-list)
"History of `web-query' name arguments.
\nInitialized with `web-query-list'.")
(defvar web-query-query-history
nil
"History of `web-query' query arguments.
\nOne association list per query name.")
(defun web-query-custom (url query)
"Browse result of a custom QUERY appended to URL.
\nUsed internally by `web-query'."
(funcall browse-url-browser-function
(concat url (w3m-url-encode-string query))))
(defun web-query-google (url query)
"Browse result of a Google QUERY limited to URL site.
\nUsed internally by `web-query'."
(funcall browse-url-browser-function
(concat "http://www.google.com/search?q="
(w3m-url-encode-string (concat query " site:" url))
(if web-query-lucky
"&btnI=Search"
"&btnG=Search"))))
(defun web-query (name &optional query)
"Lookup NAME in `web-query-list', then submit associated URL and QUERY to `web-query-google'."
(interactive
(let* ((name (read-from-minibuffer "Name: "
(car web-query-name-history)
nil nil
'web-query-name-history))
(hist (progn
(unless (assoc name web-query-query-history)
(push (list name nil) web-query-query-history))
(cadr (assoc name web-query-query-history))))
(query (read-from-minibuffer "Query: "
nil nil nil
'hist)))
(list name query)))
(let ((hist (cadr (assoc name web-query-query-history))))
(unless query
(read-from-minibuffer "Query: " nil nil nil 'hist))
(when (member query hist)
(setq hist (remove query hist)))
(push query hist)
(setcdr (assoc name web-query-query-history) (list hist))
(multiple-value-bind (type url) (cdr (assoc name web-query-list))
(case type
(:custom (web-query-custom url query))
(:google (web-query-google url query))))))
(message ";;; functions --> Code Formatting Functions")
(message ";;; functions --> find-code-block")
(defun find-code-block (&optional regexp indent)
"Find the begin and end of code block containing point.
When run interactively, then begin and end points of the block
are printed in the mini-buffer. Otherwise, a list containing
them is returned.
A code block is defined as contiguous lines of text having the
same indentation. So a code block ends when either the
indentation changes or a blank line is reached.
The begin point will be at the start of a line and the end point
will be at the end of a line, unless point is not in a code block
in which case nil is returned for both.
The optional parameter REGEXP is an additional regular expression
to match on. If non-nil, every line in the code block must also
match REGEXP.
If optional parameter INDENT is non-nil then each line will be
indented via `indent-according-to-mode'."
(interactive "*")
(let (beg
end
(ind 0)
(blank-line-regexp "^[\t ]*$"))
(save-excursion
(setq ind (current-indentation))
(goto-char (point-at-bol))
(unless (or
(looking-at blank-line-regexp)
(if regexp
(not (looking-at regexp))
nil))
(while (and
(not (bobp))
(not (looking-at blank-line-regexp))
(= ind (current-indentation))
(if regexp
(looking-at regexp)
t))
(forward-line -1)
(goto-char (point-at-bol))
)
(unless (and
(not (looking-at blank-line-regexp))
(= ind (current-indentation))
(if regexp
(looking-at regexp)
t))
(forward-line 1))
(goto-char (point-at-bol))
(setq beg (point))
(when indent
(indent-according-to-mode))
(setq ind (current-indentation))
(while (and
(not (eobp))
(not (looking-at blank-line-regexp))
(= ind (current-indentation))
(if regexp
(looking-at regexp)
t))
(forward-line 1)
(when indent
(indent-according-to-mode))
(goto-char (point-at-bol))
)
(unless (and
(not (looking-at blank-line-regexp))
(= ind (current-indentation))
(if regexp
(looking-at regexp)
t))
(forward-line -1))
(end-of-line)
(setq end (point))
))
(if (interactive-p)
(message "%s %s" beg end)
(list beg end))
))
(message ";;; functions --> lineup-assignment-commands")
(defun lineup-assignment-commands (&optional indent)
"Line up a block of variable assignment commands.
Match any contiguous block of code (presumably assignment
commands) and line up the equal signs.
If optional parameter INDENT is non-nil then each line will be
indented via `indent-according-to-mode'.
Example:
// assignments
var1 = value1; // var1
variable2 = value2; // var2
Becomes:
// assignments
var1 = value1; // var1
variable2 = value2; // var2"
(interactive "*")
(let (beg
end
(pos 0)
(equal-regexp "[\t ]+=[\t ]+"))
(save-excursion
(setq range (find-code-block nil indent))
(setq beg (car range))
(setq end (cadr range))
(when (> end beg)
(save-restriction
(narrow-to-region beg end)
(save-match-data
(goto-char (point-min))
(while (< (point) (point-max))
(when (and
(re-search-forward equal-regexp (point-at-eol) t)
(not (equal (get-char-property (point) 'face)
'font-lock-comment-face)))
(goto-char (point-at-bol))
(re-search-forward equal-regexp (point-at-eol))
(replace-match " = ")
(backward-char 2)
(when (> (- (point) (point-at-bol)) pos)
(setq pos (- (point) (point-at-bol)))))
(goto-char (point-at-bol))
(forward-line 1))
(goto-char (point-min))
(while (< (point) (point-max))
(when (and
(re-search-forward equal-regexp (point-at-eol) t)
(not (equal (get-char-property (point) 'face)
'font-lock-comment-face)))
(backward-char 2)
(while (< (- (point) (point-at-bol)) pos)
(insert " ")))
(goto-char (point-at-bol))
(forward-line 1))
(goto-char (point-min))
(while (< (point) (point-max))
(goto-char (point-at-bol))
(forward-char (current-indentation))
(when (and
(not (equal (get-char-property (point-at-eol) 'face)
'font-lock-comment-face))
(equal (get-char-property (point-at-eol) 'face)
'font-lock-comment-face))
(comment-indent))
(forward-line 1))
))))))
(message ";;; functions --> lineup-declaration-commands")
(defun lineup-declaration-commands (&optional indent)
"Line up a block of variable declaration commands.
If optional parameter INDENT is non-nil then each line will be
indented via `indent-according-to-mode'.
Example:
// variables
public Integer i; // int example
public String s; // string example
private Integer i2; // int 2
private String s2; // string 2
protected Date dte; // date example
Becomes:
// variables
public Integer i; // int example
public String s; // string example
private Integer i2; // int 2
private String s2; // string 2
protected Date dte; // date example"
(interactive "*")
(let (beg end face prev-face (change -1) (prev-change -2) (whitespace-regexp "[\t ]+")) (save-excursion
(setq range (find-code-block nil indent))
(setq beg (car range))
(setq end (cadr range))
(when (> end beg)
(save-restriction
(narrow-to-region beg end)
(save-match-data
(goto-char (point-min))
(while (< (point) (point-max))
(forward-char (current-indentation))
(re-search-forward whitespace-regexp (point-at-eol) t)
(replace-match " ")
(goto-char (point-at-bol))
(forward-line 1))
(while (> change prev-change)
(setq prev-change change)
(when (< prev-change 0)
(setq prev-change (current-indentation)))
(setq face nil)
(setq prev-face nil)
(goto-char (point-min))
(while (< (point) (point-max))
(goto-char (point-at-bol))
(forward-char (current-indentation))
(unless (equal (get-char-property (point) 'face)
'font-lock-comment-face)
(goto-char (point-at-bol))
(forward-char prev-change)
(unless prev-face
(while (and (< (point) (point-at-eol))
(looking-at whitespace-regexp))
(forward-char))
(setq prev-face (get-char-property (point) 'face)))
(while (and (< (point) (point-at-eol))
(not (looking-at whitespace-regexp)))
(forward-char))
(while (and (< (point) (point-at-eol))
(or
(looking-at whitespace-regexp)
(equal prev-face (get-char-property (point) 'face))))
(forward-char))
(when (and (< (point) (point-at-eol))
(< change (- (point) (point-at-bol)))
(if face
(equal face (get-char-property (point) 'face))
t))
(unless face
(setq face (get-char-property (point) 'face)))
(setq change (- (point) (point-at-bol)))))
(forward-line 1))
(when (> change prev-change)
(goto-char (point-min))
(while (< (point) (point-max))
(goto-char (point-at-bol))
(forward-char (current-indentation))
(unless (equal (get-char-property (point) 'face)
'font-lock-comment-face)
(goto-char (point-at-bol))
(forward-char prev-change)
(while (and (< (point) (point-at-eol))
(not (looking-at whitespace-regexp)))
(forward-char))
(while (and (< (point) (point-at-eol))
(or
(looking-at whitespace-regexp)
(not (equal face (get-char-property (point) 'face)))))
(forward-char))
(while (< (- (point) (point-at-bol)) change)
(insert " ")))
(forward-line 1))))
(goto-char (point-min))
(while (< (point) (point-max))
(goto-char (point-at-bol))
(forward-char (current-indentation))
(when (and
(not (equal (get-char-property (point-at-eol) 'face)
'font-lock-comment-face))
(equal (get-char-property (point-at-eol) 'face)
'font-lock-comment-face))
(comment-indent))
(forward-line 1))
))))))
(message ";;; functions-extra --> Esoteric Functions")
(message ";;; functions --> ldif-update-xml")
(defun ldif-update-xml ()
"Update an LDIF node with the base64 encoded value of an XML block.
\nMust be run from the attribute being updated, which must be in
the form of `attribute::'."
(interactive "*")
(let (beg
end
attr
block
(blank-line-regexp "^[\t ]*$"))
(save-excursion
(save-match-data
(goto-char (point-at-bol))
(when (search-forward "::" (point-at-eol))
(setq attr (point))
(when (search-forward "<?xml")
(setq beg (point-at-bol))
(while (and
(not (eobp))
(not (looking-at blank-line-regexp)))
(forward-line 1))
(forward-line -1)
(end-of-line)
(setq end (point))
(setq block (buffer-substring beg end))
(with-temp-buffer
(insert block)
(goto-char (point-min))
(search-forward "<?xml")
(goto-char (point-at-bol))
(when (char-equal (char-after (point)) ?#)
(while (char-equal (char-after (point)) ?#)
(delete-char 1)
(when (char-equal (char-after (point)) ? )
(delete-char 1))
(forward-line 1)
(goto-char (point-at-bol))
))
(goto-char (point-min))
(while (re-search-forward "^#" (point-max) t)
(delete-region (point-at-bol) (point-at-eol))
(unless (eobp)
(delete-char 1)))
(base64-encode-region (point-min) (point-max))
(goto-char (point-min))
(while (not (eobp))
(goto-char (point-at-bol))
(insert " ")
(forward-line 1))
(setq block (buffer-substring (point-min) (point-max)))
)
(goto-char attr)
(delete-region (point) (point-at-eol))
(forward-line 1)
(goto-char (point-at-bol))
(while (char-equal (char-after (point)) ? )
(delete-region (point-at-bol) (point-at-eol))
(delete-char 1))
(goto-char attr)
(insert block)
))))))
(message ";;; functions-extra --> Games")
(message ";;; functions --> towers")
(defun towers (n)
"Solve the clasical Towers of Hanoi problem for N levels."
(interactive)
(let ((buffer "*Towers*"))
(get-buffer-create buffer)
(set-buffer buffer)
(setq buffer-read-only nil)
(erase-buffer)
(insert (format "Towers of Hanio puzzle with %d disks" n))
(newline)
(newline)
(towers-move n 1 3 2)
(setq buffer-read-only t)
(switch-to-buffer buffer)
(goto-char (point-min)))
(values))
(message ";;; functions --> towers-move")
(defun towers-move (n from to using)
"Make one Towers of Hanoi move.
\nN is the number of disks to move.
FROM is the source peg.
TO is the target peg.
USING is the remaining peg."
(when (> n 0)
(towers-move (1- n) from using to)
(insert (format "move %d --> %d" from to))
(newline)
(towers-move (1- n) using to from)))
(message ";;; functions-extra --> End")