How can I see list of labels?

Yes, you are right. It is funny :slight_smile: . Instead of home the Russian translation дом appears and instead of edit the Russian редактировать appears.

Dear @JoePass and @jeroen, we have an answer:
http://lists.texmacs.org/wws/arc/texmacs-users/2021-03/msg00001.html
I’ll read file-menu.scm soon—hopefully we will have a nice “verbatim” menu.

This worked in the short tests that I made.
Please let me know if now the menu entries are the labels or the translated labels.

;;=============================
;;Label list widget and balloon
;;=============================



;; the balloon shows all the labels that match the start of the current
;; reference or label (except the current label, which matches by definition,
;; if in a label)

(use-modules (utils library cursor)) ; for the with-cursor macro (Scheme
					; developer's manual, pag. 20)



;;; indexed sorting

(define (sort-list-indexed lst proc)
	(let* ((lst-indexed
	       (map (lambda (x y) (cons x  y)) 
		    lst (iota (length lst))))
	       (lst-indexed-sorted
		(sort-list lst-indexed (lambda (x y) (proc (car x) (car y))))))
	  (values (map car lst-indexed-sorted) (map cdr lst-indexed-sorted))))

;;; From srfi-1

 (define (partition pred lis)
  (check-arg procedure? pred partition)
  (let recur ((lis lis))
    (if (null-list? lis) (values lis lis)       ; Use NOT-PAIR? to handle dotted lists.
        (let ((elt (car lis))
              (tail (cdr lis)))
          (receive (in out) (recur tail)
            (if (pred elt)
                (values (if (pair? out) (cons elt in) lis) out)
                (values in (if (pair? in) (cons elt out) lis))))))))

;; In the introductory comments to srfi-1 (because part of r5rs)
   (define (check-arg pred val caller)
      (let lp ((val val))
        (if (pred val) val (lp (error "Bad argument" val pred caller)))))


 (define (null-list? l)
  (cond ((pair? l) #f)
        ((null? l) #t)
        (else (error "null-list?: argument out of domain" l))))


;;; indexed partitioning

;; partitions a list according to pred, then conses one partition to the list
;; equivalence-classes and passes the new list equivalence-classes and the
;; other partition to a copy of itself (recursively)
(define (partition-equivalence-classes-aux pred equivalence-classes lst)
  (cond ((null? lst) equivalence-classes) ; base case
	(values
	  (call-with-values
	      (lambda ()
		(partition (lambda (x) (pred (car lst) x)) lst))
	    (lambda (l1 l2)
	      (partition-equivalence-classes-aux
	       pred
	       (cons l1 equivalence-classes)
	       l2))))))

(define (partition-equivalence-classes pred lst)
  (partition-equivalence-classes-aux pred '() lst))

;; marks each element of lst with its position index, then partitions the new
;; list in equivalence classes using equivalence of the car as predicate.
;; In this way, we have a partitioned list and we know which position each
;; element had in the original list
(define (partition-equivalence-classes-indexed pred lst)
  (let ((lst-indexed (map (lambda (x y) (cons x y))
			  lst (iota (length lst)))))
    (partition-equivalence-classes
     (lambda (x y) (pred (car x) (car y)))
     lst-indexed)))

;;; index elements of a list of strings starting from the second element,
;;; adding the index at the end of the string

;; Generate a list of indices, turn them into strings, append them to the
;; strings in the list using map.

;; In the previous version of the code it was done applying the function
;; index-pairs-aux recursively


(define (parenthesize-index n)
   (string-join `("(" ,(number->string n) ")") ""))

(define (string-indices lst)
  (cons "" (map parenthesize-index
		(map (cut + <> 2) (iota (- (length lst) 1))))))

(define (index-element elem index-string)
  (cons (string-join `(,(car elem) ,index-string)) (cdr elem)))

(define (index-pairs-from-second lst)
  (map index-element lst (string-indices lst)))



;; The list of indexed strings is organized into equivalence classes; we
;; flatten it before re-ordering it according to the original ordering (saved
;; in the indices in the cdr). Here is the flattening function
(define (flatten lst)
  (cond ((null? lst) lst)
	((not (list? (car lst))) (cons (car lst) (flatten (cdr lst))))
	(else (append (car lst) (flatten (cdr lst))))))



;;; Tree search

(define (biblio-context? t)
  (or (tree-func? t 'bibliography 4)
      (tree-func? t 'bibliography* 5)))

(tm-define (in-biblio-context? t) (tree-search-upwards t biblio-context?))

;; definition of tree-search
;; in progs/kernel/library/tree.scm

;; (define-public (tree-search t pred?)
;;   (with me (if (pred? t) (list t) '())
;;     (if (tree-atomic? t) me
;; 	(append me (append-map (cut tree-search <> pred?)
;; 			       (tree-children t))))))


;; Starting from the standard tree-search, a tree-search function that does not
;; look inside the current focus.
;; If I find the path of (focus-tree) I exit from the function

;; I could write a single search function that does not look inside the current
;; focus and apply it to every case (since we are looking for labels, excluding
;; the current focus in a reference will find all labels)
(define (tree-search-elsewhere t pred?)
  (with me (if (and (pred? t) ) (list t) '())
    (cond
      ((tree-atomic? t) me)
      ((equal? (tree->path (focus-tree)) (tree->path t)) '())
      (else (append me (append-map (cut tree-search-elsewhere <> pred?)
				   (tree-children t)))))))

(tm-define (search-doc-all-labels t)
  (:synopsis "A function that finds all labels that are not part of the bibliography.")
  (tree-search t
    (lambda (s) (and (label-context? s) (not (in-biblio-context? s)))
	    )))

(tm-define (search-doc-elsewhere-labels t)
  (:synopsis "A function that finds all labels outside the current focus that are not part of the
bibliography.")
  (tree-search-elsewhere t
    (lambda (s) (and (label-context? s) (not (in-biblio-context? s)))
	    )))

(tm-define (search-doc-labels t)
  (if (label-context? (focus-tree))
      (search-doc-elsewhere-labels t)
      (search-doc-all-labels t)))


;;; Filter labels that start as the text typed in the label or reference in focus

(tm-define (filter-labels labels str)
  (:synopsis "Keeps the labels whose start is equal to str")
  (filter (lambda (s)
	    (and (>= (string-length s) (string-length str))
		 (string-contains s str 0 (string-length str)))) 
	  labels))
;; first we check if the string is at least as long as the text in the ref or
;; label (arguments of and are evaluated only up to the first that is false)
;; then we check that the label contains the already-typed text (which is now
;; at most as long as the label).
;; The two indices 0 and (string-length str) cause the comparison to be made
;; only to the beginning substring of s of length equal to the length of str.
;; I think that the indices of string-contains behave like the indices of
;; substring (first included, last excluded), I tested this in one case only:
;; (string-contains "test " "test" 0 4) $0
;; (string-contains "test " "test" 0 3) $#f



;;; Index repeated labels to distinguish them

;; The "enum" widget provided by TeXmacs filters the list to keep only unique
;; entries. We want to see all labels, so we add an index to repeated entries
;; applying the function index-repeated-entries, which needs the function
;; order-indexed-list to put its elements in the original order after it marked
;; them


;; order-indexed-list puts the element marked with i at the i-th place in the
;; output list; for this, it uses imperative code
(define (order-indexed-list lst)
  (let ((ordered-lst (make-list (length lst))))
    (begin
      (do ((i 0 (1+ i))) ((>= i (length lst)))
	(list-set! ordered-lst
		   (cdr (list-ref lst i))
		   (car (list-ref lst i))))
      ordered-lst)))

(define (index-repeated-entries lst)
  (order-indexed-list
   (flatten (map index-pairs-from-second
		 (partition-equivalence-classes-indexed equal? lst)))))



;;; Build label list

;; use search-doc-labels function instead of the standard search-labels, that
;; finds the labels defined in the bibliography as well.
;; The search-doc-labels function behaves differently if in a label (excludes
;; the current focus)
(define (label-list)
  (let ((ls (search-doc-labels (buffer-tree))))
    (map (lambda (l) (tree->string (tm-ref l 0))) ls)))
;; (define (label-list)
;;   (let ((ls (search-doc-labels (buffer-tree))))
;;     (map (lambda (l) (cadr (tree->stree l))) ls)))


;;; Widget

;; An insert function that inserts a string only up to before the last blank
(define (keep-till-first-blank str)
  ;; (display "keep-till-first-blank\n")
  (let* ((ind-first-blank (string-index str #\space)))
    ;; if we did not find a blank,
    ;; ind-first-blank is false: keep the
    ;; whole string
    (if ind-first-blank
	(substring str 0 ind-first-blank)
	str)))


;; The enum widget treats the entries of its list as if they were menu entries,
;; translating them into the language set for the interface.  In order to
;; prevent this, we wrap each list entry in a verbatim tag (see
;; http://lists.texmacs.org/wws/arc/texmacs-users/2021-03/msg00001.html).  When
;; using the selected element (saved inside the "answer" variable) we then need
;; to extract the string element out of the verbatim tag.
(tm-widget (enum-labels)
  (enum (with-cursor ; place the selected item at the end of the current focus
	    (path-end (root-tree) (tree->path (focus-tree)))
	  (insert (keep-till-first-blank (cadr answer))))
					; We use (cadr answer) to extract the
					; string out of the verbatim tag
					; keep-till-first-blank acts on (cadr
					; answer), because in the list we want
					; to display the combination of label
					; and index
	(map (lambda (l) `(verbatim ,l))
	     (index-repeated-entries (label-list)))
	"Choose label ..."
"24em"))

;; Attempt to fix the "<меньше>" issue
;; Does not work, the issue is probably a bug
;; (tm-widget (enum-labels)
;;   (enum (with-cursor ; place the selected item at the end of the current focus
;; 	    (path-end (root-tree) (tree->path (focus-tree)))
;; 	  (insert (keep-till-first-blank answer)));keep-till-first-blank acts
;; 					;on answer, because in the list we want
;; 					;to display the combination of label
;; 					;and index
;; 	(map stree->tree (index-repeated-entries (label-list))) "Choose label ..."
;; "24em"))


;;; Balloon

(tm-define (label-balloon)
  (let* ((focus-string (cadr (tree->stree (focus-tree))))
         (ll (filter-labels ; keep only labels that start with the text in focus tree
	      (label-list)
	      focus-string)))
    (display-balloon (cursor-tree) `(document ,@ll) "auto" "auto" "keyboard")))

;; (tm-define (label-balloon)
;;   (let* ((focus-string (cadr (tree->stree (focus-tree))))
;;          (ll (filter-labels ; keep only labels that start with the text in focus tree
;; 	      (label-list)
;; 	      focus-string)))
;;     (display-balloon (cursor-tree) `(document ,@(map stree->tree ll)) "auto" "auto" "keyboard")))

;;; Tie widget and balloon to context and actions

(define (inactive-reference-focus)
  (and (inside? 'inactive)
            (or
             (reference-context? (focus-tree))
             (label-context? (focus-tree)))))

;; Widget in context menu
(tm-menu (texmacs-popup-menu)
  (:require (inactive-reference-focus))
  (former)
  ---
  ("Show labels" (top-window enum-labels "Insert labels")))

;; Balloon to keyboard shortcut
(kbd-map
  (:require (inactive-reference-focus))
  ("C-l C-l" (label-balloon)))


I checked It works well for \ref \eqref and \label even with preview-ref started. But nothing happens with Ctl-l Ctr-l clicking (with and without preview-ref, with and without ridged paper style).

This can be because of two things, not exclusive of each other (according to how the program works and my experience using it in TeXmacs):

  1. You are in a label, which is unique (i.e. there is no other label which starts in the same way). The balloon shows all other labels that start like the current label; if you are in a reference, it shows all labels that starts like the reference. If you are in a label with unique name, pls. either try the shortcut in a reference or in a label which starts like some other labels.

  2. TeXmacs is not recognizing the shortcut. It happened to me, but I did not write it down and I forgot when (perhaps when testing under Windows). If you are not in case 1., pls. try and change the shortcut
    (for example, try “C-F8” like @jeroen set it to)

For point .1 I will try and document the widget code better than it is now, but it will take time.

Please let me know. We should be able to make it work :slight_smile:

It works but with Theme->Plain only. I use ridged paper and with this theme, it does not work. Also, I observed that it works slowly with \label. But without a balloon the functionality is well.

Which one of the two was the reason? i.e. you were in a unique label or did you need to change shortcut? Or something else?

IMHO that is a bug of TeXmacs (maybe worth reporting)

I will think about this. I do not see a possible reason while I am writing, but if something comes to my mind I will write again.

I just forget that balloon is working when \ref \eqref or \label has started :).

Sorry, I did not understand. Could you try explaining in another way?

To use C-l C-l I have to print first \ref, \eqref, or \lebel and after use C-l C-l. But I used C-l C-l without \ref, \eqref, or \lebel.

1 Like

Thanks for writing this function. I think it’s essential for a smooth writing experience.

I found that I can make the balloon stable with preview-ref on by holding the shortcut. It does have a down side, though. The focus menu will freeze for some time and the longer I holds, the longer the time will be.

2 Likes