How can I see list of labels?

Here I have to figure out how (search-labels (buffer-tree)) works. Maybe I will succeed. Please give me some time.

Here I think I know what you mean (at least approximately) but I am too far away from understanding the code to be able to answer. Maybe one of the developers can help (we have to invoke them: @mgubi).

In any way, thank you very much. I’m sure that it will be much better to include this option in the future versions of the Texmacs.

TeXmacs is reasonably easy to extend by users. In my opinion, it takes now some documented and well-guided examples so that more people will write extensions. I hope that the blog at https://texmacs.github.io/notes/docs/main.html will help as a place where people can write small tutorials and also document/publicize good extensions that they write.

For this example, I will need to learn a bit more to be able to write about it: I have “hacked” it rather than “programmed” it. But: step by step.

Thank you for your reference. I made as noted in that cite " To automatically regenerate all the web pages use Tools->Web->Create/Update web site within TeXmacs and choose src/ as source and docs/ as destination directories. Once the repository is pushed on github it becomes visible." But I do not understand how to use these notes in TeXmacs.

If I understand well your question: I did not give the link to the website so that you may find in it something to use for writing references, but to say that I hope that with time it may become a collection of user-written extensions. In this way one would not have to always ask the developers for features (like in this case the list of labels), but could find them in the extensions written by users.
Of course this is my way of seeing things.

I re-read your initial post and modified the code. Now the contextual menu has an entry for label search when you are writing a label as well. Here is the code (pls. substitute it in place of the one I wrote above in this thread):

(tm-widget (enum-labels) 
  (enum (insert answer) 
(map cadr (map tree->stree (search-labels (buffer-tree)))) "Choose label ..."
"24em"))


