Skip to Content.
Sympa Menu

texmacs-users - Re: Closing a widget automatically

Subject: mailing-list for TeXmacs Users

List archive

Re: Closing a widget automatically


Chronological Thread 
  • From: Giovanni Piredda <address@hidden>
  • To: address@hidden
  • Subject: Re: Closing a widget automatically
  • Date: Sat, 23 Jan 2021 00:55:11 +0100


Am 19.01.2021 um 08:29 schrieb Massimiliano Gubinelli:
You can try to use balloon widgets, see here how Joris implemented the link preview with that

https://texmacs.github.io/notes/docs/previews.html <https://texmacs.github.io/notes/docs/previews.html>

Max


Jeroen picked up the suggestion of using a balloon and after more development I post here the current code for, now, an enum widget and a balloon widget (at the end of the post). You can either place the code in the personal initialization file or in a module that then you can load using use-modules (through the initialization file if you want the widgets to be available in all files).

There are two widgets: a choice widget and a balloon widget

The choice widget is available through the context menu when either in an inactive reference or in an inactive label. It will include all labels; labels which are repeated are indexed with a number (starting from the second occurrence); clicking on a label inserts it at the current cursor position. The widget remains open till the user closes it; till it is open, you will be inserting the strings present in the label list at the current cursor position every time you click on one of them (the list is formed when the widget is set up and isn't ever updated). More than one widget can be open at the same time (containing possibly different lists).

The balloon is linked to a keyboard shortcut, active either in an inactive reference or in an inactive label. If it does not appear, you can try changing shortcut (it was in this way for me).

If in a reference, the balloon widget contains the list of all labels that start with the string that is present in the reference at the time the balloon is invoked (without indexing of repeated entries). If in a label, it contains again the list of matching labels (as when in a reference) minus the current label. It is not---yet---possible to use it to insert a reference at the cursor position, though maybe it is possible to add that.

The biggest flaw I see at the moment is in the way I am indexing repeated entries; I (not Jeroen, I don't want to compromise his reputation on this flawed code :-)) coded it in a o(n^2) way. My gut feeling is that up to 50 labels it should be ok, and when the labels are 100 the code will become sluggish (did not test it). One way to code it in a close-to-linear way is first sort the labels, then index repeated entries, then reset the initial ordering, but I have to search for code that does this (I have found immediately code that sorts, but I think that I need an indexed sort as well to reinstate the initial order).

;; optional module declaration: modify according to your wishes

;;(texmacs-module (widgets widget-label-list))

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


;;; 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

;; The following functions work well together because in the input list of
;; labels found by search-doc-labels there are no spaces, so I can apply the
;; index-equal-elements to the cdr of the list after I have already modified it
;; with index-equal-elements applied to the whole list (using as a comparison
;; the car of the list)---the modifications neither cause new matches, nor
;; exclude already-existing matches

(define (index-equal-elements element lst n)
  (cond ((null? lst) lst)
    ((equal? (car lst) element)
     (cons (string-join `(,(car lst) " (" ,(number->string n) ")") "")
           (index-equal-elements element (cdr lst) (+ n 1))))
    (else  (cons (car lst) (index-equal-elements element (cdr lst) n)))))

(define (index-repeated-entries lst)
  (cond ((null? lst) lst)
    (else (cons (car lst)
            (index-repeated-entries
             (index-equal-elements (car lst) (cdr lst) 2))))))


;;; 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)))


;;; 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)))

(tm-widget (enum-labels)
  (enum (insert (keep-till-first-blank answer))
(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")))

;;; 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-F8" (label-balloon)))






Archive powered by MHonArc 2.6.19.

Top of Page