drym-org / symex.el

An intuitive way to edit Lisp symbolic expressions ("symexes") structurally in Emacs
Other
271 stars 22 forks source link

User context handling #102

Open countvajhula opened 1 year ago

countvajhula commented 1 year ago

Summary of Changes

This is a prototype for generalized "user context" handling. The idea is that there are many elements that inform the configuration when we enter Symex state, and for many of them, it doesn't make sense to handle them explicitly in Symex. Instead, we need some kind of "glue" layer that allows users to customize the interactions with other extensions and contexts. The present PR is one possible way to implement this layer. I haven't thought through all the ramifications yet and for now it only implements the eval functionality (default binding: e) using this approach.

The first and most obvious element that informs the Symex runtime context is the major mode of the buffer. If it is ELisp, we want to employ ELisp runtime functions for evaluation, doc lookups, etc. If it is Racket, then we want to use Racket functions for these, and so on.

But there are cases where a source major mode isn't sufficient context to determine whether Symex mode is even applicable. In these cases there may be additional context that could be used, such as point being within a code block in an Org buffer (#95 ). Contradistinctively, there are cases where the major mode alone isn't enough to determine the appropriate configuration even if it suggests that Symex is applicable. For instance, if we are in an Elisp buffer but point is within a comment or a string, we would want to configure Symex differently or perhaps avoid entering Symex altogether, as we might do in a Rigpa setting, where we might prefer to skip over Symex to enter Normal state directly in Rigpa's Lisp tower.

In all of these cases, it seems we are looking for a way to infer "user context" -- distinguishing features of the user's current configuration -- that will allow us to apply the appropriate configuration in a tailored rather than one-size-fits-all way. Since this seems like a general need, it might make the most sense to have this as a separate Emacs extension. For now, this module uses the identifier prefix contextualize- to differentiate it from Symex-specific functionality that uses the prefix symex-.

Next steps

Public Domain Dedication

(Why: The freely released, copyright-free work in this repository represents an investment in a better way of doing things called attribution-based economics. Attribution-based economics is based on the simple idea that we gain more by giving more, not by holding on to things that, truly, we could only create because we, in our turn, received from others. As it turns out, an economic system based on attribution -- where those who give more are more empowered -- is significantly more efficient than capitalism while also being stable and fair (unlike capitalism, on both counts), giving it transformative power to elevate the human condition and address the problems that face us today along with a host of others that have been intractable since the beginning. You can help make this a reality by releasing your work in the same way -- freely into the public domain in the simple hope of providing value. Learn more about attribution-based economics at drym.org, tell your friends, do your part.)

countvajhula commented 1 year ago

@devcarbon-com This is an early prototype of the context handling mechanism we talked about. If you want to try writing the my-org-inside-literate-code-block-p predicate, you could use this user-context-handling branch. The predicate should return the language of the code block as a symbol, so in your example

#+begin_src emacs-lisp
(setq mouse-autoselect-window t)
#+end_src

... calling my-org-inside-literate-code-block-p when point is anywhere within the block, i.e. on line 2 here, should result in 'elisp (for some inspiration, you could look at symex-primitives-lisp.el for examples of similar predicates although most of those return booleans).

Then, once that's working, you can register the context handler using:

(setq my-org-symex-context
      (list (cons #'my-org-inside-literate-code-block-p
                  #'symex-contextualize)))
(contextualize-register-context symex-category
                                my-org-symex-context)

... and in theory, at that point, entering Symex within an Elisp literal code block should work for evaluation (e) 😸

devcarbon-com commented 1 year ago

@countvajhula Nice! I'll take a look.