From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Theodor Thornhill Newsgroups: gmane.emacs.devel Subject: Re: Plug treesit.el into other emacs constructs Date: Thu, 15 Dec 2022 20:37:01 +0100 Message-ID: <871qp01msi.fsf@thornhill.no> References: <87wn6whete.fsf@thornhill.no> <87r0x3gnv5.fsf@thornhill.no> <04BB786A-3ED1-4918-8583-17AA01A1E453@gmail.com> <4E3940CA-67A6-45B7-8785-4E60FDECCDFB@gmail.com> <4315EFC6-7AA8-4A48-845C-9CA8B88034D9@thornhill.no> <87bko521n0.fsf@thornhill.no> <87359h1ybt.fsf@thornhill.no> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="34509"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Yuan Fu , emacs-devel@gnu.org, eliz@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Dec 15 20:38:09 2022 Return-path: Envelope-to: ged-emacs-devel@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 1p5u3T-0008gj-9G for ged-emacs-devel@m.gmane-mx.org; Thu, 15 Dec 2022 20:38:07 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p5u2e-0002Ws-8m; Thu, 15 Dec 2022 14:37:16 -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 1p5u2c-0002Wh-NH for emacs-devel@gnu.org; Thu, 15 Dec 2022 14:37:15 -0500 Original-Received: from out-24.mta0.migadu.com ([2001:41d0:1004:224b::18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1p5u2Z-00020m-Gs for emacs-devel@gnu.org; Thu, 15 Dec 2022 14:37:14 -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=1671133024; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: in-reply-to:in-reply-to:references:references; bh=bpxLk+VhMc8Rq/9rHWX7y6X+ekwbG8zpFZsRvMZm0YQ=; b=x0RUzzwPukTgqHFPPHFXGA/Ngq5EqjWCLvbCT24yMRj/W5HNxj3a+Rl9qzpz2LWihLTFsG Mk3+GQwogunOwRu3OUB6esrlkOYCy0bAY0owI2NbtG8W4/uQXGy1D5nKGAYITgnToICXjk ZTxuoWAZO+Eux4J7GtgnmcZkwRemfdRGIcgb2vaXL9vuKlc7glsIPAWNoR5uMmMmoeTa9B HcaQMOMEtkmMENTFvZtxAhwC+9o8Lc35L/uYQ1sPvChUySInmIHvlgWriGlXL5kYBMaR+Z 9g3FJRZK3ZXT2a6/CJk2/gEKs4PUH/BSHz0BDyD2yF0+di4rcPeeKM92w7TXwA== In-Reply-To: X-Migadu-Flow: FLOW_OUT Received-SPF: pass client-ip=2001:41d0:1004:224b::18; envelope-from=theo@thornhill.no; helo=out-24.mta0.migadu.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:301465 Archived-At: Stefan Monnier writes: >> Great. It seems there has been almost no development, nor documentation >> done in this area for a long time. Should I try to improve on this part >> of the code while I'm at it? > > That would be welcome, yes. > Ok, will do. >> Yeah, that's what I'm thinking too. I'm just thinking we should be >> clear on what a word/sexp/sentence/paragraph/defun etc is in non-lisp >> and non-human languages. > > In the context of SMIE I came up with a usable meaning for sexp (which > I've been trying to explain in this thread), but for sentence and > paragraph it seems harder and is likely to depend on the specifics of > the language (e.g. for some languages "sentence" might be mapped to > "instruction" or maybe "instruction that doesn't itself contain nested > instructions", but some languages don't have a notion of instruction). > Yeah, I understand. >>>> Now I'm having issues where movement over sexps ends up not in the >>>> same place. >>> Same place as? >> IIRC there's no guarantee that the movement sequence used for >> transpose-sexp moves over the same blocks of code, so in non-lisp >> languages there's no real semantic to go from. > > I guess in general it can be difficult to be consistent, indeed. > In SMIE I preserve the following (or at least I try to): > > infix > ^ ^ ^ ^ > AB AE BB BE > > if `transpose-sexp` swaps FOO and BAR, then `forward-sexp` from AE goes > to BE and `backward-sexp` from BB goes to AB. But when you start to > consider mixfix syntax it can become much less clear what needs to > be done. I don't think we should worry too much if `transpose-sexp` and > `forward/backward-sexp` don't align 100% is all cases: we should strive > to keep them consistent, but it's OK to break down in corner cases. > Actually, I think there is a nice solution waiting for us. If we consider the 'balanced expressions' to be swapped in transpose-sexps as siblings, we could just: (defun treesit-transpose-sexps (&optional arg) "Tree-sitter `beginning-of-defun' function. ARG is the same as in `beginning-of-defun'." (interactive "*p") (if-let* ((node (treesit-node-at (point))) (prev (treesit-node-prev-sibling node)) (next (treesit-node-next-sibling node))) (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)))) If this code is plugged into transpose-sexps we get this nice behavior: Python: ``` def foo(): return x |if x == 5 else False def foo(): return x == 5 if x| else False ``` and ``` def foo(): return x if x == 5 el|se False def foo(): return x if False else x == 5| ``` and ``` def foo(): return| x if x == 5 else False ;; Don't have two things to transpose ``` Java: ``` public class foo { void foo(String x,| int y) {} } public class foo { void foo(int y, String x|) {} ``` and ``` public class foo { void foo() { if (x =|= y) {} } } public class foo { void foo() { if (y == x|) {} } } ``` and ``` public class foo { void foo(String x, int y) { foo(a + 4|, c * b + y, b, d).bar(); } } public class foo { void foo(String x, int y) { foo(c * b + y, a + 4|, b, d).bar(); } } ``` and ``` foo(a + 4, c * b |+ y, b, d); foo(a + 4, y + c * b, b, d); ``` Now forward/backward-sexp can actually work a little differently, as you suggest, or we can let it use the same "move over siblings"-semantic. In that case we don't even need the treesit-sexp-type-regexp variables to control this, I think. What do you think? Theo