xenodium / chatgpt-shell

A multi-llm Emacs shell (ChatGPT, Claude, Gemini, Ollama) + editing integrations
https://lmno.lol/alvaro
GNU General Public License v3.0
862 stars 77 forks source link

Question. How to make the shell "org-mode friendly" #140

Closed agzam closed 1 year ago

agzam commented 1 year ago

chatgpt-shell nicely can structure responses in markdown format, but I recently realized that most often I copy a response to paste it into org-mode document. I tried changing the prompt asking it to make responses in org-mode format (with source blocks), but it still uses markdown blocks. Is there a way to make it render everything in Org-mode? I know I can use chatgpt-shell--org-babel, but having it in the shell would be also great.

xenodium commented 1 year ago

ChatGPT responses don't do org very well, so I stopped trying and mostly embraced tendering markdown :) We'd have to convert the markdown responses to org. If I remember correctly, gptel.el client does this. Tried that package?

Alternatively, I wonder if we can do the conversion when copying and pasting. Have you tried something like that?

agzam commented 1 year ago

Ah... For some reason, I thought that this package actually does handle org-mode, but I couldn't find the option to turn it on. I guess I confused it with gptel, which I stopped using. chatgpt-shell is just much more versatile. I suppose I can figure out something that converts markdown to org-mode for copy-pasting. Pandoc usually does a great job. I'll post an update when I get the time to experiment. I'm going to close this for now. Thank you!

agzam commented 1 year ago

Sorry for a long delay. I didn't have a chance to fix it in my workflow. Today I bothered by it once again and I found outrageously simple and thus brilliant solution:

(defun maybe-yank-as-org (orig-fun beg end &optional type register yank-handler)
  "Advice function to convert marked region to org before yanking."
  (let ((modes '(markdown-mode chatgpt-shell-mode)))
    (if (and (not current-prefix-arg)
             (apply 'derived-mode-p modes))
        (let* ((_ (unless (executable-find "pandoc")
                    (user-error "pandoc not found")))
               (region-content (buffer-substring-no-properties beg end))
               (converted-content
                (with-temp-buffer
                  (insert region-content)
                  (shell-command-on-region
                   (point-min)
                   (point-max) "pandoc -f markdown -t org" nil t)
                  (buffer-string))))
          (kill-new converted-content)
          (message "yanked Markdown as Org"))
      (funcall orig-fun beg end type register yank-handler))))

(advice-add 'evil-yank :around #'maybe-yank-as-org)

So, now in any markdown or chatgpt-shell buffer, if I yank, it yanks it in Org-mode format. And if I want to yank it without converting, I can yank with an argument. I use evil, so I'm advising evil-yank. I'm sure it's super trivial to make it work in vanilla Emacs.

xenodium commented 1 year ago

Neat! Optionally, we may be able to avoid the advice by creating a custom yank function delegating to evil-yank and set the binding in markdown-mode and chatgpt-shell-mode.

agzam commented 1 year ago

Yes, I think that is the better and more idiomatic way and has less chance of misdirection. Also, a separate command would allow it to call from any mode, not just hard-coded list, and opens possibilities for adding conversion from other formats. I can imagine one day wanting to grab e.g., Clojure code as an Org source code block.