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

Semantically kill/yank citations between formats #635

Open
Hugo-Heagren opened this issue Jun 14, 2022 · 7 comments
Open

Semantically kill/yank citations between formats #635

Hugo-Heagren opened this issue Jun 14, 2022 · 7 comments
Labels
enhancement New feature or request

Comments

@Hugo-Heagren
Copy link
Contributor

Is your feature request related to a problem? Please describe.

I plan essays and write notes in org mode, and use org mode's citation syntax to plan my references.

But then I write in LaTeX. I have an org plan buffer open on the left, and my prose on the right. At the moment I have to manually look at the left-hand citation, and write out (or use citar to insert) the same citation again, in a different format.

Describe the solution you'd like

Tools like citar help a lot, but it would be great if I could just copy my citation from org mode (maybe with a citar command) and paste it into the LaTeX buffer as LaTeX code. A sort of semantic copy/paste.

Of course, citar handles many different formats, so ideally this should just happen automagically (just like insertion does) -- you yank and the yanked text just looks like it should, in any buffer (including those not supported, where a simple text string is inserted).

Describe alternatives you've considered

Implementing a janky solution in my init file; processing manually as above.

Additional context

This could be implemented as part of citar-copy-reference, by attaching yank-handler and citar-keys-entries properties to the text (see yank's docstring). The yank-handler function would check if we're in a buffer which citar can handle (tex, org mode, markdown etc.). If not, insert the text as-is. If so, call citar-major-mode-function with the value of the keys-entries property. (there are other details to work out, like how to undo this, but it's a start).

I would happy to try implementing this.

@Hugo-Heagren Hugo-Heagren added the enhancement New feature or request label Jun 14, 2022
@bdarcus
Copy link
Contributor

bdarcus commented Jun 14, 2022

Interesting idea.

... it would be great if I could just copy my citation from org mode (maybe with a citar command) and paste it into the LaTeX buffer as LaTeX code. A sort of semantic copy/paste.

I wonder how common this use case is?

Don't most users tend to use one major for authoring documents with citations?

That's the only real concern I have; not really an objection.

So it probably depends on what the implementation looks like; whether there's any downside to it.

This could be implemented as part of citar-copy-reference, by attaching yank-handler and citar-keys-entries properties to the text (see yank's docstring).

Two things here:

  1. wouldn't it be a citar-copy-citation? citar-org actually has such a function, and some related ones for modifying citations in the buffer (see latex,markdown: Add functions to shift references #385).
  2. note the breaking changes we're working on in New caching and formatting functionality #634. That will change the API to use citekeys.

PS - I was also playing with this idea, which is related (though I need to remind myself we support CSL JSON also).

(defun citar-export-cited-references (keys)
  "Export a BibTeX file of references for KEYS cited in buffer."
  (let* ((fn (citar--get-major-mode-function 'list-keys))
         (keys (funcall fn))
         (type (char-to-string
           (read-char-choice
            "Export file as [b]ibtex or [r]eference? " '(?b ?r)))))
    (with-temp-buffer
      (if (equal type "r")
          (citar-format-reference keys)
        (citar-insert-bibtex keys)))
  (message (concat "Exported ... with " (length keys) " references"))))

@Hugo-Heagren
Copy link
Contributor Author

Hugo-Heagren commented Jun 14, 2022

That's the only real concern I have; not really an objection.

So it probably depends on what the implementation looks like; whether there's any downside to it.

Fair point. I can imagine that some users might also prefer the simple text copy/yank. Perhaps the 'semantic' behaviour should be toggle-able with a custom option? Something like citar-use-mode-aware-yank. The yank handler could just behave like insert if this option was nil.

citar-copy-citation

This sounds like it makes sense, but I can't find any references to this function anywhere? Have I misunderstood and you're suggesting this as a name for the function?

If so, I'm not sure. For one, I think it might add mental overhead to have two different copying functions. The user option above would allow control of whether to use this functionality generally, if people want it (which might be a motivation for having separate functions). Secondly, embedding the semantic copying behaviour in citar-copy-reference means that yanking will Just Work in any buffer. If in an org, markdown or latex buffer, you get a correctly formated markup citation, if anything else, you get a textual reference string. The whole point is that you can copy one thing, in the same way in any situation, and it will paste in properly wherever it goes. Pulling apart functions to copy the citation and the textual reference would stop that happening.

note the breaking changes we're working on

Ahh. Well, I was only raising an idea, and it would be quite a while until I had time to look into anyway, so I might wait for that PR to stabilise.

@bdarcus
Copy link
Contributor

bdarcus commented Jun 14, 2022

This sounds like it makes sense, but I can't find any references to this function anywhere? Have I misunderstood and you're suggesting this as a name for the function?

Yeah, I was suggesting the possibility of one or more new major-mode functions.

@aikrahguzar
Copy link
Contributor

Yeah, I was suggesting the possibility of one or more new major-mode functions.

Why does it need a new major mode function? To me it seems like on one side we need citation-at-point to extract the keys and on the other side insert-citation. Copying part of the operation will likely need a new command but pasting should be doable as normal using a yank-handler property on the keys.

The only thing missing is citation command but doesn't seem like it is doable using an addition to major-mode-functions since it needs information from two major-modes and seems something that is hopeless to do in general. I think the best thing to do is to as for a normal citation and either a default cite command or prompt for one.

@bdarcus
Copy link
Contributor

bdarcus commented Jun 16, 2022

I think the best thing to do is to as for a normal citation and either a default cite command or prompt for one.

Can you imagine an elegant UX for that?

If most users only copy and paste within the same document, or major mode, we wouldn't want to both them to confirm that.

Is it possible to prompt if the major mode changes?

BTW, just as a reminder, we have this org keymap, which is attached to citations.

key             binding
---             -------

C-c             Prefix Command
ESC             Prefix Command
S-<left>        citar-org-shift-reference-left
S-<right>       citar-org-shift-reference-right
<mouse-1>       org-open-at-point

M-p             citar-org-update-pre-suffix

C-c C-x         Prefix Command

C-c C-x k       citar-org-kill-citation
C-c C-x DEL     citar-org-delete-citation

... and then this is the embark keymap for citations:

key             binding
---             -------

RET             citar-run-default-action
e               citar-open-entry
f               citar-open-library-file
i               citar-insert-edit
l               citar-open-link
n               citar-open-notes
o               citar-open
r               citar-copy-reference

@aikrahguzar
Copy link
Contributor

Can you imagine an elegant UX for that?

If most users only copy and paste within the same document, or major mode, we wouldn't want to both them to confirm that.

I think copy and pasting within the same mode is an editing operation and I would prefer to use something that is part of normal editing experience of a mode. In latex for example I would use evil-tex-a-command text operator to do this.

But ignoring that, this doesn't seem too difficult. From the documentation of yank

The value of a yank-handler property must be a list of one to four
elements, of the form (FUNCTION PARAM NOEXCLUDE UNDO).
FUNCTION, if non-nil, should be a function of one argument (the
 object to insert); FUNCTION is called instead of insert.
PARAM, if present and non-nil, is passed to FUNCTION (to be handled
 in whatever way is appropriate; e.g. if FUNCTION is yank-rectangle,
 PARAM may be a list of strings to insert as a rectangle)

So the major mode from which the citation was copied can be used as the PARAM and then compared against the major-mode of the target buffer.

If someone on a recent enough emacs has a creative idea of how to detect when a string is a citation, they can even use kill-transform-function to do this propertization automatically but it definitely feels something more suitable in a config than a package.

@Hugo-Heagren
Copy link
Contributor Author

So the major mode from which the citation was copied can be used as the PARAM and then compared against the major-mode of the target buffer.

Yes, this would work. I was thinking of a slightly different way: that on copying, the citation string could be parsed, and an internal mode-agnostic representation stored in a text property. Then the yank handler just calls citar--major-mode-function with that value (citar--major-mode-function being a function already built to do detection and handling of major modes). Same result, different mechanics 🤷

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

No branches or pull requests

3 participants