;;; eev-edit.el -- tools for editing (mainly refining) elisp hyperlinks.
;; Copyright (C) 2012-2020 Free Software Foundation, Inc.
;;
;; This file is part of GNU eev.
;;
;; GNU eev is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; GNU eev is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see .
;;
;; Author: Eduardo Ochs
;; Maintainer: Eduardo Ochs
;; Version: 20201228
;; Keywords: e-scripts
;;
;; Latest version:
;; htmlized:
;; See also:
;;
;; (find-eev-intro)
;;; Commentary:
;; See:
;; (find-refining-intro "2. Refining hyperlinks")
;; (find-eval-intro "9. Producing and refining hyperlinks")
;; (find-escripts-intro "5.7. Refining hyperlinks")
;; (find-escripts-intro "5.8. Pointing to anchors")
;; (find-eevfile "eev-mode.el" "Keys for refining hyperlinks")
;;
;; `M-h M--', `M-s' and `M-I' are not yet explained in the intros!
;; «.ee-duplicate-this-line» (to "ee-duplicate-this-line")
;; «.ee-yank-pos-spec» (to "ee-yank-pos-spec")
;; «.ee-copy-this-line-to-kill-ring» (to "ee-copy-this-line-to-kill-ring")
;; «.ee-shrink-hyperlink-at-eol» (to "ee-shrink-hyperlink-at-eol")
;; «.ee-flip-psne-ness» (to "ee-flip-psne-ness")
;; «.eewrap-vldi-list-line» (to "eewrap-vldi-list-line")
;;; _ _ _ _
;;; __| |_ _ _ __ | (_) ___ __ _| |_ ___
;;; / _` | | | | '_ \| | |/ __/ _` | __/ _ \
;;; | (_| | |_| | |_) | | | (_| (_| | || __/
;;; \__,_|\__,_| .__/|_|_|\___\__,_|\__\___|
;;; |_|
;;
;; «ee-duplicate-this-line» (to ".ee-duplicate-this-line")
;; (define-key eev-mode-map "\M-h\M-2" 'ee-duplicate-this-line)
;; See: (find-refining-intro "2. Refining hyperlinks")
;; (find-refining-intro "2. Refining hyperlinks" "M-h M-2")
(defun ee-duplicate-this-line ()
"Duplicate the current line (without any changes to the kill ring)."
(interactive)
(let ((line (buffer-substring (ee-bol) (ee-eol))))
(save-excursion (beginning-of-line) (insert-before-markers line "\n"))))
;;; _
;;; _ _ __ _ _ __ | | __
;;; | | | |/ _` | '_ \| |/ /
;;; | |_| | (_| | | | | <
;;; \__, |\__,_|_| |_|_|\_\
;;; |___/
;;
;; «ee-yank-pos-spec» (to ".ee-yank-pos-spec")
;; (define-key eev-mode-map "\M-h\M-y" 'ee-yank-pos-spec)
;; See: (find-refining-intro "2. Refining hyperlinks")
;; (find-refining-intro "2. Refining hyperlinks" "M-h M-y")
;; (find-refining-intro "yanks" "the text at the end of the sexp")
(defun ee-yank-pos-spec ()
"Append the top of the kill ring to a hyperlink sexp, as a Lisp string.
This command is useful for \"refining elisp hyperlinks\" by adding a
pos-spec argument to them. Here's an example; if you are using the
default `eev-mode-map' keybindings then
`M-h M-i' runs `find-einfo-links',
`M-h M-2' runs `ee-duplicate-this-line', and
`M-h M-y' runs `ee-yank-pos-spec'.
Suppose that you are visiting the info node below,
(find-enode \"Lisp Eval\")
and you find some interesting information in that page, close to
an occurrence of the string \"`defvar'\". You mark that string,
add it to the kill-ring with `M-w', then type `M-h M-i', go to
the line that contains
# (find-enode \"Lisp Eval\")
and then you type `M-h M-2 M-h M-y'; it becomes these two lines:
# (find-enode \"Lisp Eval\")
# (find-enode \"Lisp Eval\" \"`defvar'\")
Now you check that the second line points to where you wanted,
and you copy that hyperlink to a more permanent place."
(interactive)
(goto-char (1- (point-at-eol))) ; put point before the ")"
(insert " " (ee-pp0 (ee-last-kill)))) ; insert pos-spec
;;; ____ _ _ _ _ _
;;; / ___|___ _ __ _ _ | |_| |__ (_)___ | (_)_ __ ___
;;; | | / _ \| '_ \| | | |_____| __| '_ \| / __|_____| | | '_ \ / _ \
;;; | |__| (_) | |_) | |_| |_____| |_| | | | \__ \_____| | | | | | __/
;;; \____\___/| .__/ \__, | \__|_| |_|_|___/ |_|_|_| |_|\___|
;;; |_| |___/
;;
;; «ee-copy-this-line-to-kill-ring» (to ".ee-copy-this-line-to-kill-ring")
;; (define-key eev-mode-map "\M-h\M-w" 'ee-copy-this-line-to-kill-ring)
;; See: (find-refining-intro "3. Three buffers")
;; (find-refining-intro "3. Three buffers" "M-h M-w")
(defun ee-copy-this-line-to-kill-ring (&optional arg)
"Copy the current line to the kill ring and highlight (\"flash\") it.
With a prefix argument run `ee-copy-preceding-tag-to-kill-ring' instead."
(interactive "P")
(if arg (ee-copy-preceding-tag-to-kill-ring)
(let* ((start (ee-bol))
(end (save-excursion (next-line) (ee-bol)))
(str (buffer-substring start end))
(msg "Copied the current line to the kill ring - use C-y to paste"))
(eeflash+ start end eeflash-copy)
(kill-new str)
(message msg))))
;; Experimental, 2019aug29
;; See: (find-anchors-intro "3. The preceding tag")
;;
;; (defun ee-tag-re () (ee-tolatin1 "«\\([!-~]+\\)»"))
(defvar ee-tag-re-utf-8 "«\\([!-~]+\\)»")
(defun ee-tag-re () ee-tag-re-utf-8)
(defun ee-copy-preceding-tag-to-kill-ring ()
"Copy the preceding tag to the kill ring and highlight (\"flash\") it.
A \"tag\" is the string between \"«»\"s in an anchor."
(interactive)
(save-excursion
(if (re-search-backward (ee-tag-re))
(let* ((start (match-beginning 1))
(end (match-end 1))
(str (ee-no-properties (match-string 1)))
(msg (format "Copied \"%s\" to the kill ring" str)))
(eeflash start end eeflash-copy)
(kill-new str)
(message msg))
(error "No preceding tag!"))))
;;; _ _ _
;;; ___| |__ _ __(_)_ __ | | __
;;; / __| '_ \| '__| | '_ \| |/ /
;;; \__ \ | | | | | | | | | <
;;; |___/_| |_|_| |_|_| |_|_|\_\
;;;
;; «ee-shrink-hyperlink-at-eol» (to ".ee-shrink-hyperlink-at-eol")
;; (define-key eev-mode-map "\M-h\M--" 'ee-shrink-hyperlink-at-eol)
;; See: (find-anchors-intro "2. Shrinking")
(defun ee-shrink-sexp (sexp)
"If the car of SEXP of the form `find-xxxfile', reduce it to `find-xxx'."
(if (eq (car sexp) 'find-esfile)
`(find-es ,(substring (nth 1 sexp) 0 -2) ,@(cddr sexp))
(let* ((headname (symbol-name (car sexp)))
(last4chars (substring headname -4))
(-last4chars (substring headname 0 -4)))
(if (equal last4chars "file")
`(,(intern -last4chars) ,@(cdr sexp))))))
(defun ee-shrink-hyperlink-at-eol ()
(interactive)
(end-of-line)
(let* ((beg (save-excursion (ee-backward-sexp)))
(sexp (read (buffer-substring beg (point))))
(shrunksexp (ee-shrink-sexp sexp)))
(when shrunksexp
(delete-region beg (point))
(insert (ee-pp0 shrunksexp)))))
;;; __ _ _
;;; / _| (_)_ __ _ __ ___ _ __ ___
;;; | |_| | | '_ \ _____| '_ \/ __| '_ \ / _ \
;;; | _| | | |_) |_____| |_) \__ \ | | | __/
;;; |_| |_|_| .__/ | .__/|___/_| |_|\___|
;;; |_| |_|
;;
;; «ee-flip-psne-ness» (to ".ee-flip-psne-ness")
;; (define-key eev-mode-map "\M-s" 'ee-flip-psne-ness)
;; See: (find-psne-intro "6. `ee-flip-psne-ness'")
;; (find-psne-intro "6. `ee-flip-psne-ness'" "M-s")
(defun ee-flip-psne-ness ()
(interactive)
(if (search-forward-regexp "\\$S/\\(https?\\|ftp\\)/\\|\\(https?\\|ftp\\)://")
(cond ((match-string 1) (replace-match "\\1://"))
((match-string 2) (replace-match "$S/\\2/")))))
;;; _ _ _ _ _ _ _ _
;;; __ _| | __| (_) | (_)___| |_ | (_)_ __ ___
;;; \ \ / / |/ _` | |_____| | / __| __|____| | | '_ \ / _ \
;;; \ V /| | (_| | |_____| | \__ \ ||_____| | | | | | __/
;;; \_/ |_|\__,_|_| |_|_|___/\__| |_|_|_| |_|\___|
;;;
;; «eewrap-vldi-list-line» (to ".eewrap-vldi-list-line")
;; (define-key eev-mode-map "\M-I" 'eewrap-vldi-list-line)
;;
;; This is an undocumented hack! (?)
;;
;; In a Debian system, for each installed package named xxxx there is
;; an associated file, at /var/lib/dpkg/info/xxxx.list - let's call
;; that the "vldi list" associated to the package xxxx - that lists
;; all the files installed by that package...
;;
;; To convert a vldi list to hyperlinks, copy it to a read-write
;; buffer and run M-I on each of its lines. More details later - this
;; is a hack!
;;
;; Old version: (find-eev "eev-insert.el" "ee-ill")
(defun eewrap-vldi-list-line () (interactive)
"Convert a filename at the current line into a hyperlink, and go down.
Supports `find-man', `find-udfile', and `find-fline' hyperlinks.
This function recognizes lines containing directory names, and
handles them in the following way: if the current line contains a
directory name, say, /foo/bar, and the next line contains the
name of a file or a directory in /foo/bar, say, /foo/bar/plic,
then just delete the current line."
(beginning-of-line)
(if (looking-at "^\\(.*\\)\n\\1/") ; a directory
(delete-region (point) (progn (ee-next-line 1) (point)))
(ee-this-line-wrapn 1 'ee-wrap-vldi-list-line)))
(defun ee-wrap-vldi-list-line (line)
"An internal function used by `eewrap-vldi-list-line'."
(if (string-match "^.*/man./\\([^/]+\\)\\.\\([0-9A-Za-z]+\\)\\.gz$" line)
(format "%s(find-man \"%s %s\")"
ee-H (match-string 2 line) (match-string 1 line))
(if (string-match "^/usr/share/doc/\\(.*\\)$" line)
(format "%s(find-udfile \"%s\")" ee-H (match-string 1 line))
(format "%s(find-fline \"%s\")" ee-H line))))
;; (find-vldifile "bash.list")
(provide 'eev-edit)
;; Local Variables:
;; coding: utf-8-unix
;; ee-anchor-format: "«%s»"
;; no-byte-compile: t
;; End: