From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Theodor Thornhill via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#60128: 30.0.50; [PATCH]: Add treesit-transpose-sexps Date: Fri, 16 Dec 2022 21:04:28 +0100 Message-ID: <87a63nru7n.fsf@thornhill.no> Reply-To: Theodor Thornhill Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="37546"; mail-complaints-to="usenet@ciao.gmane.io" Cc: casouri@gmail.com, Stefan Monnier To: 60128@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Fri Dec 16 21:05:30 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1p6GxV-0009UA-72 for geb-bug-gnu-emacs@m.gmane-mx.org; Fri, 16 Dec 2022 21:05:29 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p6GxF-0006NQ-T4; Fri, 16 Dec 2022 15:05:13 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p6Gx6-0006Mg-Jr for bug-gnu-emacs@gnu.org; Fri, 16 Dec 2022 15:05:12 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1p6Gx5-0002Ym-Ly for bug-gnu-emacs@gnu.org; Fri, 16 Dec 2022 15:05:03 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1p6Gx4-0006DD-0h; Fri, 16 Dec 2022 15:05:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Theodor Thornhill Original-Sender: "Debbugs-submit" Resent-CC: casouri@gmail.com, monnier@iro.umontreal.ca, bug-gnu-emacs@gnu.org Resent-Date: Fri, 16 Dec 2022 20:05:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 60128 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org X-Debbugs-Original-Xcc: casouri@gmail.com, Stefan Monnier Original-Received: via spool by submit@debbugs.gnu.org id=B.167122109723868 (code B ref -1); Fri, 16 Dec 2022 20:05:01 +0000 Original-Received: (at submit) by debbugs.gnu.org; 16 Dec 2022 20:04:57 +0000 Original-Received: from localhost ([127.0.0.1]:51301 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1p6Gwz-0006Cu-3w for submit@debbugs.gnu.org; Fri, 16 Dec 2022 15:04:57 -0500 Original-Received: from lists.gnu.org ([209.51.188.17]:48416) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1p6Gwx-0006Cm-Ff for submit@debbugs.gnu.org; Fri, 16 Dec 2022 15:04:56 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p6Gwj-0006Ja-Km for bug-gnu-emacs@gnu.org; Fri, 16 Dec 2022 15:04:51 -0500 Original-Received: from out2.migadu.com ([2001:41d0:2:aacc::]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p6Gwf-0002PV-B6 for bug-gnu-emacs@gnu.org; Fri, 16 Dec 2022 15:04:39 -0500 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=thornhill.no; s=key1; t=1671221070; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type; bh=nTkYw7zr4gD7A0I/udfBGN9G28I6Cpo7FxzKGWHn8h4=; b=A0D77jflpOjm/uKQ/rvO40Tc/cfe+VDFnhPOz9M2RduLIm7pNRr7Gdvy2byHyIKikfFxHe +2g0toAlx0w8izz01WxHUELF1s1QGNs9ryYvGN8IK3J5uF+6AWIriGNgYib1oT4039110l 7Du/KXCl82LRds9xCvqFmyXPfuSBOUnnATm76rYRWy80lST9gJd/F0Vq2gkNyKNLkQ2V34 mjjOuTnMLdTGEJZ+iqI41S5BNC7IGzl4MRhrpz9nfXhkvVwDTld/Gcpgz5q4HAt5b5pmHp +RwOxDPb4vmNFuNReNljbyfS6KKsP/n2kFIxB/NSjltGXsHDalVHXxcX3zO74A== X-Migadu-Flow: FLOW_OUT Received-SPF: pass client-ip=2001:41d0:2:aacc::; envelope-from=theo@thornhill.no; helo=out2.migadu.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:251240 Archived-At: --=-=-= Content-Type: text/plain Hi there! Attached is a patch that enables transpose-sexps for tree-sitter enabled modes. This function will swap the node _before_ node-at-point with the node _after_, so it would do something like: foo a|nd bar => bar and foo| or foo(a + 4,| y + c * b, b, d); => foo(y + c * b, a + 4|, b, d); It will _not_ try to swap things that are not siblings. I think that makes sense in the case of non-lisp languages, since _most_ places you can transpose-sexps you will end up with broken code. What do you think? I think this makes sense on the master branch, not release. Theo --=-=-= Content-Type: text/x-diff Content-Disposition: attachment; filename=0001-Add-treesit-transpose-sexps.patch >From 9c2bf9869fbd76b81c21f13a02d70e85eec736be Mon Sep 17 00:00:00 2001 From: Theodor Thornhill Date: Thu, 15 Dec 2022 21:22:13 +0100 Subject: [PATCH] Add treesit-transpose-sexps We don't really need to rely on forward-sexp to define what to transpose. In tree-sitter we can consider siblings as "balanced expressions", and swap them without doing any movement to calculate where the siblings in question are. * lisp/simple.el: Add requires for treesit. * lisp/simple.el (transpose-sexps): If tree-sitter is available, use treesit-transpose-sexps as the 'special' function. (transpose-subr): Just use tree-sitter when available. * lisp/treesit.el (treesit-transpose-sexps): New function. --- lisp/simple.el | 67 ++++++++++++++++++++++++++----------------------- lisp/treesit.el | 16 ++++++++++++ 2 files changed, 52 insertions(+), 31 deletions(-) diff --git a/lisp/simple.el b/lisp/simple.el index dcc2242e49..15f7381f06 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -28,10 +28,12 @@ ;;; Code: -(eval-when-compile (require 'cl-lib)) +(eval-when-compile (require 'cl-lib) + (require 'treesit)) (declare-function widget-convert "wid-edit" (type &rest args)) (declare-function shell-mode "shell" ()) +(declare-function treesit-parser-list "treesit.c") ;;; From compile.el (defvar compilation-current-error) @@ -8453,36 +8455,37 @@ transpose-sexps (transpose-sexps arg nil) (scan-error (user-error "Not between two complete sexps"))) (transpose-subr - (lambda (arg) - ;; Here we should try to simulate the behavior of - ;; (cons (progn (forward-sexp x) (point)) - ;; (progn (forward-sexp (- x)) (point))) - ;; Except that we don't want to rely on the second forward-sexp - ;; putting us back to where we want to be, since forward-sexp-function - ;; might do funny things like infix-precedence. - (if (if (> arg 0) - (looking-at "\\sw\\|\\s_") - (and (not (bobp)) - (save-excursion - (forward-char -1) - (looking-at "\\sw\\|\\s_")))) - ;; Jumping over a symbol. We might be inside it, mind you. - (progn (funcall (if (> arg 0) - 'skip-syntax-backward 'skip-syntax-forward) - "w_") - (cons (save-excursion (forward-sexp arg) (point)) (point))) - ;; Otherwise, we're between sexps. Take a step back before jumping - ;; to make sure we'll obey the same precedence no matter which - ;; direction we're going. - (funcall (if (> arg 0) 'skip-syntax-backward 'skip-syntax-forward) - " .") - (cons (save-excursion (forward-sexp arg) (point)) - (progn (while (or (forward-comment (if (> arg 0) 1 -1)) - (not (zerop (funcall (if (> arg 0) - 'skip-syntax-forward - 'skip-syntax-backward) - "."))))) - (point))))) + (if (treesit-parser-list) #'treesit-transpose-sexps + (lambda (arg) + ;; Here we should try to simulate the behavior of + ;; (cons (progn (forward-sexp x) (point)) + ;; (progn (forward-sexp (- x)) (point))) + ;; Except that we don't want to rely on the second forward-sexp + ;; putting us back to where we want to be, since forward-sexp-function + ;; might do funny things like infix-precedence. + (if (if (> arg 0) + (looking-at "\\sw\\|\\s_") + (and (not (bobp)) + (save-excursion + (forward-char -1) + (looking-at "\\sw\\|\\s_")))) + ;; Jumping over a symbol. We might be inside it, mind you. + (progn (funcall (if (> arg 0) + 'skip-syntax-backward 'skip-syntax-forward) + "w_") + (cons (save-excursion (forward-sexp arg) (point)) (point))) + ;; Otherwise, we're between sexps. Take a step back before jumping + ;; to make sure we'll obey the same precedence no matter which + ;; direction we're going. + (funcall (if (> arg 0) 'skip-syntax-backward 'skip-syntax-forward) + " .") + (cons (save-excursion (forward-sexp arg) (point)) + (progn (while (or (forward-comment (if (> arg 0) 1 -1)) + (not (zerop (funcall (if (> arg 0) + 'skip-syntax-forward + 'skip-syntax-backward) + "."))))) + (point)))))) arg 'special))) (defun transpose-lines (arg) @@ -8521,6 +8524,8 @@ transpose-subr (progn (funcall mover (- x)) (point)))))) pos1 pos2) (cond + ((treesit-parser-list) + (apply #'transpose-subr-1 (funcall aux arg))) ((= arg 0) (save-excursion (setq pos1 (funcall aux 1)) diff --git a/lisp/treesit.el b/lisp/treesit.el index 0df71d12ed..69b53bde5d 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1623,6 +1623,22 @@ treesit--defun-maybe-top-level node) finally return node)))) +(defun treesit-transpose-sexps (&optional arg) + "Tree-sitter `transpose-sexps' function. +Arg is the same as in `transpose-sexps'." + (interactive "*p") + (if-let* ((node (treesit-node-at (point))) + (parent (treesit-node-parent node)) + (index (treesit-node-index node)) + (prev (treesit-node-child parent (1- index))) + (next (treesit-node-child parent (+ arg index)))) + (list (cons (treesit-node-start prev) + (treesit-node-end prev)) + (cons (treesit-node-start next) + (treesit-node-end next))) + ;; Hack to trigger the error message in `transpose-subr-1' when we + ;; don't have siblings to swap. + (list (cons 0 1) (cons 0 1)))) (defun treesit-beginning-of-defun (&optional arg) "Move backward to the beginning of a defun. -- 2.34.1 --=-=-=--