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: Tue, 13 Dec 2022 21:02:15 +0100 Message-ID: <87o7s7gji0.fsf@thornhill.no> References: <87wn6whete.fsf@thornhill.no> <87r0x3gnv5.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="12374"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel@gnu.org, eliz@gnu.org, casouri@gmail.com To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Tue Dec 13 21:03:35 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 1p5BV0-0002xv-Ja for ged-emacs-devel@m.gmane-mx.org; Tue, 13 Dec 2022 21:03:35 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1p5BUM-0004OQ-2M; Tue, 13 Dec 2022 15:02:54 -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 1p5BTq-0004Nz-Qu for emacs-devel@gnu.org; Tue, 13 Dec 2022 15:02:23 -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 1p5BTo-0002jE-D7; Tue, 13 Dec 2022 15:02:22 -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=1670961737; 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=0JrNMPQmmKPcLqdV43UXcJ6SKhDIGQfGtfZgh+cURy0=; b=IsUYgaqorIrJd7kKMB+XSbhW6Lu7cOlElinAZK/O2NPtAYk3xDubPAeMi4wS/RSZzVSnEh /gaCQbYh/z2ibaAjDWyAg93w8CCJa32gE55Jy6bm/SfaqZUwLpliNyzeBSAA3htfQLAx/X T6cNTXZ1uuBOyl1kLK2EaI1Qv1FN7lFO4UeE1f2fwlCoSXgY5S5p0pmlbqCBZ5ZUG6SLNG MQraVl1202UTZ53siUeROR0FqWwEJQkvSJ06APOKo++GxWhRfizrBfrp8U4hLxQHdPc/Ho TATQc2vMduokrX9my+ElfebsDEMzF3cQcr3VyxmnMKtr+kOHeLPSa3Xiq4P1nw== In-Reply-To: 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: 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:301357 Archived-At: Stefan Monnier writes: >>>> ** Forward-sexp: >>>> Executing C-M-f repeatedly will go from: >>>> ``` >>>> public void foo(|String bar, String baz) {} >>>> ``` >>>> to >>>> ``` >>>> public void foo(String bar|, String baz) {} >>>> ``` >>> >>> That looks wrong. `String` is a valid AST node. Whether it gets a node >>> in tree-sitter or not, I don't know, but here there are several "sexps" >>> that start at point and I think `forward-sexp` should be conservative >>> and keep advancing by the smallest option. >> I understand. My reasoning is that 'forward-word' is suitable for that, > > It's not, tho, because it stops within identifiers like "foo_bar". > There's a similar question for things like `String.match`. > Ok, I think I understand. But 'void foo(String bar)' is not the same as 'String.format', where 'void foo(bar String)' would make to sense, but 'format.String' could. >> and to actually gain something from these we need to use a little bigger >> constructs. In tree-sitter 'String' isn't really valid, because you >> need the identifier to create a complete node. > > I think we should not define the "ideal" behavior based on what > Tree-sitter provides. > As I said, in the *A*ST, `String` is a valid node. > It's especially true if you consider more complex types like > > public void foo(Array, String>> bar, String baz) > And in this case multiple forward-sexps would be ``` |public void foo(Array, String>> bar, String baz) public| void foo(Array, String>> bar, String baz) public void| foo|(Array, String>> bar, String baz) public void foo(Array|, String>> bar, String baz) public void foo(Array, String>> bar, String baz) public void foo(Array, String>> bar, String baz) public void foo(Array, String>> bar, String baz) public void foo(Array, String|>> bar, String baz) public void foo(Array, String>> bar|, String baz) public void foo(Array, String>> bar, String| baz) public void foo(Array, String>> bar, String baz|) ``` and transpose-sexp would be: ``` public void foo(Array, String>> bar,| String baz) public void foo(String baz, Array, String>> bar|) ``` Not really sure how to accomodate the two behaviors in the same function, but I'll get there. >> In this case I'd think that forward-sexp would do: >> ``` >> x = |f (x) * 3 + 2; >> x = f (x)| * 3 + 2; >> x = f (x) * 3| + 2; >> x = f (x) * 3 + 2;| >> ``` >> Or something like that. > > Similarly here I think it should first stop after `f`. > The other ones look right to me. > Ok >> So that multiple transpose-sexps would move >> 'f(x)' over the operators, swapping with the integers. > > You could still do that, but you'd have to start with point next to `*` > to specify the node whose children you want to swap. > Yeah. >>>> ``` >>>> public void foo(String bar, String baz|) {} >>>> ``` >>> >>> That one's right :-) >> >> Why is this one right, and the above not? > > Because point was left of the comma and the smallest right child of the > corresponding node is "String bar" and not "String" (which is more like > the left child of the node that covers "String bar"). > Ok, so you mean that forward-sexp should incrementally cover more and more of a node, but transpose-sexp would find the _whole_ node, then swap it with the one "in front" of it? so in 'void(String foo, int bar)' forward-sexp would go word by word, but transpose-sexp would capture "String foo" and "int bar" when point is on the comma? >> Thanks for the feedback so far. I interpret this that this feature is >> wanted, so I'll make a more serious effort and get back to you. > > Yes, definitely. It's one of the best features of SMIE compared to > "hand-written" indentation code, if you ask me :-) > Tree-sitter should be able to do it even better. > Nice! >> BTW, where are the semantics for these movement functions defined? > > In our heads. > Sweet - I might bother you more, then. >> I mean, what construct is each one expected to jump over? > > In my book "sexp" movement should jump over subtrees of the AST. So given this ast point should move over each named node, no matter if transposing them would create broken code? ``` (class_declaration (modifiers public) class name: (identifier) body: (class_body { (method_declaration dimensions: (generic_type (type_identifier) (type_arguments < (generic_type (type_identifier) (type_arguments < (type_identifier) >)) >)) body: (identifier) (formal_parameters ( (formal_parameter type: (type_identifier) dimensions: (identifier)) , (formal_parameter type: (type_identifier) dimensions: (identifier)) )) (block { })) })) ``` Forgive my stupid questions, I just want it to be clear to me what I'm doing here ;) Theo