[Date Prev][Date Next][Thread Prev][][Date Index][Thread Index]

Re: What does function w3m-search-name-anchor do?

On 2019-05-28 10:57, Boruch Baum wrote:
> Function `w3m-search-name-anchor' was recently modified. It is an
> interactive function, without any docstring or keybinding, and I don't
> understand what it is supposed to be doing. Can someone please explain
> it / add a docstring?

Okay, I was impatient, and since I didn't hear any feedback quickly, I
did some poking around, and I think I understand the original intent of
the person who wrote the function. However, there seem to be a bunch of
problems / issues with the function, and it should either be documented
and bound to a key, or have its interactive spec removed.

The idea is to allow a user to easily jump to any anchor on a page, from
any point on that page. The first two problems are that the user needs
to know the exact spelling of the anchor, and there's no way for a user
to know that without either looking at the page's raw html or buffer's
text properties. Let's use the project's own home page
(http://emacs-w3m.namazu.org/) as an example. If you tab through the
page's links, you'll notice subtle differences between each local-link's
label and the actual anchor (the actual link/anchor should appear in the
echo area when you tab to a link). In the case of this particular page,
the differences are capitalizations, but that's arbitrary.

When looking at the internals, another weirdness appears: each anchor
for some reason is a list of itself and all the page's previous anchors.
Here's a test function to illustrate. When you run it and check the
*Messages* buffer, note the accumulating content in the
w3m-name-anchor2. I haven't yet figured out what text property
w3m-name-anchor is meant to be, and why it is distinct from w3m-name-anchor2.

(defun w3m--test-show-page-anchors ()
  (let ((pos (point-min))
	(cur-pos (point))
    (message "debug: w3m-name-anchor")
    (while (setq pos (next-single-property-change pos 'w3m-name-anchor))
      (message "debug: pos: %s  anchor: %s" pos (get-text-property pos 'w3m-name-anchor)))
    (setq pos (point-min))
    (message "debug: w3m-name-anchor2")
    (while (setq pos (next-single-property-change pos 'w3m-name-anchor2))
      (message "debug: pos: %s  anchor: %s" pos (get-text-property pos 'w3m-name-anchor2)))))

Here is a pair of functions that makes the idea behind the original
function more useful to an end-user.

(defun w3m--get-page-anchors ()
  "Returns an alist of name anchors and positions for the current buffer."
  (let ((pos (point-min))
	(cur-pos (point))
    (while (setq pos (next-single-property-change pos 'w3m-name-anchor))
      (push (cons (car (get-text-property pos 'w3m-name-anchor)) pos) anchor-list))
    (setq pos (point-min))
    (while (setq pos (next-single-property-change pos 'w3m-name-anchor2))
      (push (cons (car (get-text-property pos 'w3m-name-anchor2)) pos) anchor-list))

(defun w3m-search-name-anchor (name &optional quiet no-record)
  "Jump to an anchor on the current page.
When called interactively, prompts for the anchor NAME.
Otherwise, when QUIET is non-nil, don't report an error, and NO-RECORD ???"
  (interactive (list (completing-read "Name: " (w3m--get-page-anchors) nil t) nil nil))
  (let ((anchor-list (w3m--get-page-anchors)))
    (if (not (assoc name anchor-list))
      (unless quiet
        (w3m--message t 'w3m-error "No such anchor: %s" name))
     (goto-char (cdr (assoc name anchor-list))))))

This pair of functions retains the current data structures. However,
it's still unclear to me why the values of w3m-name-anchor2 are lists
instead of just a single value. Also, it might computationally make more
sense to generate the alist of (anchor-name . position) at the time the
page is originally rendered, and store it as a buffer-local variable.

The pair of functions seem to be an improvement, but still aren't a
complete solution, because the function should really prompt the user
for the "page-visible" label for the anchor instead of for the technical
anchor name. In the test case I chose, the project home page, the
correspondence is obvious with only minor case variations, but many
pages encode their anchors. For example, the user would see "foo", but
the anchor would be "chapter01section04".

Still, it's an improvement.

CA45 09B5 5351 7C11 A9D1  7286 0036 9E45 1595 8BC0