Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: Detect "mode" for org code blocks? #95

Open
devcarbon-com opened this issue Mar 12, 2023 · 8 comments
Open

Feature request: Detect "mode" for org code blocks? #95

devcarbon-com opened this issue Mar 12, 2023 · 8 comments

Comments

@devcarbon-com
Copy link
Collaborator

Use case: quickly tinkering in literate programming. A common case being a literate emacs config.

@countvajhula
Copy link
Collaborator

Could you give an example of what you're looking for here?

@devcarbon-com
Copy link
Collaborator Author

Sure,

Say you have a literate config with the following:

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

As-is, if I try to eval the setq, I get symex--evaluate: Symex mode: Lisp flavor not recognized!

It would be neat if Symex would detect it was in an org src-block and use the set language for evaluation.

@devcarbon-com
Copy link
Collaborator Author

Along these lines:

(when (eq major-mode `org-mode)
    (let ((element (org-element-at-point)))
      (when (eq 'src-block (org-element-type element))
        (org-element-property :language element))))

@countvajhula
Copy link
Collaborator

Ah yeah, that would be nice.

Here's one way we could do it:

We first define a general notion of cursor context awareness. This could be as simple as a (set-context category) function that checks a list of (condition, handler) pairs for the given category, where if the condition is met then the handler is called. The purpose of the "category" is to specialize the context-handling to specific cases, for instance, "symex" would be one category here which would be used by Symex users and the Symex library, where (set-context symex-context) would replace (and generalize) the current major mode Lisp flavor check that you ran into. But other libraries could use different categories so that they don't interfere with one another (so this would be a separate library and not part of Symex itself). Users could add context handlers using a function like (context-add-rule category condition handler).

For the org case and Symex, we would do:

(context-add-rule symex-context #'my-org-inside-literate-code-block symex-set-language-context)

We could implement context-add-rule so that the handler is called with the return value of the condition predicate. That way, here, myorg-inside-literate-code-block could return "python" (i.e. it would need to determine that by parsing the containing org text in any way that works) and that would become the input to setting the language context.

There could be another helper package called cursor-context-predicates which includes a bunch of standard predicates (detecting literate org code blocks, detecting comment blocks, or whatever else) so that users wouldn't need to write ELisp for standard cases.

For the case of comments, we could register a comment detection predicate and call set-context in the high level symex motions (h and l) so that encountering a comment would trigger the use of a different "symex-comment-mode" or something like that, which would allow going "down" to the base of the comment, and "up" into the body of the comment.

This could also be used in Rigpa to set the appropriate editing ensemble (i.e. data structure like a tower containing editing states like Evil states) based on whether we're in a comment or not, which is a feature I've been missing for a while.

If you think this is a good approach, you could try writing the my-org-inside-literal-code-block function -- it should return something like "elisp" or "python" if it is in a literal code block, and nil otherwise. In the meantime, I'll write an early prototype for the context handling as a distinct Symex module, which just refactors the existing major mode checks to use the context-setting pattern. Then we should be able to extend it to support the other cases here with predicates for each case, like the org-literal-code-block predicate.

@devcarbon-com
Copy link
Collaborator Author

@countvajhula Neat!

On a side note I'm curious, is the plan for Rigpa to also be evil independent at some point?

@countvajhula
Copy link
Collaborator

Do you mean from the perspective of users or just as a dependency? As far as I know, both Rigpa and Symex are independent of whether users are Evil users or not. I haven't reviewed this in detail recently so it's likely that the interface with Evil can be further minimized, but from the perspective of users it's just an implementation detail that should not affect them. If it does affect users by revealing the inner Evil workings or expecting Evil familiarity in some way, then I would consider it a bug (please report any such case! 🙂 ).

@countvajhula
Copy link
Collaborator

Regarding whether there is a plan to not even use evil as a dependency (for either Rigpa or Symex), yes, I think that would make sense in the long term since Evil is much more heavyweight than our actual needs. But in the near term a higher priority is countvajhula/rigpa#10 -- that is, writing a modal interface provider that, unlike evil, isn't tied to a specific buffer, and unlike hydra, is specifically designed to be lightweight modal interface. This would probably replace hydra-backed modes (like View, Window, Buffer) rather than affect evil-backed modes (like Line, Word, Symex), for now. But it could potentially replace evil-backed modes too. I think a great proof-of-concept would demonstrate its use as View Mode (for example) without some of the hacks that are currently necessary to accommodate hydra exits (i.e. currently we need to advertise that the hydra is "possibly about to exit" beforehand, and then later check whether it did in fact exit via a different hook -- see "portend-exit" and "signal-exit" in the rigpa code if you're curious -- but understanding that is beside the point since we would like to avoid that whole way of doing it!). Of course, we would still support hydra for the purposes of abstraction, but all built-in Rigpa modes would be transitioned to the new provider (or remain on evil).

@devcarbon-com
Copy link
Collaborator Author

I haven't dug into this code specifically yet, but boon-core sounds like it might be good inspiration if nothing else for a rigpa mode provider: https://github.com/jyp/boon#comparison-with-other-modal-layers-for-emacs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants