I would like to export from Org-Mode tables to s-expressions.
| first | second | thrid |
|--------+--------+--------|
| value1 | value2 | value3 |
| value4 | value5 | value6 |
Would turn into:
((:FIRST "value1" :SECOND "value2" :THIRD "value3")
(:FIRST "value4" :SECOND "value5" :THIRD "value6"))
I plan on writing such a setup if it doesn't exist yet but figured I'd tap into the stackoverflow before I start reinventing the wheel.
This does the trick. It has minimal error checking.
The interface to use is either the programmatic interface:
(org-table-to-sexp <location-of-beginning-of-table> <location-of-end-of-table>)
In which case it'll return the sexp you requested.
If you wanted an interactive usage, you can call the following command to operate on the table in the region. So, set the mark at the beginning of the table, move to the end, and type:
M-x insert-org-table-to-sexp
That will insert the desired sexp immediately after the table in the current buffer.
Here is the code:
(defun org-table-to-sexp-parse-line ()
"Helper, returns the current line as a list of strings"
(save-excursion
(save-match-data
(let ((result nil)
(end-of-line (save-excursion (end-of-line) (point))))
(beginning-of-line)
(while (re-search-forward "\\([^|]*\\)|" end-of-line t)
(let ((match (mapconcat 'identity (split-string (match-string-no-properties 1)) " ")))
(if (< 0 (length match))
;; really want to strip spaces from front and back
(push match result))))
(reverse result)))))
(require 'cl)
(defun org-table-to-sexp (b e)
"Parse an org-mode table to sexp"
(save-excursion
(save-match-data
(goto-char b)
(let ((headers (mapcar
(lambda (str)
(make-symbol (concat ":" (upcase str))))
(org-table-to-sexp-parse-line)))
(sexp nil))
(forward-line 1) ;skip |--+--+--| line
(while (< (point) e)
(forward-line 1)
(let ((line-result nil))
(mapcar* (lambda (h e)
(push h line-result)
(push e line-result))
headers
(org-table-to-sexp-parse-line))
(if line-result
(push (reverse line-result)
sexp))))
sexp))))
(defun insert-org-table-to-sexp (b e)
"Convert the table specified by the region and insert the sexp after the table"
(interactive "r")
(goto-char (max b e))
(print (org-table-to-sexp b e) (current-buffer)))
Related
If there is a data in region:
flower
park
flower
stone
flower
stone
stone
flower
M-x some-command should give me in different buffer:
4 flower
2 stone
1 park
This data can then be sorted by frequency or item.
I suppose a common method would be to just hash the strings and then print the contents. This approach can be easily accomplished in emacs.
;; See the emacs manual for creating a hash table test
;; https://www.gnu.org/software/emacs/manual/html_node/elisp/Defining-Hash.html
(defun case-fold-string= (a b)
(eq t (compare-strings a nil nil b nil nil t)))
(defun case-fold-string-hash (a)
(sxhash (upcase a)))
(define-hash-table-test 'case-fold
'case-fold-string= 'case-fold-string-hash)
(defun uniq (beg end)
"Print counts of strings in region."
(interactive "r")
(let ((h (make-hash-table :test 'case-fold))
(lst (split-string (buffer-substring-no-properties beg end) "\n"
'omit-nulls " "))
(output-func (if current-prefix-arg 'insert 'princ)))
(dolist (str lst)
(puthash str (1+ (gethash str h 0)) h))
(maphash (lambda (key val)
(apply output-func (list (format "%d: %s\n" val key))))
h)))
Output when selecting that text
4: flower
1: park
3: stone
I suppose there are lots of approaches you could take to this. Here's a fairly simple approach:
(defun uniq-c (beginning end)
"Like M-| uniq -c"
(interactive "r")
(let ((source (current-buffer))
(dest (generate-new-buffer "*uniq-c*"))
(case-fold-search nil))
(set-buffer dest)
(insert-buffer-substring source beginning end)
(goto-char (point-min))
(while (let* ((line (buffer-substring (line-beginning-position)
(line-end-position)))
(pattern (concat "^" (regexp-quote line) "$"))
(count (count-matches pattern (point) (point-max))))
(insert (format "%d " count))
(forward-line 1)
(flush-lines pattern)
(not (eobp))))
(pop-to-buffer dest)))
It is similar to uniq -c in bash.
Then why not use uniq -c?
With the region highlighted, M-| "sort | uniq -c", will run that command on the current region. The results will show in the minibuffer and will be listed in *Messages* buffer. Adding a prefix arg will insert the results into the current buffer.
In elisp, how can I get a destructuring bind for regex matches?
For example,
;; what is the equivalent of this with destructuring?
(with-temp-buffer
(save-excursion (insert "a b"))
(re-search-forward "\\(a\\) \\(b\\)")
(cons (match-string 1)
(match-string 2)))
;; trying to do something like the following
(with-temp-buffer
(save-excursion (insert "a b"))
(cl-destructuring-bind (a b) (re-search-forward "\\(a\\) \\(b\\)")
(cons a b)))
I was thinking I would have to write a macro to expand matches if there isn't another way.
Here is one way: you first extend pcase to accept a new re-match pattern, with a definition such as:
(pcase-defmacro re-match (re)
"Matches a string if that string matches RE.
RE should be a regular expression (a string).
It can use the special syntax \\(?VAR: to bind a sub-match
to variable VAR. All other subgroups will be treated as shy.
Multiple uses of this macro in a single `pcase' are not optimized
together, so don't expect lex-like performance. But in order for
such optimization to be possible in some distant future, back-references
are not supported."
(let ((start 0)
(last 0)
(new-re '())
(vars '())
(gn 0))
(while (string-match "\\\\(\\(?:\\?\\([-[:alnum:]]*\\):\\)?" re start)
(setq start (match-end 0))
(let ((beg (match-beginning 0))
(name (match-string 1 re)))
;; Skip false positives, either backslash-escaped or within [...].
(when (subregexp-context-p re start last)
(cond
((null name)
(push (concat (substring re last beg) "\\(?:") new-re))
((string-match "\\`[0-9]" name)
(error "Variable can't start with a digit: %S" name))
(t
(let* ((var (intern name))
(id (cdr (assq var vars))))
(unless id
(setq gn (1+ gn))
(setq id gn)
(push (cons var gn) vars))
(push (concat (substring re last beg) (format "\\(?%d:" id))
new-re))))
(setq last start))))
(push (substring re last) new-re)
(setq new-re (mapconcat #'identity (nreverse new-re) ""))
`(and (pred stringp)
(app (lambda (s)
(save-match-data
(when (string-match ,new-re s)
(vector ,#(mapcar (lambda (x) `(match-string ,(cdr x) s))
vars)))))
(,'\` [,#(mapcar (lambda (x) (list '\, (car x))) vars)])))))
and once that is done, you can use it as follows:
(pcase X
((re-match "\\(?var:[[:alpha:]]*\\)=\\(?val:.*\\)")
(cons var val)))
or
(pcase-let
(((re-match "\\(?var:[[:alpha:]]*\\)=\\(?val:.*\\)") X))
(cons var val))
This has not been heavily tested, and as mentioned in the docstring it doesn't work as efficiently as it (c|sh)ould when matching a string against various regexps at the same time. Also you only get the matched substrings, not their position. And finally, it applies the regexp search to a string, whereas in manny/most cases regexps searches are used in a buffer. But you may still find it useful.
If I have two buffers open (side-by-side) and I move from one window to another, can I replace previously selected word in the first (now inactive) window with the one that is under cursor in active window?
_ is cursor
_______________
| foo | _bar |
| | |
| | |
| | |
|_______|_______|
is there an internal command that can quickly let me replace foo with bar?
No internal commands, but this is Emacs:
(defun replace-word-other-window ()
(interactive)
(let ((sym (thing-at-point 'symbol))
bnd)
(other-window 1)
(if (setq bnd (bounds-of-thing-at-point 'symbol))
(progn
(delete-region (car bnd) (cdr bnd))
(insert sym))
(message "no symbol at point in other window"))
(other-window -1)))
update: advanced version
(defun region-or-symbol-bounds ()
(if (region-active-p)
(cons (region-beginning)
(region-end))
(bounds-of-thing-at-point 'symbol)))
(defun replace-word-other-window ()
(interactive)
(let* ((bnd-1 (region-or-symbol-bounds))
(str-1 (buffer-substring-no-properties
(car bnd-1)
(cdr bnd-1)))
(bnd-2 (progn
(other-window 1)
(region-or-symbol-bounds))))
(if bnd-2
(progn
(delete-region (car bnd-2) (cdr bnd-2))
(insert str-1))
(message "no region or symbol at point in other window"))
(other-window -1)))
I am defining a major mode that works on paragraphs of the following nature:
: Identifier
1. some text
2. ...
3. some more text
: New Identifier
: Another Identifier
some text
I want to write a defun called get-paragraphs that will return a list that looks like:
( ("Identifier", ("1. some text", "2. ...", "3. some more text")),
("New Identifier", ()),
("Another Identifier", ("some text"))
)
How do I go about cutting up the text like this in Emacs Lisp:
Is there a function to iterate through them (and subsequently chop them up to my liking)? Should I use regular expressions? Is there an easier way?
You should iterate over the buffer and collect your text (untested):
(defun get-paragraphs ()
(save-excursion
(goto-char (point-min))
(let ((ret '()))
(while (search-forward-regexp "^: " nil t)
(let ((header (buffer-substring-no-properties (point) (line-end-position)))
(body '()))
(forward-line)
(while (not (looking-at "^$"))
(push (buffer-substring-no-properties (point) (line-end-position)) body)
(forward-line))
(push (cons header (list (reverse body))) ret)))
(nreverse ret))))
Here, take this Lisp code:
(defun chopchop ()
(mapcar
(lambda (x)
(destructuring-bind (head &rest tail)
(split-string x "\n" t)
(list head tail)))
(split-string (buffer-substring-no-properties
(point-min)
(point-max)) "\n?: *" t)))
I need to spell check a large document containing many camelcased words. I want ispell or aspell to check if the individual words are spelled correctly.
So, in case of this word:
ScientificProgrezGoesBoink
I would love to have it suggest this instead:
ScientificProgressGoesBoink
Is there any way to do this? (And I mean, while running it on an Emacs buffer.) Note that I don't necessarily want it to suggest the complete alternative. However, if it understands that Progrez is not recognized, I would love to be able to replace that part at least, or add that word to my private dictionary, rather than including every camel-cased word into the dictionary.
I took #phils suggestions and dug around a little deeper. It turns out that if you get camelCase-mode and reconfigure some of ispell like this:
(defun ispell-get-word (following)
(when following
(camelCase-forward-word 1))
(let* ((start (progn (camelCase-backward-word 1)
(point)))
(end (progn (camelCase-forward-word 1)
(point))))
(list (buffer-substring-no-properties start end)
start end)))
then, in that case, individual camel cased words suchAsThisOne will actually be spell-checked correctly. (Unless you're at the beginning of a document -- I just found out.)
So this clearly isn't the fullblown solution, but at least it's something.
There is "--run-together" option in aspell. Hunspell can't check camelcased word.
If you read the code of aspell, you will find its algorithm actually does not split camelcase word into a list of sub-words. Maybe this algorithm is faster, but it will wrongly report word containing two character sub-word as typo. Don't waste time to tweak other aspell options. I tried and they didn't work.
So we got two problems:
aspell reports SOME camelcased words as typos
hunspell reports ALL camelcased words as typos
Solution to solve BOTH problems is to write our own predicate in Emacs Lisp.
Here is a sample predicate written for javascript:
(defun split-camel-case (word)
"Split camel case WORD into a list of strings.
Ported from 'https://github.com/fatih/camelcase/blob/master/camelcase.go'."
(let* ((case-fold-search nil)
(len (length word))
;; ten sub-words is enough
(runes [nil nil nil nil nil nil nil nil nil nil])
(runes-length 0)
(i 0)
ch
(last-class 0)
(class 0)
rlt)
;; split into fields based on class of character
(while (< i len)
(setq ch (elt word i))
(cond
;; lower case
((and (>= ch ?a) (<= ch ?z))
(setq class 1))
;; upper case
((and (>= ch ?A) (<= ch ?Z))
(setq class 2))
((and (>= ch ?0) (<= ch ?9))
(setq class 3))
(t
(setq class 4)))
(cond
((= class last-class)
(aset runes
(1- runes-length)
(concat (aref runes (1- runes-length)) (char-to-string ch))))
(t
(aset runes runes-length (char-to-string ch))
(setq runes-length (1+ runes-length))))
(setq last-class class)
;; end of while
(setq i (1+ i)))
;; handle upper case -> lower case sequences, e.g.
;; "PDFL", "oader" -> "PDF", "Loader"
(setq i 0)
(while (< i (1- runes-length))
(let* ((ch-first (aref (aref runes i) 0))
(ch-second (aref (aref runes (1+ i)) 0)))
(when (and (and (>= ch-first ?A) (<= ch-first ?Z))
(and (>= ch-second ?a) (<= ch-second ?z)))
(aset runes (1+ i) (concat (substring (aref runes i) -1) (aref runes (1+ i))))
(aset runes i (substring (aref runes i) 0 -1))))
(setq i (1+ i)))
;; construct final result
(setq i 0)
(while (< i runes-length)
(when (> (length (aref runes i)) 0)
(setq rlt (add-to-list 'rlt (aref runes i) t)))
(setq i (1+ i)))
rlt))
(defun flyspell-detect-ispell-args (&optional run-together)
"If RUN-TOGETHER is true, spell check the CamelCase words.
Please note RUN-TOGETHER will make aspell less capable. So it should only be used in prog-mode-hook."
;; force the English dictionary, support Camel Case spelling check (tested with aspell 0.6)
(let* ((args (list "--sug-mode=ultra" "--lang=en_US"))args)
(if run-together
(setq args (append args '("--run-together" "--run-together-limit=16"))))
args))
;; {{ for aspell only, hunspell does not need setup `ispell-extra-args'
(setq ispell-program-name "aspell")
(setq-default ispell-extra-args (flyspell-detect-ispell-args t))
;; }}
;; ;; {{ hunspell setup, please note we use dictionary "en_US" here
;; (setq ispell-program-name "hunspell")
;; (setq ispell-local-dictionary "en_US")
;; (setq ispell-local-dictionary-alist
;; '(("en_US" "[[:alpha:]]" "[^[:alpha:]]" "[']" nil ("-d" "en_US") nil utf-8)))
;; ;; }}
(defvar extra-flyspell-predicate '(lambda (word) t)
"A callback to check WORD. Return t if WORD is typo.")
(defun my-flyspell-predicate (word)
"Use aspell to check WORD. If it's typo return t."
(let* ((cmd (cond
;; aspell: `echo "helle world" | aspell pipe`
((string-match-p "aspell$" ispell-program-name)
(format "echo \"%s\" | %s pipe"
word
ispell-program-name))
;; hunspell: `echo "helle world" | hunspell -a -d en_US`
(t
(format "echo \"%s\" | %s -a -d en_US"
word
ispell-program-name))))
(cmd-output (shell-command-to-string cmd))
rlt)
;; (message "word=%s cmd=%s" word cmd)
;; (message "cmd-output=%s" cmd-output)
(cond
((string-match-p "^&" cmd-output)
;; it's a typo because at least one sub-word is typo
(setq rlt t))
(t
;; not a typo
(setq rlt nil)))
rlt))
(defun js-flyspell-verify ()
(let* ((case-fold-search nil)
(font-matched (memq (get-text-property (- (point) 1) 'face)
'(js2-function-call
js2-function-param
js2-object-property
js2-object-property-access
font-lock-variable-name-face
font-lock-string-face
font-lock-function-name-face
font-lock-builtin-face
rjsx-text
rjsx-tag
rjsx-attr)))
subwords
word
(rlt t))
(cond
((not font-matched)
(setq rlt nil))
;; ignore two character word
((< (length (setq word (thing-at-point 'word))) 2)
(setq rlt nil))
;; handle camel case word
((and (setq subwords (split-camel-case word)) (> (length subwords) 1))
(let* ((s (mapconcat (lambda (w)
(cond
;; sub-word wholse length is less than three
((< (length w) 3)
"")
;; special characters
((not (string-match-p "^[a-zA-Z]*$" w))
"")
(t
w))) subwords " ")))
(setq rlt (my-flyspell-predicate s))))
(t
(setq rlt (funcall extra-flyspell-predicate word))))
rlt))
(put 'js2-mode 'flyspell-mode-predicate 'js-flyspell-verify)
Or just use my new pacakge https://github.com/redguardtoo/wucuo
You should parse the camel cased words and split them, then check the individual spelling for each one and assemble a suggestion taking into account the single suggestion for each misspelled token. Considering that each misspelled token can have multiple suggestions this sounds a bit inefficient to me.