(tm-menu (texmacs-popup-menu)
  (:require (or
	     (and 
	      (tree-is? (focus-tree) 'reference) 
	      (tree-is? (tree-outer (focus-tree)) 'inactive))
	    (and
	     (tree-is? (focus-tree) 'label)
	     (tree-is? (tree-outer (focus-tree)) 'inactive))))
  (former)
  ---
  ("Show labels ..." (show enum-labels)))

I did not yet figure out how to exclude the labels of the bibliography entries from the list. I will let you know what happens.

1 Like

You could do something like this to filter bibliography entries:

(filter
(lambda u (not (string-starts? (car u) "bib-")))
(map cadr
  (map tree->stree
        (search-labels (buffer-tree))
            ))
))
1 Like

Inspired by the code in progs/link/ref-edit.scm, here is a function to find all labels starting with a string:

(tm-define (search-labels-starts t s)
(let* (
     (labs (search-labels t))
     (labl (map (lambda (lab) (tm->string (tm-ref lab 0))) labs))
     (filt (lambda (lab) (string-starts? lab s))))
(list-filter labl filt)))

This could be useful to implement a dialog that adapts while the user is typing the label or reference.

1 Like

This has the disadvantage that the user needs to remember that labels must not start with “bib-”. If it is possible, I would like a code that checks the tree above the label and filters the label out if it is in the bibliography.
I have tried, also looking at progs/link/ref-edit.scm,

(tm-define (label-context-b? t)
   (and (tree-in? t (label-tag-list)) (not (tree-is? (tree-outer (tree-outer t)) 'bibitem*))))

together with

(tree-search (buffer-tree) label-context-b?)

which did not work.

I am thinking how to insert in a widget the other piece of code you wrote.

The code to “execute function on any keypress in this field” could be in \progs\generic\search-widgets.scm, as matches get highlighted when one types in the box for text search, but I haven’t understood where yet.

It is a good idea. I use Latex for many years and can solve any problem with Latex by using the internet. There is huge information about Latex. The bad side of Texmacs is the need for knowledge of Scheme and there is a great problem with writing extensions. The collection (with an explanation if possible) of extensions will be good support for using Texmacs.

I do not have yet a grasp of this, but I realized, after a bit of time using it, that there is at least one good reason for using Scheme as an extension language: recursion (“natural” in Scheme) acts very well on the trees that represent TeXmacs documents.

It seems that if you do tree-outer twice you get a document containing multiple bibitem*s.

This seems to work:

(tree-is? (tree-ref t :previous) 'bibitem*)

I also notice that progs/database/bib-local.scm has a biblio-context? function:

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

Using this I think we could also do

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

and

(tm-define (search-doc-labels t)
  (tree-search t
    (lambda (s) (and (label-context? s) (not (in-biblio-context? s)))
  )))
1 Like

I still have to understand the details of how it works (e.g. what tree-func? does), but it is very nice. With my tree-outer construct I wanted to reach the bibliography tag, the one I posted is not rational (starting from the guess that tree-outer picks up the upper branch of the tree) as bibitem is at the same level as the label.

With this I think we are at version 0.99 of the widget :smirk:. There is one important property of the widget to implement: it must be either a modal window, or it must disappear once the user starts editing somewhere else. In the current state, one could end up with several widgets open at the same time.
Having it modal is probably the easiest of the two options, but the other could maybe work as well. I have made a very brief internet search (with the words modal widget texmacs) and I found two pages which seem relevant
https://lists.texmacs.org/wws/arc/texmacs-users/2013-10/msg00002.html
https://www.mail-archive.com/texmacs-dev@gnu.org/msg01978.html
but I will go through them later (and maybe search/read more).

So, for @JoePass, this is the current code for the initialization file

(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?))


(tm-define (search-doc-labels t)
  "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)))
  )))


;; use search-doc-labels function instead of the standard search-labels, that
;; finds the labels defined in the bibliography as well
(tm-widget (enum-labels) 
  (enum (insert answer) 
(map cadr (map tree->stree (search-doc-labels (buffer-tree)))) "Choose label ..."
"24em"))


(tm-menu (texmacs-popup-menu)
  (:require (or
	     (and 
	      (tree-is? (focus-tree) 'reference) 
	      (tree-is? (tree-outer (focus-tree)) 'inactive))
	    (and
	     (tree-is? (focus-tree) 'label)
	     (tree-is? (tree-outer (focus-tree)) 'inactive))))
  (former)
  ---
  ("Show labels ..." (show enum-labels)))
1 Like

Excellent! Thank you for this code. I hope it will be useful for TeXmacs users. I changed a little bit your code. I added

(and 
	      (tree-is? (focus-tree) 'eqref) 
	      (tree-is? (tree-outer (focus-tree)) 'inactive))

The command \ref gives the number of the reference, only. The command \eqref makes reference with parentheses. The code now works with \ref and as well with \eqref. I’m not a user of Scheme and do not know this language, I made an analogy only.

I think, that it better to implement this code in TeXmacs itself.

3 Likes

(this post came out longer than what I thought it would )

In Scheme a function call is expressed as a list

(f a b c)

is the function f applied to the arguments a b and c.
a b and c can also be expressions, that Scheme needs to evaluate, and they are generally made in the same way:
either a function call that starts with a parenthesis and the name of the function, followed by arguments
or so-called “atoms”, i.e. elementary data, which are numbers, strings or symbols (more on symbols later).
Scheme then proceeds by substituting inside the parentheses the value of each expression in place of the expression, then evaluates the expression that results out of this, till it has evaluated everything up to the outer parentheses.

(or a b c ...) is the “or” statement that exists in every language (without entering into details that are not essential here), so you with your code you are adding a new clause to the or (a new case, which if true will make the whole expression true). and is “and” :slight_smile:

Both “or” and “and” are expressed with the operator first, like all Scheme functions (e.g. to do 1+1 in Scheme you must do (+ 1 1)).

The apostrophe before the words “eqref” and “inactive” tells Scheme not to evaluate those expressions, but to repeat them. So the result of the Scheme code 'eqref is the symbol eqref, and the result of 'inactive is the symbol inactive.
TeXmacs recognizes both symbols as part of its syntax.

The point of defining parts of trees with a symbol instead than with a string (e.g eqref instead of "eqref") is that by the way strings and symbols are defined it is quicker to check that two symbols are equal than to check that two strings are equal; I have a vague understanding of why this is the case, but so vague that I will not try to write it down … perhaps someone else will be able to explain it (it depends on how strings and symbols are saved in the computer’s memory as far as I understood).

With this I have not defined what is a symbol :-). I will do it when I will understand it :smirk:

Forward with the code.
I did not investigate what tree-outer and focus-tree do but I guessed it: (tree-outer t) returns the tree of which t is a branch. (focus-tree) returns the current focus :slight_smile:, which is determined by the cursor (just guesses, but in this code they worked).

I also guessed that tree-is? checks the first element of the tree (first argument) against the second argument. So (tree-is? (focus-tree) 'eqref) is the function tree-is? applied to the two arguments (focus-tree) and 'eqref.

Putting together a few pieces:
(tree-is? (focus-tree) 'eqref)

  • we have to evaluate the function tree-is? with the arguments (focus-tree) and 'eqref
  • as a first step we evaluate the arguments
  • (focus-tree) will give as a result a list (which represents the tree at focus, let us not enter into this), let us call it focus-list for our example
  • 'eqref evaluates to the symbol eqref, which Scheme knows how to handle, let us call it #eqref in this example to remind ourselves that it is an expression which is already evaluated and it gave a symbol as a result of the evaluation (regardless of whether this notation has already another meaning in Scheme, which I do not know)
  • now Scheme evaluates (tree-is? focus-list #eqref), and substitutes the result of the evaluation in its place

And so on, till the outer parentheses.

1 Like

Thank you for your explanation. I see that scheme is a very specific language. I have very little experience in Basic (student time) and Python (just for fun). It is difficult to make something for Texmacs without community.
I made code using an analogy in another post How do I change hotkeys?.

Perhaps you could like the online book by Dorai Sitaram (https://ds26gte.github.io/tyscheme/index.html) could interest you.
The first 6 chapters are the fundamental things, then chapter 7 (I/O), 8 (macros, of which I know very little and they are quite different from the ones of Common Lisp I read). Of the other chapters 13 (the so-called continuations) is still a general topic (I know almost nothing about this too, never had the occasion to use them, I know they are jumps, more powerful than the jumps of other languages (do not know why). The other chapters seem to me explanations on implementations of programming techniques.

I liked also Yet Another Scheme Tutorial (http://www.shido.info/lisp/idx_scm_e.html).

As far as I understand, the concepts to learn for an elementary grasp of Scheme (as a functional language) are

  • The substitution model for computation (I described it in the previous post)
  • Variable binding, that in a functional language is permanent—if I write (define x 1), x will have the value 1 for all the computation. Then there is the procedure set! that changes the value of x :smirk: but it is conceptually outside the domain of the functional language
  • Mapping. This is explained in the websites; I read (do not recall where) that once you know mapping, you will think that every language should implement it … and I agree.
  • Connected with mapping, passing functions as arguments to other functions. I map a function over a list to obtain an output list, so I pass to the map function both the function and the list. Another example: I have a procedure to find zeros of a function with the bisection method, and I pass to this procedure the function of which I want to find the zeros)
  • Recursion, that you have to use instead of looping (in fact in looping you change the value of the loop variable, and in functional programming bindings are permanent)

One advantage of functional programming that I see after having a bit of experience is that programs are easier to test than the ones written with imperative programming. The same input to a procedure should always give the same output (so-called “referential transparency”), and this is not true for programs written with other kinds of programming, because the behaviour of the procedure could depend on variables that you do not pass to the procedure through its interface.
And of course … one can use programming constructs outside the “functional” domain in Scheme too :smirk: (the procedure set! is imperative for example)

Step by step the community will grow, the forum, the mailing list and the blog all help to make it grow.

1 Like

Here is another attempt at something useful :slight_smile: It’s based on @mgubi’s suggestion on the mailing list to use balloons.

With this you can define a shortcut to show a list of existing labels in a pop-up when you are editing a reference or label

(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?))

(tm-define (search-doc-labels t)
  "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 (label-balloon)
  (let* ((ls (search-doc-labels (buffer-tree)))
         (ll (map (lambda (l) (tree->string (tm-ref l 0))) ls)))
    (display-balloon (cursor-tree) `(document ,@ll) "auto" "auto" "keyboard")
))

(kbd-map
(:require
       (and (inside? 'inactive)
            (or
             (reference-context? (focus-tree))
             (label-context? (focus-tree)))))
   ("C-F8" (label-balloon))
)

I have to say I’m enjoying this little collaboration. It’s a great learning experience :slight_smile:

I’m too. Could you please explain how to use this code?