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: convert links #94

Open
anarcat opened this issue Feb 13, 2016 · 13 comments
Open

feature request: convert links #94

anarcat opened this issue Feb 13, 2016 · 13 comments

Comments

@anarcat
Copy link
Contributor

anarcat commented Feb 13, 2016

i often end up converting links from:

[foo](http://example.com)

to:

[foo][]

 [foo]: http://example.com

The rationale is that writing the former is more natural, but looks more messy, so i start by doing that but often end up converting to the latter because it formats better.

I ended up recording this awful keyboard macro to do this more or less automatically:

C-s         ;; isearch-forward
](          ;; self-insert-command * 2
<left>          ;; left-char
C-SPC           ;; set-mark-command
C-r         ;; isearch-backward
[           ;; self-insert-command
M-w         ;; kill-ring-save
M-C-s           ;; isearch-forward-regexp
C-q         ;; quoted-insert
2*LFD           ;; electric-newline-and-maybe-indent
<left>          ;; left-char
<right>         ;; right-char
C-y         ;; yank
RET         ;; markdown-enter-key
<left>          ;; left-char
:           ;; self-insert-command
SPC         ;; self-insert-command
C-r         ;; isearch-backward
C-y         ;; yank
C-r         ;; isearch-backward
10*<right>      ;; right-char
10*<left>       ;; left-char
<right>         ;; right-char
C-s         ;; isearch-forward
](          ;; self-insert-command * 2
<left>          ;; left-char
<deletechar>        ;; delete-forward-char
[]          ;; self-insert-command * 2
C-SPC           ;; set-mark-command
C-s         ;; isearch-forward
)           ;; self-insert-command
<left>          ;; left-char
C-w         ;; kill-region
<deletechar>        ;; delete-forward-char
C-u C-SPC       ;; set-mark-command
C-u C-SPC       ;; set-mark-command
C-u C-SPC       ;; set-mark-command
C-y         ;; yank
<home>          ;; move-beginning-of-line
SPC         ;; self-insert-command
C-u C-SPC       ;; set-mark-command
C-u C-SPC       ;; set-mark-command
C-u C-SPC       ;; set-mark-command
M-q         ;; fill-paragraph

As a lisp expression:

;; horrible way of converting [foo](link) to [foo][] [foo]: link
(fset 'md-convert-link
   [?\C-s ?\] ?\( left ?\C-  ?\C-r ?\[ ?\M-w ?\C-\M-s ?\C-q ?\C-j ?\C-j left right ?\C-y ?\C-m left ?: ?  ?\C-r ?\C-y ?\C-r right ?\C-s ?\] ?\( left deletechar ?\[ ?\] ?\C-  ?\C-s ?\) left ?\C-w deletechar ?\C-u ?\C-  ?\C-u ?\C-  ?\C-u ?\C-  ?\C-y home ?  ?\C-u ?\C-  ?\C-u ?\C-  ?\C-u ?\C-  ?\M-q])

yes, this is horrible. i started writing this as a function but then got tired and wondered if anyone else worked on this. here's how far i got so far:

(defun anarcat/markdown-convert-link ()
  (interactive)
  (search-forward "](")
  (search-forward ")")
  (kill-region) ;; the link
  ;; need to kill the parens too
  (save-excursion
    (search-forward "\n\n")
    (yank)
    ;; need to save point here to come back
    )
  (search-backwards "]")
  (search-backwards "["]
  (kill-ring-save) ;; the text
  ;; now go back to the point and format the text and all
  )

i don't like it one bit so far... anyone else fixed up something like this?

@jrblevin
Copy link
Owner

This is an existing feature: Place the point anywhere in the inline link and press C-c C-a r (as if you were inserting a reference link) and the link will be converted to a reference style link.

@vyp
Copy link

vyp commented Feb 13, 2016

btw, i don't know what markdown you are using, but with pandoc you can just do [foo] instead of [foo][].

@anarcat
Copy link
Contributor Author

anarcat commented Feb 13, 2016

damn, i was offline and ended up rewriting this thing twice... here's what i ended up with:

(defun anarcat/markdown-convert-link ()
  "convert a [text](link) link format into [text][] ... [text]:
link

allowing search-backwards (say with a prefix) could also be
interesting.

This is discussed in
https://github.com/jrblevin/markdown-mode/issues/94 and should be
eventually merged upstream once it is acceptable elisp.
"
  (interactive)
  ;; find unconverted link
  ;; we have 3 groups in here:
  ;; 1. text (without brakets)
  ;; 2. link (with parens, to replace it with replace-match)
  ;; 3. link (without parens, to extract it to insert it later)
  (re-search-forward "\\[\\([^]]*\\)]\\((\\([^)]*\\))\\)")
  (let ((text (match-string 1))
        (link (match-string 3)))
    ;; remove the link and replace with brakets
    ;; link is the "2" below, and replace only that
    (replace-match "[]" nil nil nil 2)
    ;; go at the end of the paragraph and add stuff there
    (save-excursion
      (search-forward "\n\n")
      ;; insert the link reference
      (insert (format " [%s]: %s\n\n" text link))
      ;; XXX: we insert two newlines to avoid breaking the paragraph
      ;; break, but that makes too many spaces if we insert many links
      ;; like this. not sure how to fix this.
      )
    )
  )

also, C-c C-a r does not convert a link here: it just adds a new one. i am using markdown-mode.el 2.0 from Debian jessie, looking at the current code it seems this is a new feature from 2.1... grml.

oh well, i gues it's time to load a new version from ELPA. :)

@vyp as for the markdown dialect, i'm writing for ikiwiki, using the default markdown processor (which is not pandoc).

@anarcat
Copy link
Contributor Author

anarcat commented Feb 13, 2016

markdown-mode is still at version 2.0 in marmalade, it seems. MELPA has a snapshot from 2016, which works, so I guess i just wasted time re-learning elisp programming. which was actually nice. :)

