From e8acfc7fb4a6c01d50ed121ca5ce2ed41f7b0db9 Mon Sep 17 00:00:00 2001 From: Bozhidar Batsov Date: Tue, 9 Dec 2014 19:43:24 +0200 Subject: [PATCH] Add a command for string quotes toggling to ruby-mode * progmodes/ruby-mode.el (ruby-toggle-string-quotes): New command that allows you to quickly toggle between single-quoted and double-quoted string literals. --- lisp/ChangeLog | 2 ++ lisp/progmodes/ruby-mode.el | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 5ed3e47c7d9..3ab15aab243 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -2,6 +2,8 @@ * progmodes/ruby-mode.el (auto-mode-alist): Add .rabl, Berksfile and Puppetfile. + (ruby-toggle-string-quotes): New command that allows you to quickly + toggle between single-quoted and double-quoted string literals. 2014-12-09 Eric S. Raymond diff --git a/lisp/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index 803bf579da3..225f1f62673 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -152,6 +152,7 @@ This should only be called after matching against `ruby-here-doc-beg-re'." (define-key map (kbd "M-C-p") 'ruby-beginning-of-block) (define-key map (kbd "M-C-n") 'ruby-end-of-block) (define-key map (kbd "C-c {") 'ruby-toggle-block) + (define-key map (kbd "C-c '") 'ruby-toggle-string-quotes) map) "Keymap used in Ruby mode.") @@ -164,6 +165,8 @@ This should only be called after matching against `ruby-here-doc-beg-re'." ["End of Block" ruby-end-of-block t] ["Toggle Block" ruby-toggle-block t] "--" + ["Toggle String Quotes" ruby-toggle-string-quotes t] + "--" ["Backward Sexp" ruby-backward-sexp :visible (not ruby-use-smie)] ["Backward Sexp" backward-sexp @@ -1763,6 +1766,48 @@ If the result is do-end block, it will always be multiline." (ruby-do-end-to-brace beg end))) (goto-char start)))) +(defun ruby--string-region () + "Return region for string at point." + (let ((orig-point (point)) (regex "'\\(\\(\\\\'\\)\\|[^']\\)*'\\|\"\\(\\(\\\\\"\\)\\|[^\"]\\)*\"") beg end) + (save-excursion + (goto-char (line-beginning-position)) + (while (and (re-search-forward regex (line-end-position) t) (not (and beg end))) + (let ((match-beg (match-beginning 0)) (match-end (match-end 0))) + (when (and + (> orig-point match-beg) + (< orig-point match-end)) + (setq beg match-beg) + (setq end match-end)))) + (and beg end (list beg end))))) + +(defun ruby-string-at-point-p () + "Check if cursor is at a string or not." + (ruby--string-region)) + +(defun ruby--inverse-string-quote (string-quote) + "Get the inverse string quoting for STRING-QUOTE." + (if (equal string-quote "\"") "'" "\"")) + +(defun ruby-toggle-string-quotes () + "Toggle string literal quoting between single and double." + (interactive) + (when (ruby-string-at-point-p) + (let* ((region (ruby--string-region)) + (min (nth 0 region)) + (max (nth 1 region)) + (string-quote (ruby--inverse-string-quote (buffer-substring-no-properties min (1+ min)))) + (content + (buffer-substring-no-properties (1+ min) (1- max)))) + (setq content + (if (equal string-quote "\"") + (replace-regexp-in-string "\\\\\"" "\"" (replace-regexp-in-string "\\([^\\\\]\\)'" "\\1\\\\'" content)) + (replace-regexp-in-string "\\\\\'" "'" (replace-regexp-in-string "\\([^\\\\]\\)\"" "\\1\\\\\"" content)))) + (let ((orig-point (point))) + (delete-region min max) + (insert + (format "%s%s%s" string-quote content string-quote)) + (goto-char orig-point))))) + (eval-and-compile (defconst ruby-percent-literal-beg-re "\\(%\\)[qQrswWxIi]?\\([[:punct:]]\\)" -- 2.11.4.GIT