Quel raccourci clavier utiliser pour naviguer hors d'une chaîne

9

Quand je suis au milieu d'une chaîne looooong, comme ce qui suit

(setq Emacs-beta "Which keyboard shortcut to use for navigating out of a string")

Puis-je en sauter juste avant le premier "(après Emacs-beta) avec un raccourci?

Dieter.Wilhelm
la source
Pas vraiment une réponse C-r " C-b.
Nom du

Réponses:

12

Emacs 25 ou plus récent

Vous voulez C-M-uqui exécute la commande backward-up-list.

Reculez d'un niveau de parenthèses. Cette commande fonctionnera également sur d'autres expressions de type parenthèses définies par le mode de langue actuel.

Si ESCAPE-STRINGS n'est pas nul (comme c'est interactif), sortez également des chaînes englobantes.

nounou
la source
Vous devez mentionner que c'est seulement 25.
abo-abo
@ abo-abo Ce n'est pas le cas: je viens de le tester en 24.5.1. Je ne sais pas quand il a été ajouté, mais si quelqu'un peut le découvrir, je le modifierai.
nanny
@ abo-abo Oups, je suis désolé, vous avez raison.
nounou
Je suis avec Emacs-24.5 -Qune chaîne, mais je reçois avec CMu: up-list: Scan error: "Unbalanced parentheses"?
Dieter.Wilhelm
1
@ Dieter.Wilhelm Right: comme vous pouvez le voir par mon commentaire et mon montage, je me suis trompé. Cela ne fonctionnera que dans Emacs 25 ou plus récent.
nounou
3

C'est faisable comme ça:

(defun exit-string-backwards ()
  (interactive)
  (goto-char (nth 8 (syntax-ppss))))

En mode lispy , appuyer sur [vous amènera au début de la liste contenant, en quittant n'importe quelle chaîne. Une fois que vous êtes au début de la liste, vous pouvez accéder facilement à d'autres parties, par exemple, pour atteindre la fin de la Emacs-betapresse 2m.

abo-abo
la source
1

Il s'agit en fait d'une question de programmation Emacs Lisp très intéressante. Nous pouvons conserver les caractères avant ou arrière jusqu'à ce que nous trouvions que le caractère sous le curseur ne fait pas partie de la chaîne.

Vous pouvez utiliser le visage de la police pour décider si le caractère se trouve à l'intérieur de la chaîne. C'est un excellent truc que j'ai appris de flyspell. En théorie, ce n'est pas parfait, mais dans le monde réel, il fonctionne avec presque tous les principaux modes de langage de programmation sur Emacs23, Emacs24, Emacs25 .

Voici le code complet:

(defun font-face-is-similar (f1 f2)
  (let (rlt)
    ;; (message "f1=%s f2=%s" f1 f2)
    ;; in emacs-lisp-mode, the '^' from "^abde" has list of faces:
    ;;   (font-lock-negation-char-face font-lock-string-face)
    (if (listp f1) (setq f1 (nth 1 f1)))
    (if (listp f2) (setq f2 (nth 1 f2)))

    (if (eq f1 f2) (setq rlt t)
      ;; C++ comment has different font face for limit and content
      ;; f1 or f2 could be a function object because of rainbow mode
      (if (and (string-match "-comment-" (format "%s" f1)) (string-match "-comment-" (format "%s" f2)))
          (setq rlt t)))
    rlt))

(defun goto-edge-by-comparing-font-face (&optional step)
"Goto either the begin or end of string/comment/whatever.
If step is -1, go backward."
  (interactive "P")
  (let ((cf (get-text-property (point) 'face))
        (p (point))
        rlt
        found
        end)
    (unless step (setq step 1)) ;default value
    (setq end (if (> step 0) (point-max) (point-min)))
    (while (and (not found) (not (= end p)))
      (if (not (font-face-is-similar (get-text-property p 'face) cf))
          (setq found t)
        (setq p (+ p step))))
    (if found (setq rlt (- p step))
      (setq rlt p))
    ;; (message "rlt=%s found=%s" rlt found)
    (goto-char rlt)))

Usage:

  • (goto-edge-by-comparing-font-face 1)aller au bord droit, (goto-edge-by-comparing-font-face -1)aller au bord gauche
  • il ne dépend d'aucun mode majeur spécifique, vous pouvez l'utiliser n'importe où dans n'importe quelle langue

backward-up-listn'est pas très fiable du point de vue de l'utilisateur car il est conçu comme une commande générique basée sur scan-sexps. Par exemple, pour le code if (true) { return 'hello world'; }en mode js2, il déplacera le focus sur le {caractère au lieu du premier caractère de guillemet simple. Pour le code printf("hello world")en mode c ++, cela ne fonctionnera pas. J'ai testé avec Emacs 24.5

chen bin
la source
Cela va au bord droit, l'OP a demandé au point avant le bord gauche. Que faire si le mode lisp n'est pas activé?
Nom du
(goto-edge-by-compare-font-face -1) allez sur le bord gauche, backward-charou forward-charsi vous déplacez le curseur hors du bord.
chen bin
Ok, bonne idée, mais si vous l'exécutez lorsque le mode texte est activé, les points vont après ). Ainsi, selon les modes, votre code a des comportements différents.
Nom du
Il utilise le même algorithme que flyspell. Il prend donc en charge tous les principaux modes de prise en charge de flyspell
chen bin
0

Voici une autre façon (que j'ai tendance à utiliser plus) juste pour la variété. La solution n'est pas spécifique aux chaînes mais elle fonctionne également pour ce cas d'utilisation.

  • Installer iy-go-to-char(également disponible sur Melpa).
  • Liez iy-go-to-char-backwardet iy-go-to-charà vos fixations préférées. Pour cette explication, disons que vous êtes lié iy-go-to-char-backwardà C-c C-,et iy-go-to-charà C-c C-..
  • Maintenant, si vous êtes à l'intérieur de la chaîne, vous appelez iy-go-to-char-backwardet tapez ".

    Cela ressemblerait C-c C-, ". Si vous avez iy-go-to-char-continue-when-repeatingdéfini sur t(par défaut), "une nouvelle pression vous amènera à une "occurrence char avant, et ainsi de suite.

  • Si vous êtes à l'intérieur de la chaîne et si vous voulez maintenant aller à la fin de la chaîne, vous appelez iy-go-to-charet tapez ".

    Cela ressemblerait C-c C-. ". Si vous avez iy-go-to-char-continue-when-repeatingdéfini sur t(par défaut), "une nouvelle pression vous amènera à l' "occurrence de caractère suivante.

Kaushal Modi
la source