thanks!

@anarcat anarcat closed this as completed Feb 13, 2016
@anarcat
Copy link
Contributor Author

anarcat commented Feb 13, 2016

ah - one thing my function does a little better is that it puts the link at the end of the paragraph instead of at the end of file, which I like because it makes the plain text more readable: you don't have to jump to the end of file to follow links by hand.

@jrblevin
Copy link
Owner

You can customize the location for inserting reference definitions by setting markdown-reference-location.

@anarcat
Copy link
Contributor Author

anarcat commented Feb 13, 2016

cool, that's what i was looking for, thanks!

@anarcat
Copy link
Contributor Author

anarcat commented Sep 7, 2017

This is an existing feature: Place the point anywhere in the inline link and press C-c C-a r (as if you were inserting a reference link) and the link will be converted to a reference style link.

Is it me or did this feature disappear?

If I have a document that only has [foo](link) and I move the point to "link" then type C-c C-a r, it just prompts me for the same link info again but doesn't convert the link...

Ideas?

@anarcat anarcat reopened this Sep 7, 2017
@jrblevin
Copy link
Owner

jrblevin commented Sep 7, 2017

I combined the three old functions (for inline, reference, plain URL links) into one with the new C-c C-l command. The old commands are now aliases for it. If you remove the URL (kill it for using later), then give a reference label it will convert for you. If the ref isn't defined, one will be added and you'll be prompted for the URL (which you can then yank).

The idea is that it uses whatever information you give it to determine the link type. There are examples of other possible conversions in the documentation.

@anarcat
Copy link
Contributor Author

anarcat commented Sep 7, 2017

oh i see. sorry for not catching up on the docs and all the noise. ;) short too, i like it. i'll try to train my muscle memory back in polace - thanks!

@anarcat anarcat closed this as completed Sep 7, 2017
@jrblevin
Copy link
Owner

jrblevin commented Sep 7, 2017

It's no problem. My sense at the time was that C-c C-l would be more intuitive, but I'm considering bringing back dedicated conversion commands, as they do avoid shuffling URLs/text around.

@anarcat
Copy link
Contributor Author

anarcat commented Nov 26, 2020

If you remove the URL (kill it for using later), then give a reference label it will convert for you. If the ref isn't defined, one will be added and you'll be prompted for the URL (which you can then yank).

I understand this ticket is getting really old by now, but I keep on thinking about it every time I switch links between inline and ref. That process actually takes a long time. The actual keystrokes are:

  • C-c
  • C-l
  • alt-backspace (orc-s-left c-w)
  • RET
  • RET
  • c-y
  • RET

phew! i often end up doing a macro instead, but it's not very reliable: if a ref already exist, it kind of explodes midway...

it would still be nice to have a wrapper around this, possibly by setting a prefix argument?

similar: #565

@anarcat
Copy link
Contributor Author

anarcat commented Feb 13, 2024

i reworked my code a bit and ended up with something like this:

(defun anarcat/markdown-convert-link ()
  "Convert markdown inline links to references.

This convers a [text](link) link format into [text][] ... [text]:
linké

Allowing search-backwards (say with a prefix) could also be
interesting.

This is discussed in:

https://github.com/jrblevin/markdown-mode/issues/94

Should eventually merged upstream once it is acceptable elisp."
  (interactive)
  ;; find unconverted link
  ;; we have 3 groups in here:
  ;; 1. text (without brakets)
  ;; 2. link (with parens, to replace it with replace-match)
  ;; 3. link (without parens, to extract it to insert it later)
  (if (re-search-forward "\\[\\([^]]*\\)]\\((\\([^)]*\\))\\)" nil t)
      (let ((text (match-string 1))
            (link (match-string 3)))
        ;; remove the link and replace with brakets
        ;; link is the "2" below, and replace only that
        (replace-match "[]" nil nil nil 2)
        ;; go at the end of the paragraph and add stuff there
        (save-excursion
          (search-forward "\n\n" nil 1)
          ;; insert the link reference
          (insert (format " [%s]: %s\n\n" text link))
          ;; XXX: we insert two newlines to avoid breaking the paragraph
          ;; break, but that makes too many spaces if we insert many links
          ;; like this. not sure how to fix this.
          ))
    (message "no inline link found until end of buffer")))

would you be open a merge request to add that to markdown-mode?

@anarcat anarcat reopened this Feb 13, 2024
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

3 participants