Difference between revisions of "Emacs"
(move point to after word in <r> elt) |
m (sort&goto-pardef) |
||
Line 4: | Line 4: | ||
I often define keyboard macros as I edit, some of these I record as |
I often define keyboard macros as I edit, some of these I record as |
||
functions which you can put in your .emacs, since they come in handy |
functions which you can put in your .emacs, since they come in handy |
||
time and again |
time and again. I use |
||
[[Format dictionaries|Apertium-dixtools]]-formatted dix, some of the functions below won't work with the regular format (at least <code>sort-pardef</code>). The code below adds keyboard shortcuts <code>C-c L</code> and <code>C-c R</code> which make LR or RL restricted copies of <e>'s, <code>C-c G</code> which finds the pardef of a dictionary entry (and lets you go back with <code>C-u C-SPC</code>) and <code>C-c S</code> which sorts a pardef by its right-hand-side <r>. |
|||
<pre> |
<pre> |
||
(defun nxml-dix-up-to |
(defun nxml-dix-up-to (eltname) |
||
"Move point before the |
"Move point before the element `eltname' (a string, eg. \"e\") |
||
which we're looking at." |
|||
⚫ | |||
(nxml-token-after) |
(nxml-token-after) |
||
(goto-char xmltok-start) |
(goto-char xmltok-start) |
||
(let ((tok (xmltok-start-tag-qname))) |
(let ((tok (xmltok-start-tag-qname))) |
||
(while (not (or (equal tok |
(while (not (or (equal tok eltname) (equal tok (concat "<" eltname)))) |
||
(nxml-backward-up-element) |
(nxml-backward-up-element) |
||
(nxml-token-after) |
(nxml-token-after) |
||
Line 23: | Line 24: | ||
restriction." |
restriction." |
||
(interactive "P") |
(interactive "P") |
||
(nxml-dix-up-to |
(nxml-dix-up-to "e") |
||
(kill-sexp) (yank) (newline-and-indent) (yank) |
(kill-sexp) (yank) (newline-and-indent) (yank) |
||
(goto-char (mark t)) |
(goto-char (mark t)) |
||
Line 33: | Line 34: | ||
(nxml-backward-up-element) (nxml-forward-element) (forward-word 2))) |
(nxml-backward-up-element) (nxml-forward-element) (forward-word 2))) |
||
(defun nxml-dix-goto-pardef () |
|||
;; whatever keys you prefer: |
|||
"Call from an entry to go to its pardef. Mark is pushed so you |
|||
⚫ | |||
can go back with C-u \\[set-mark-command]." |
|||
⚫ | |||
(interactive) |
|||
(if (save-excursion |
|||
⚫ | |||
(nxml-dix-up-to "e") |
|||
(re-search-forward "n=\"\\([^\"]*\\)\"") |
|||
(let ((pdname (match-string 1))) |
|||
(goto-char (point-min)) |
|||
(if (re-search-forward |
|||
(concat "<pardef *n=\"" pdname "\"") nil t) |
|||
(setq pos (match-beginning 0))))) |
|||
(progn (push-mark) |
|||
(goto-char pos)))) |
|||
(defun nxml-dix-sort-e-by-r (reverse beg end) |
|||
"Sort region alphabetically by contents of <r> element; |
|||
argument means descending order. Assumes <e> elements never |
|||
occupy more than one line. |
|||
Called from a program, there |
|||
are three arguments: REVERSE (non-nil means reverse order), BEG |
|||
and END (region to sort). The variable `sort-fold-case' |
|||
determines whether alphabetic case affects the sort order." |
|||
(interactive "P\nr") |
|||
(save-excursion |
|||
(save-restriction |
|||
(narrow-to-region beg end) |
|||
(goto-char (point-min)) |
|||
(let ;; To make `end-of-line' and etc. to ignore fields. |
|||
((inhibit-field-text-motion t)) |
|||
(sort-subr reverse |
|||
;; todo: use nxml-dix-up-to and |
|||
;; nxml-forward-element to make it XML general |
|||
'forward-line |
|||
'end-of-line |
|||
(lambda () |
|||
(nxml-forward-element) |
|||
(nxml-backward-down-element 2) |
|||
(nxml-backward-element))))))) |
|||
(defun nxml-dix-sort-pardef (reverse) |
|||
"Sort a pardef using `nxml-dix-sort-e-by-r'. Requires pardef to |
|||
be formatted as per apertium-dixtools." |
|||
⚫ | |||
(save-excursion |
|||
(nxml-dix-up-to "pardef") |
|||
(mark-sexp) |
|||
(forward-line) |
|||
(exchange-point-and-mark) |
|||
(beginning-of-line) |
|||
(nxml-dix-sort-e-by-r reverse (mark) (point)))) |
|||
;; add keyboard shortcuts on loading nxml-mode: |
|||
(add-hook 'nxml-mode-hook |
|||
(lambda () |
|||
⚫ | |||
⚫ | |||
(lambda nil (interactive) |
|||
⚫ | |||
add an RL restriction to the copy." |
add an RL restriction to the copy." |
||
(nxml-dix-restriction-copy 'RL))) |
|||
(define-key nxml-mode-map (kbd "C-c S") 'nxml-dix-sort-pardef) |
|||
(define-key nxml-mode-map (kbd "C-c G") 'nxml-dix-goto-pardef))) |
|||
</pre> |
</pre> |
||
Revision as of 08:16, 22 June 2009
Emacs has a nice xml editing mode called nXML.
I often define keyboard macros as I edit, some of these I record as
functions which you can put in your .emacs, since they come in handy
time and again. I use
Apertium-dixtools-formatted dix, some of the functions below won't work with the regular format (at least sort-pardef
). The code below adds keyboard shortcuts C-c L
and C-c R
which make LR or RL restricted copies of <e>'s, C-c G
which finds the pardef of a dictionary entry (and lets you go back with C-u C-SPC
) and C-c S
which sorts a pardef by its right-hand-side <r>.
(defun nxml-dix-up-to (eltname) "Move point before the element `eltname' (a string, eg. \"e\") which we're looking at." (nxml-token-after) (goto-char xmltok-start) (let ((tok (xmltok-start-tag-qname))) (while (not (or (equal tok eltname) (equal tok (concat "<" eltname)))) (nxml-backward-up-element) (nxml-token-after) (setq tok (xmltok-start-tag-qname))))) (defun nxml-dix-restriction-copy (&optional RL) "Make a copy of the Apertium element we're looking at, and add an LR restriction to the copy. A prefix argument makes it an RL restriction." (interactive "P") (nxml-dix-up-to "e") (kill-sexp) (yank) (newline-and-indent) (yank) (goto-char (mark t)) (let ((dir (if RL "RL" "LR"))) (forward-word) (insert (concat " r=\"" dir "\""))) (forward-char) (just-one-space) (delete-backward-char 1) (forward-word 3) (when RL (nxml-backward-up-element) (nxml-forward-element) (forward-word 2))) (defun nxml-dix-goto-pardef () "Call from an entry to go to its pardef. Mark is pushed so you can go back with C-u \\[set-mark-command]." (interactive) (if (save-excursion (nxml-dix-up-to "e") (re-search-forward "n=\"\\([^\"]*\\)\"") (let ((pdname (match-string 1))) (goto-char (point-min)) (if (re-search-forward (concat "<pardef *n=\"" pdname "\"") nil t) (setq pos (match-beginning 0))))) (progn (push-mark) (goto-char pos)))) (defun nxml-dix-sort-e-by-r (reverse beg end) "Sort region alphabetically by contents of <r> element; argument means descending order. Assumes <e> elements never occupy more than one line. Called from a program, there are three arguments: REVERSE (non-nil means reverse order), BEG and END (region to sort). The variable `sort-fold-case' determines whether alphabetic case affects the sort order." (interactive "P\nr") (save-excursion (save-restriction (narrow-to-region beg end) (goto-char (point-min)) (let ;; To make `end-of-line' and etc. to ignore fields. ((inhibit-field-text-motion t)) (sort-subr reverse ;; todo: use nxml-dix-up-to and ;; nxml-forward-element to make it XML general 'forward-line 'end-of-line (lambda () (nxml-forward-element) (nxml-backward-down-element 2) (nxml-backward-element))))))) (defun nxml-dix-sort-pardef (reverse) "Sort a pardef using `nxml-dix-sort-e-by-r'. Requires pardef to be formatted as per apertium-dixtools." (interactive "P") (save-excursion (nxml-dix-up-to "pardef") (mark-sexp) (forward-line) (exchange-point-and-mark) (beginning-of-line) (nxml-dix-sort-e-by-r reverse (mark) (point)))) ;; add keyboard shortcuts on loading nxml-mode: (add-hook 'nxml-mode-hook (lambda () (define-key nxml-mode-map (kbd "C-c L") 'nxml-dix-restriction-copy) (define-key nxml-mode-map (kbd "C-c R") (lambda nil (interactive) "Make a copy of the Apertium element we're looking at, and add an RL restriction to the copy." (nxml-dix-restriction-copy 'RL))) (define-key nxml-mode-map (kbd "C-c S") 'nxml-dix-sort-pardef) (define-key nxml-mode-map (kbd "C-c G") 'nxml-dix-goto-pardef)))
Also, if you like having all <i> elements aligned at eg. column 25, the following in your .emacs lets you do M-x align
on a region to achieve that, and also aligns <p> to 10 and <r> to 44 (for bidix):
(add-hook 'align-load-hook (lambda () (add-to-list 'align-rules-list '(nxml-dix-i-align (regexp . "\\(\\s-*\\)\\(<i.*\\)$") (modes . '(nxml-mode)) (column . 25))) (add-to-list 'align-rules-list '(nxml-dix-r-align (regexp . "\\(\\s-*\\)\\(<r>.*\\)$") (tab-stop . nil) (modes . '(nxml-mode)) (column . 44))) (add-to-list 'align-rules-list '(nxml-dix-p-align (regexp . "\\(\\s-*\\)\\(<p>.*\\)$") (modes . '(nxml-mode)) (column . 10)))))