From unknown Wed Jun 18 00:22:43 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#78703 <78703@debbugs.gnu.org> To: bug#78703 <78703@debbugs.gnu.org> Subject: Status: beginning-of-defun and friends still wrong in typescript-ts-mode Reply-To: bug#78703 <78703@debbugs.gnu.org> Date: Wed, 18 Jun 2025 07:22:43 +0000 retitle 78703 beginning-of-defun and friends still wrong in typescript-ts-m= ode reassign 78703 emacs submitter 78703 Daniel Colascione severity 78703 normal thanks From debbugs-submit-bounces@debbugs.gnu.org Thu Jun 05 19:40:19 2025 Received: (at submit) by debbugs.gnu.org; 5 Jun 2025 23:40:19 +0000 Received: from localhost ([127.0.0.1]:39256 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uNKC3-0001ZK-9L for submit@debbugs.gnu.org; Thu, 05 Jun 2025 19:40:19 -0400 Received: from lists.gnu.org ([2001:470:142::17]:37768) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uNKC0-0001Sw-I9 for submit@debbugs.gnu.org; Thu, 05 Jun 2025 19:40:16 -0400 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 1uNKBs-00089u-Aw for bug-gnu-emacs@gnu.org; Thu, 05 Jun 2025 19:40:08 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uNKBq-0003AY-7A for bug-gnu-emacs@gnu.org; Thu, 05 Jun 2025 19:40:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Type:MIME-Version:Message-ID:Date:Subject:To:From:Sender: Reply-To:Cc:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=pprL4aOfJGfLUYTmRBf9GlS9/TsBivrcm5CgG6aCqA0=; b=kVrZx3SWkGSH+Ko/4/ViYqZhPI HKA+YBarhX0+/71IWWydCouod9oCdeMRIV31hcXCCakcKTmCkpbe2ec8iEPkzKhImvyk9dpG/5ZtQ uhv0t2IewuG6Eu0bvHaAVNkfiY5D5VYHNQBoxdz++xnmzFUtnE1DBjnZgcxUksA7bA0XmzTpc75y5 Byl0pnOvBzYnWgJwsg23iWrn7/vARpxLySDXpf/2aZGyur5qOIlejh8gyGEl45+ksjfWH1LJbN0cH YW8s3PwzKbXYYIpDwHSuNftp1ykCl9agJP7y56xuo791nYn2ymaTb29vTKJxZsLbYmk20qhZoZsho 4R8Ai5eA==; Received: from dancol by dancol.org with local (Exim 4.96) (envelope-from ) id 1uNKAZ-00BAUv-2W for bug-gnu-emacs@gnu.org; Thu, 05 Jun 2025 19:38:47 -0400 From: Daniel Colascione To: bug-gnu-emacs@gnu.org Subject: beginning-of-defun and friends still wrong in typescript-ts-mode User-Agent: mu4e 1.12.10; emacs 31.0.50 Date: Thu, 05 Jun 2025 16:40:03 -0700 Message-ID: MIME-Version: 1.0 Content-Type: text/plain Received-SPF: pass client-ip=2600:3c01:e000:3d8::1; envelope-from=dancol@dancol.org; helo=dancol.org 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_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: 0.9 (/) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.1 (/) Right now, C-M-a runs treesit-beginning-of-defun which goes to the start of the previous defun in buffer text, not the enclosing defun. If we have this program: 1 function foo() { 2 function bar() { 3 return 5 4 } 5 return 7 6 } and point is on line 5, then if we hit C-M-a, point goes to line 2, not line 1. In every single situation, when I use beginning-of-defun, I intend to go to the start of my enclosing defun not the one that happens to be previous in buffer linearization. From debbugs-submit-bounces@debbugs.gnu.org Fri Jun 06 03:01:36 2025 Received: (at 78703) by debbugs.gnu.org; 6 Jun 2025 07:01:37 +0000 Received: from localhost ([127.0.0.1]:41258 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uNR56-0004A7-IG for submit@debbugs.gnu.org; Fri, 06 Jun 2025 03:01:36 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:46874) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uNR52-00049h-LY for 78703@debbugs.gnu.org; Fri, 06 Jun 2025 03:01:33 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uNR4v-0003fW-5K; Fri, 06 Jun 2025 03:01:26 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=HyFOrBlb4xeQqQc9wx84g1j4qwjfuG+gyiSZBVA+V4E=; b=TYAyrUWg1325 A2CdIG1pFYRDSfGoh+uIUeHy71qizriKg+1+cTlhkx5dU4NmNzJAErP253VF3AltOb6swo8BrA8Cc 6HkHp/ht51uhOmXkjKJr/BkTc6gFCPw9rdI7l1CzKLnyBdrNcpuR7yjj7+H8WyKHd8ClKhxO4P0F9 ySjI+woyzFsZSuRbAWmHkHyDZXpgAApn4N3fwq3GP0IA31+f+YBCACbuLpSSuSKr+wsUEVEFvccYU jbpJkyLigLnMUdUBrfI1haFGLkPfuUTQO8jIo1bedbq8P44Yji1pgZ3h7jyBwX4XIINOuraw0tn1D JysljDDJjMoODLAYCR44SQ==; Date: Fri, 06 Jun 2025 10:01:20 +0300 Message-Id: <86zfell5fj.fsf@gnu.org> From: Eli Zaretskii To: Daniel Colascione , Yuan Fu In-Reply-To: (message from Daniel Colascione on Thu, 05 Jun 2025 16:40:03 -0700) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode References: X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 78703 Cc: 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Daniel Colascione > Date: Thu, 05 Jun 2025 16:40:03 -0700 > > Right now, C-M-a runs treesit-beginning-of-defun which goes to the > start of the previous defun in buffer text, not the enclosing defun. > > If we have this program: > > 1 function foo() { > 2 function bar() { > 3 return 5 > 4 } > 5 return 7 > 6 } > > > and point is on line 5, then if we hit C-M-a, point goes to line 2, not > line 1. In every single situation, when I use beginning-of-defun, I > intend to go to the start of my enclosing defun not the one that happens > to be previous in buffer linearization. I think you want to set treesit-defun-tactic to 'top-level'. From debbugs-submit-bounces@debbugs.gnu.org Fri Jun 06 03:23:45 2025 Received: (at 78703) by debbugs.gnu.org; 6 Jun 2025 07:23:45 +0000 Received: from localhost ([127.0.0.1]:41371 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uNRQX-0005Pf-AE for submit@debbugs.gnu.org; Fri, 06 Jun 2025 03:23:45 -0400 Received: from mail-pg1-x52d.google.com ([2607:f8b0:4864:20::52d]:50348) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1uNRQU-0005P6-4D for 78703@debbugs.gnu.org; Fri, 06 Jun 2025 03:23:43 -0400 Received: by mail-pg1-x52d.google.com with SMTP id 41be03b00d2f7-b2f62bbb5d6so182088a12.0 for <78703@debbugs.gnu.org>; Fri, 06 Jun 2025 00:23:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1749194616; x=1749799416; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=kYXoxnqywdikarGrdo5/ozBp8dlTOAJFjWhpDF3KOj8=; b=BIDAb1I0NbOTbT+EV1uXHv28EDvbgC72mneabTBHH6dWRVh9sEpxzRj4JBeax4yBf0 jvldcZCr5TZ1hGIB23TLVIUL6IzXIRISSjnGeByFcGrENICjDaon4nbogWB2cLJCukZZ LozuoUuZzOnZTEybBzBcpuhTOpHvXOjvfcmMwufq1NO3N5GYw7CvbiHaHxfpSLRI9Dev Eb2MluHUEOIHvvJ6/hT7FP7q4fr53tvSjsVO4HL3FN2r4WDoFyAyDXcBpsSD+/yuWxYO k1lxC4zGQXvI2NkZb0t2QxQjqRmLKMiwWWsc9O/NOrREhtMwFEzYg4UH90U8dg/eq1i4 +jkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749194616; x=1749799416; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kYXoxnqywdikarGrdo5/ozBp8dlTOAJFjWhpDF3KOj8=; b=ZYRLGlcmR7j62Iq+2qxTpyRAA/umW21mvTUXmL64kcz/M52/4XOjJnfYVWWenqcqkB lgVxCrmvnt+tCXZp2q6ACmH3ll1BvWC0r6HPAo1Yr28cxFPrSHFMTAxTKkyZa59B45Z8 CM2YoQTGMDhu8Q6qmVN+f4VXeOst597z1yU5Ke8ppjnZyC7E2beiEyZaDgf7vjQjx5KQ 9AKw9qNCC/yBhmIFr8eSvAejW8xQZRAWR/5eJeqPDJUYXFb4LxouhqPgUfcSs5iQSHou oLQJlymNoPq7xnqmg8COQlf/99dUdMHOZNoWyig2yPBfblzFCSS72sEDiGBQ2aX1y3FA aPYA== X-Forwarded-Encrypted: i=1; AJvYcCWxXkVfNYUFQrZUDYyoTZQTlHCEuVOUxL7jn+6h3iDoW4PgeD2R/DB+rta9BJ5OVmXnguET+A==@debbugs.gnu.org X-Gm-Message-State: AOJu0YzrOHcFv8a4xMO9WiGfrztO3rwO4GFJ6328V8Fd+3uGcEsWLvHO Xc5r2Hi6ZgYtHxbQRt/Je9S9rT/qI67wd+M+g5AWomgfteeYVfdtzPCH X-Gm-Gg: ASbGncsy90703zAZ6+Vr09622eHR/3hs6mj6QhSIODtpHhwEnRO26EQHYTwvvTCDn0N WF9GEZIW0TrvdOY45D4UlPECCFIZk0jMZLE2sD90x1ctfDciVkk9OUxAtDhPMdfikWXAQfMpP/6 nBc4X8tWseblLGKH5QdfDSeoAEqVzm04hyIvCtMH+5Md/y2Y6v99ZLc46kvrJ3l43+A56mECuj7 TesbjTVRskdWE5lI8o0ryOXyHeJt3U+bSRSE1cPv7297DCsfWaI3fvN9AnUGO42+v9Cq3MbIHtx UcpNO7+ukjsQsmixQIvnuf/lvyPMSNMzSh8Qz2vOnd/zVKH5//QqFQRm9VD2RCt6DuuZwl7HZD9 anCyK1wIfwmig4IoDwUkOkf5r X-Google-Smtp-Source: AGHT+IHLnjA3MyhtomYiYZdF95iavya4Zt43eQcDcuus3ZAPBugvFFoLFPFVuu/FfO6GBWqMOjYNDg== X-Received: by 2002:a17:90b:510e:b0:311:baba:bb91 with SMTP id 98e67ed59e1d1-313472e4fd4mr4193306a91.10.1749194615431; Fri, 06 Jun 2025 00:23:35 -0700 (PDT) Received: from smtpclient.apple (c-24-4-247-194.hsd1.ca.comcast.net. [24.4.247.194]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-31349f352b0sm769191a91.18.2025.06.06.00.23.34 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 Jun 2025 00:23:34 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.500.181.1.5\)) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode From: Yuan Fu In-Reply-To: <86zfell5fj.fsf@gnu.org> Date: Fri, 6 Jun 2025 00:23:23 -0700 Content-Transfer-Encoding: quoted-printable Message-Id: <1CB2E0EE-9D64-4168-9FAC-2156F5AE305A@gmail.com> References: <86zfell5fj.fsf@gnu.org> To: Eli Zaretskii X-Mailer: Apple Mail (2.3826.500.181.1.5) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Daniel Colascione , 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) > On Jun 6, 2025, at 12:01=E2=80=AFAM, Eli Zaretskii = wrote: >=20 >> From: Daniel Colascione >> Date: Thu, 05 Jun 2025 16:40:03 -0700 >>=20 >> Right now, C-M-a runs treesit-beginning-of-defun which goes to the >> start of the previous defun in buffer text, not the enclosing defun. >>=20 >> If we have this program: >>=20 >> 1 function foo() { >> 2 function bar() { >> 3 return 5 >> 4 } >> 5 return 7 >> 6 } >>=20 >>=20 >> and point is on line 5, then if we hit C-M-a, point goes to line 2, = not >> line 1. In every single situation, when I use beginning-of-defun, I >> intend to go to the start of my enclosing defun not the one that = happens >> to be previous in buffer linearization. >=20 > I think you want to set treesit-defun-tactic to 'top-level=E2=80=99. Yes. Most likely top-level is what you want.=20 Yuan From debbugs-submit-bounces@debbugs.gnu.org Fri Jun 06 03:57:42 2025 Received: (at 78703) by debbugs.gnu.org; 6 Jun 2025 07:57:43 +0000 Received: from localhost ([127.0.0.1]:41486 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uNRxO-0007Cq-HP for submit@debbugs.gnu.org; Fri, 06 Jun 2025 03:57:42 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]:49438) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uNRxL-0007Ch-7b for 78703@debbugs.gnu.org; Fri, 06 Jun 2025 03:57:40 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID: References:In-Reply-To:Subject:CC:To:From:Date:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=ymZbxoN1fIho+/LBOGoNcMUHFBhU6jrH1Xdc2ebDhCM=; b=YIw5YK58wYs1RrNUG7H9u/X1CH msn7QNMI540bnqtM7MRjYt1iAqs7+/I3fyc8pMzu19f2fTS+rt5qZY3WDIMondvrB5JqnM/Jx3aiM xb6GfgiajvTvTnnos15i98eVRDDumz+1Tu6oePFqo0a7+WnEznoqzGBYcgygZnjXDclZv93vjrKmF 58qzBjOy+0yy/xJIdgpX4S+vO9sdySLHM65i9LnyRkvTnZkQubCXpcGXiSav5JN+yBuGIJ1fTBF1C s7HA+VqfPxi0W/TxX1yV8C8J8VujX1mSIMBH8Vr2+SLdjPgjtUEOewa82BcdibGDiu0oBl1K620tC do3mvpxw==; Received: from [2600:1010:b044:9528:0:4e:46fb:1201] (port=35960 helo=[IPv6:::1]) by dancol.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uNRw5-00BBve-0S; Fri, 06 Jun 2025 03:56:21 -0400 Date: Fri, 06 Jun 2025 00:57:36 -0700 From: Daniel Colascione To: Yuan Fu , Eli Zaretskii Subject: =?US-ASCII?Q?Re=3A_bug=2378703=3A_beginning-of-defun_and_f?= =?US-ASCII?Q?riends_still_wrong_in_typescript-ts-mode?= User-Agent: K-9 Mail for Android In-Reply-To: <1CB2E0EE-9D64-4168-9FAC-2156F5AE305A@gmail.com> References: <86zfell5fj.fsf@gnu.org> <1CB2E0EE-9D64-4168-9FAC-2156F5AE305A@gmail.com> Message-ID: <58C31A4F-D698-4AAF-93DF-A46DAA85466E@dancol.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On June 6, 2025 12:23:23 AM PDT, Yuan Fu wrote: > > >> On Jun 6, 2025, at 12:01=E2=80=AFAM, Eli Zaretskii wro= te: >>=20 >>> From: Daniel Colascione >>> Date: Thu, 05 Jun 2025 16:40:03 -0700 >>>=20 >>> Right now, C-M-a runs treesit-beginning-of-defun which goes to the >>> start of the previous defun in buffer text, not the enclosing defun=2E >>>=20 >>> If we have this program: >>>=20 >>> 1 function foo() { >>> 2 function bar() { >>> 3 return 5 >>> 4 } >>> 5 return 7 >>> 6 } >>>=20 >>>=20 >>> and point is on line 5, then if we hit C-M-a, point goes to line 2, no= t >>> line 1=2E In every single situation, when I use beginning-of-defun, I >>> intend to go to the start of my enclosing defun not the one that happe= ns >>> to be previous in buffer linearization=2E >>=20 >> I think you want to set treesit-defun-tactic to 'top-level=E2=80=99=2E > >Yes=2E Most likely top-level is what you want=2E=20 > >Yuan > > I don't think that's right either --- if I'm on line 3, I should go to lin= e 2, not 1=2E Go to beginning of defun should mean go to the beginning of *= my* defun=2E That's the traditional behavior from cc-mode, js-mode, etc=2E = and the one that makes most sense=2E I can see top-level being an option, b= ut I don't think the way nested works right now is useful and it's confusin= g and inconsistent as a default=2E From debbugs-submit-bounces@debbugs.gnu.org Fri Jun 06 13:00:56 2025 Received: (at 78703) by debbugs.gnu.org; 6 Jun 2025 17:00:56 +0000 Received: from localhost ([127.0.0.1]:44679 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uNaR5-00045d-KS for submit@debbugs.gnu.org; Fri, 06 Jun 2025 13:00:56 -0400 Received: from m228-14.mailgun.net ([159.135.228.14]:56890) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1uNaR1-00045I-Fs for 78703@debbugs.gnu.org; Fri, 06 Jun 2025 13:00:52 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.troybrown.dev; q=dns/txt; s=mx; t=1749229234; x=1749236434; h=Content-Transfer-Encoding: Content-Type: Cc: To: To: Subject: Subject: Message-ID: Date: From: From: MIME-Version: Sender: Sender; bh=yUUh1w5ANLNaqzdbcceNoJDylM8o78KfbQIwUECA0B0=; b=AOrwe5xqD0Bxnq8K0j+ISha153l6qQnOkE+nWG9xWkXc6JcB4GfqMwFreP4l70uaobvxmohmfSJk3egKdWKHfrXNEw6/Ak8wf8GwsbtKrlKgt1Ic7I9G9RSQjJ6H6341XfpFeUkuIX2+WrUnR8PuGyjCnaK/VmvxlewjPhxlOiQ= X-Mailgun-Sid: WyIwMzZhOSIsIjc4NzAzQGRlYmJ1Z3MuZ251Lm9yZyIsIjVmZDVkMiJd Received: from mail-ej1-f42.google.com (mail-ej1-f42.google.com [209.85.218.42]) by ff7953391e47 with SMTP id 68431eb2c9c5ee39f3fc31d9 (version=TLS1.3, cipher=TLS_AES_128_GCM_SHA256); Fri, 06 Jun 2025 17:00:34 GMT X-Mailgun-Sending-Ip-Pool-Name: X-Mailgun-Sending-Ip-Pool: X-Mailgun-Sending-Ip: 159.135.228.14 Received: by mail-ej1-f42.google.com with SMTP id a640c23a62f3a-addcea380eeso351024566b.0 for <78703@debbugs.gnu.org>; Fri, 06 Jun 2025 10:00:34 -0700 (PDT) X-Forwarded-Encrypted: i=1; AJvYcCWNDgBCMQgvS7rtOcSEVzB4uU+21pILsoc1zUEGimQGjxMeTX5GYU8kTNGlMnFcetFKNXoutg==@debbugs.gnu.org X-Gm-Message-State: AOJu0YytQQQpxk+YPBSFECZXnXtSbGQRGt8HS+uj5xfdSazgaKKNeFpE aqS761yAfUf96Nja1ocPY+CwUo2C5WiTROpKTH7uZ/nROXJrrzhV0a2Iy5LyK0KpMsxprDqtgxn 5bXLl90pMzJxz2f35u+l+OIHNyXtY0ik= X-Google-Smtp-Source: AGHT+IHERwfIon1TrWoZcfwRS81Dk4i5AsU2ltdHs3dEhWzmOcy/LrYfoevuag4ym4cpvJKe7xirMD2rZKiW2jvVx3I= X-Received: by 2002:a17:906:c109:b0:adb:2db9:b0b0 with SMTP id a640c23a62f3a-ade1a978ddamr371519366b.35.1749229233216; Fri, 06 Jun 2025 10:00:33 -0700 (PDT) MIME-Version: 1.0 From: Troy Brown Date: Fri, 6 Jun 2025 13:00:22 -0400 X-Gmail-Original-Message-ID: X-Gm-Features: AX0GCFshoZl44I1L7wxSlC7ETkKdg3iqOZPM_MOsIvAPW0UP4bhoArs_VAh3RhE Message-ID: Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode To: Daniel Colascione Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Yuan Fu , 78703@debbugs.gnu.org, Eli Zaretskii X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Daniel Colascione writes: > On June 6, 2025 12:23:23 AM PDT, Yuan Fu wrote: >> >> >>> On Jun 6, 2025, at 12:01=E2=80=AFAM, Eli Zaretskii wrote= : >>> >>>> From: Daniel Colascione >>>> Date: Thu, 05 Jun 2025 16:40:03 -0700 >>>> >>>> Right now, C-M-a runs treesit-beginning-of-defun which goes to the >>>> start of the previous defun in buffer text, not the enclosing defun. >>>> >>>> If we have this program: >>>> >>>> 1 function foo() { >>>> 2 function bar() { >>>> 3 return 5 >>>> 4 } >>>> 5 return 7 >>>> 6 } >>>> >>>> >>>> and point is on line 5, then if we hit C-M-a, point goes to line 2, no= t >>>> line 1. In every single situation, when I use beginning-of-defun, I >>>> intend to go to the start of my enclosing defun not the one that happe= ns >>>> to be previous in buffer linearization. >>> >>> I think you want to set treesit-defun-tactic to 'top-level=E2=80=99. >> >>Yes. Most likely top-level is what you want. >> >>Yuan >> >> > > I don't think that's right either --- if I'm on line 3, I should go to > line 2, not 1. Go to beginning of defun should mean go to the > beginning of *my* defun. That's the traditional behavior from cc-mode, > js-mode, etc. and the one that makes most sense. I can see top-level > being an option, but I don't think the way nested works right now is > useful and it's confusing and inconsistent as a default. I agree. This behavior is not intuitive at all. I reported this in detail in Bug#68664, but it never seemed to go anywhere. Furthermore, using a `treesit-defun-tactic` of `top-level` doesn't work when you are arbitrarily nested and just want to go to the beginning of the function containing point. This behavior not only impacts interactive use of `treesit-beginning-of-defun` (via "C-M-a"), but other functionality which builds upon `beginning-of-defun`, most notably `prog-fill-reindent-defun`. For the Tree-sitter modes that I maintain, I had to create a mode-specific version of `prog-fill-reindent-defun` instead. That's because, as written, `prog-fill-reindent-defun` uses `beginning-of-defun`, and since in cases like this, `treesit-beginning-of-defun' goes to the previous nested function, rather than the function containing point, you end up re-indenting the previous nested function rather than the function containing point. The mode-specific version that I created, instead uses `treesit-defun-at-point` to locate the containing function. From debbugs-submit-bounces@debbugs.gnu.org Sat Jun 07 02:09:17 2025 Received: (at 78703) by debbugs.gnu.org; 7 Jun 2025 06:09:17 +0000 Received: from localhost ([127.0.0.1]:46516 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uNmk1-0006SP-5j for submit@debbugs.gnu.org; Sat, 07 Jun 2025 02:09:17 -0400 Received: from mail-pf1-x42f.google.com ([2607:f8b0:4864:20::42f]:53637) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1uNmjy-0006S7-N7 for 78703@debbugs.gnu.org; Sat, 07 Jun 2025 02:09:15 -0400 Received: by mail-pf1-x42f.google.com with SMTP id d2e1a72fcca58-747fc77bb2aso2273093b3a.3 for <78703@debbugs.gnu.org>; Fri, 06 Jun 2025 23:09:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1749276549; x=1749881349; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=u7PeKTf8iMJ2um+6cxf57/9q68SPg72P0361cGwctTU=; b=iMpB+Mu5GBn3gVaqKt8uTiyEGNlwwnC3RblmSW8x/xGbG4hD7lRKdv9RIA5vEu8dum O4stntfUerZEEeciFAJCxmHMpuy/Dg45rmGPvt/ii6InPbFDqunhQPsqZOhc8OPbPai4 pUhCDiQ8g9CxZsicFCI4f+kyHQvIusJxORqKmvOGOiQ87xp7Pe54HD6ILfZq7Qez8bEg V4O2QmSPe/gPqa/+5S2Zlzjy8F+iAba6WoGrkgVRZ25Ua1Qrenx/ZemJBZfl53S0f4lh y5PQwTV7rOOFEyMkcIq2M+k4B3HSBVet6Xo/1XtUfISEmL2zM+qFs/jS1kCxz0SBGMzt UK0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749276549; x=1749881349; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=u7PeKTf8iMJ2um+6cxf57/9q68SPg72P0361cGwctTU=; b=ke5rP4YDh4dU+uyIYrk5XvSOfym7fERX4GMWg+UhSHhk7vvCOGd3ae0cgm7wGkrpuU FT3Y1UuLPYC3bhL9uejaopv5Ctys8VHFguCRJts043G6G1EhSU6tEtNZUAfb0SL/hE1m saI0ZzzbdiKUFlz/tr7Uj7C8BGmTCu3sojcajdqlTa1Y8TcXUv4zMozskKvEmJvtcuZH To6+lwVb1r7zMvxvtCJVnBC5+ii6w+uqnRZLXgmPKfwenhbviS3iNvoyPpnN1rI1oMy2 Yu34JO/Ik8lr5VXkYdMhYZlEDX24TxcFnHEQMQF3WPBYZfGyylTh03368ca6+fylsXKQ AtvQ== X-Forwarded-Encrypted: i=1; AJvYcCWtqIgCV3ypE3ChlcEPxra7T0yx2Kcu0QJFl1qqcWgAxF5kEBaI4bc6HbLcj5u2iBRehgGmpA==@debbugs.gnu.org X-Gm-Message-State: AOJu0YxwCoERZFNeqCdJNZaalDnuImsbCW5hp1XkPTYsxTt6KXD3FHD0 epgiy8kG0nwm1RbN39z425FJDkVFoEcyn6yoVijC7gK7sBgbc8BEnIAZ X-Gm-Gg: ASbGncvtKP1Kov/Zuh0qiqtEEwAS8v9FmI6LTych6OzbtPYmE//ER62tYyVou9yG8R3 L+oC1IqN81ExvEj2rqCGxvCQbBWrjX0wmhacPiy3cL+Tz1TYeCBo89oQ72jr0R7gbPUnf8GS9oe fKrDgwpPyoyMLcif44IzdpwqcJXJ1tn9w5C/67LsCAuV33UpTMIXcPckxcuwQS43XErPuaGnMCr N4KTEjl3VFXlaqcN5Lp9mkgRMEHrCu27sctTyiM4RmLWrQaD5iQX6OZ0CgC9ZauNlaISekWUuB+ IomrwXtM5WrFmSuKbkHBMiNHFvl4/TIyWAwY0zUhhazqgBE5nOGm+LDzTmx0zJxXT6iieHqOb5Y Pc+KdpMXtHgZ1g2hcej2qGimIOtSvR3eEd20= X-Google-Smtp-Source: AGHT+IFRJpJTH3wlJOKm1jg47d061Tei0RQ2/ER7P8CFyEhVIbrIIZM1Hh7vVcTfTzmAJ0PvRa18qA== X-Received: by 2002:a05:6a21:6d8b:b0:1f5:a3e8:64dd with SMTP id adf61e73a8af0-21ee13bd873mr8693390637.0.1749276548620; Fri, 06 Jun 2025 23:09:08 -0700 (PDT) Received: from smtpclient.apple (c-24-4-247-194.hsd1.ca.comcast.net. [24.4.247.194]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-7482b0c05efsm2236278b3a.130.2025.06.06.23.09.07 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 06 Jun 2025 23:09:08 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.500.181.1.5\)) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode From: Yuan Fu In-Reply-To: Date: Fri, 6 Jun 2025 23:08:57 -0700 Content-Transfer-Encoding: quoted-printable Message-Id: References: To: Troy Brown X-Mailer: Apple Mail (2.3826.500.181.1.5) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Eli Zaretskii , Daniel Colascione , 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) > On Jun 6, 2025, at 10:00=E2=80=AFAM, Troy Brown = wrote: >=20 > Daniel Colascione writes: >=20 >> On June 6, 2025 12:23:23 AM PDT, Yuan Fu wrote: >>>=20 >>>=20 >>>> On Jun 6, 2025, at 12:01=E2=80=AFAM, Eli Zaretskii = wrote: >>>>=20 >>>>> From: Daniel Colascione >>>>> Date: Thu, 05 Jun 2025 16:40:03 -0700 >>>>>=20 >>>>> Right now, C-M-a runs treesit-beginning-of-defun which goes to the >>>>> start of the previous defun in buffer text, not the enclosing = defun. >>>>>=20 >>>>> If we have this program: >>>>>=20 >>>>> 1 function foo() { >>>>> 2 function bar() { >>>>> 3 return 5 >>>>> 4 } >>>>> 5 return 7 >>>>> 6 } >>>>>=20 >>>>>=20 >>>>> and point is on line 5, then if we hit C-M-a, point goes to line = 2, not >>>>> line 1. In every single situation, when I use beginning-of-defun, = I >>>>> intend to go to the start of my enclosing defun not the one that = happens >>>>> to be previous in buffer linearization. >>>>=20 >>>> I think you want to set treesit-defun-tactic to 'top-level=E2=80=99. >>>=20 >>> Yes. Most likely top-level is what you want. >>>=20 >>> Yuan >>>=20 >>>=20 >>=20 >> I don't think that's right either --- if I'm on line 3, I should go = to >> line 2, not 1. Go to beginning of defun should mean go to the >> beginning of *my* defun. That's the traditional behavior from = cc-mode, >> js-mode, etc. and the one that makes most sense. I can see top-level >> being an option, but I don't think the way nested works right now is >> useful and it's confusing and inconsistent as a default. >=20 > I agree. This behavior is not intuitive at all. I reported this in > detail in Bug#68664, but it never seemed to go anywhere. Furthermore, > using a `treesit-defun-tactic` of `top-level` doesn't work when you > are arbitrarily nested and just want to go to the beginning of the > function containing point. >=20 > This behavior not only impacts interactive use of > `treesit-beginning-of-defun` (via "C-M-a"), but other functionality > which builds upon `beginning-of-defun`, most notably > `prog-fill-reindent-defun`. For the Tree-sitter modes that I > maintain, I had to create a mode-specific version of > `prog-fill-reindent-defun` instead. That's because, as written, > `prog-fill-reindent-defun` uses `beginning-of-defun`, and since in > cases like this, `treesit-beginning-of-defun' goes to the previous > nested function, rather than the function containing point, you end up > re-indenting the previous nested function rather than the function > containing point. The mode-specific version that I created, instead > uses `treesit-defun-at-point` to locate the containing function. So for this tactic, point should move out of the enclosing defun if it = is inside a defun; and if point isn=E2=80=99t inside any defun it should = move to the previous defund-beginning? Any suggestions for a good name for this tactic? Right now we have = `nested` and `top-level`. Yuan= From debbugs-submit-bounces@debbugs.gnu.org Sat Jun 07 03:14:46 2025 Received: (at 78703) by debbugs.gnu.org; 7 Jun 2025 07:14:46 +0000 Received: from localhost ([127.0.0.1]:46586 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uNnlN-0001Dk-Lz for submit@debbugs.gnu.org; Sat, 07 Jun 2025 03:14:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:60280) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uNnlK-0001DP-SI for 78703@debbugs.gnu.org; Sat, 07 Jun 2025 03:14:43 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uNnlE-0005he-AX; Sat, 07 Jun 2025 03:14:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=5sH4LsYcZ/T9k1WaOKZ/UGKTL3fA2pveQZnq5NP0D00=; b=gI3x1rD72khdzS0ogY7J QOaMu6xLu8YDdEu3NiGViSTKyTxVwarY2D0AR+phC3GT4ZVbpqD86ukiDP13wCttE9yqjB3tLr83n KUqQfJUlGS3IHvdOiyADMx+G2w9HKKAVkfyR+Iiu89qKnL/3hfA0RxzjXncTixb82m4bdiU7JNTfT uj24OMhQbthANVHeM+487ICRajkdFtkT4EGnOzL4rObcl5axRSAQlDGZcs+OUDY0/cWf7IxXlSbsI Q7gvhsBmxIzxX8ipPko5K/PGPcdJcNrBnfcQvnLB+9xSrp7ZzmQmw/kegaMzYqZ3qfdNbzW9feESw esC5tksXYql4MA==; Date: Sat, 07 Jun 2025 10:14:34 +0300 Message-Id: <86zfekja5h.fsf@gnu.org> From: Eli Zaretskii To: Yuan Fu In-Reply-To: (message from Yuan Fu on Fri, 6 Jun 2025 23:08:57 -0700) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode References: MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 78703 Cc: 78703@debbugs.gnu.org, brownts@troybrown.dev, dancol@dancol.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Yuan Fu > Date: Fri, 6 Jun 2025 23:08:57 -0700 > Cc: Daniel Colascione , > Eli Zaretskii , > 78703@debbugs.gnu.org > > So for this tactic, point should move out of the enclosing defun if it is inside a defun; and if point isn’t inside any defun it should move to the previous defund-beginning? > > Any suggestions for a good name for this tactic? Right now we have `nested` and `top-level`. Something like 'same-level'? From debbugs-submit-bounces@debbugs.gnu.org Sat Jun 07 10:03:58 2025 Received: (at 78703) by debbugs.gnu.org; 7 Jun 2025 14:03:58 +0000 Received: from localhost ([127.0.0.1]:49160 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uNu9N-0005zp-HK for submit@debbugs.gnu.org; Sat, 07 Jun 2025 10:03:57 -0400 Received: from m228-15.mailgun.net ([159.135.228.15]:32332) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1uNu9K-0005zY-5C for 78703@debbugs.gnu.org; Sat, 07 Jun 2025 10:03:55 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.troybrown.dev; q=dns/txt; s=mx; t=1749305022; x=1749312222; h=Content-Transfer-Encoding: Content-Type: Cc: To: To: Subject: Subject: Message-ID: Date: From: From: In-Reply-To: References: MIME-Version: Sender: Sender; bh=oe1tjOQIz5+6pPx2LvqID7PHTMJutuCmp/EBbFx/1go=; b=OPZxmoSqQIbB8ExMt5mNmePWW9CRlnLbC4MYFkP5oYmVfAp/wEWTj+ToEGUpvmkhc+oSgodNSeAc28Y2a4r0o7orRYn/QDzhJ+K355KTx4alLi3GaZVozaZMLSzuXk1ZS5TNPgrtuOoxwDk3U2Q0oA7EkNrHiXmeDa+iHHMmldI= X-Mailgun-Sid: WyIwMzZhOSIsIjc4NzAzQGRlYmJ1Z3MuZ251Lm9yZyIsIjVmZDVkMiJd Received: from mail-ed1-f52.google.com (mail-ed1-f52.google.com [209.85.208.52]) by 112758aafbe3 with SMTP id 684446b9953bd88224962c35 (version=TLS1.3, cipher=TLS_AES_128_GCM_SHA256); Sat, 07 Jun 2025 14:03:37 GMT X-Mailgun-Sending-Ip-Pool-Name: X-Mailgun-Sending-Ip-Pool: X-Mailgun-Sending-Ip: 159.135.228.15 Received: by mail-ed1-f52.google.com with SMTP id 4fb4d7f45d1cf-60789b450ceso2152213a12.2 for <78703@debbugs.gnu.org>; Sat, 07 Jun 2025 07:03:37 -0700 (PDT) X-Forwarded-Encrypted: i=1; AJvYcCUfx0O6mn6Z94ZkbEv/V7UjMFeqVn/XLRne5Q+mXs38I/oLztpnDxIsbXlb8xRJKp3i91uFdg==@debbugs.gnu.org X-Gm-Message-State: AOJu0YyD0YqqDS8HjUvgc6EtDtwdlm2EJnJwD95ROWszxRRXjEzp9Rm0 rskiwem9R/TTXxgSMUi1b4xFyVWz0ozvDWiVQ/O1g0UEIRREdL2sXy1Ij4/GOdgnbG3Q71Z9vn3 tZvaTpy7D4o9CHo5Ib9PL3YT+t9c4O9Y= X-Google-Smtp-Source: AGHT+IHsRI2wnq5DvvPrkrMXXYs9F2bUgiw7l/eXQxSVjshypaQawVJnr6Q6TI3+jd8NJsyJWS+CeE313T57wsHnE7o= X-Received: by 2002:a05:6402:1cc1:b0:606:baba:79f2 with SMTP id 4fb4d7f45d1cf-6077489800fmr6484665a12.33.1749305016230; Sat, 07 Jun 2025 07:03:36 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Troy Brown Date: Sat, 7 Jun 2025 10:03:24 -0400 X-Gmail-Original-Message-ID: X-Gm-Features: AX0GCFuQEIZEySYPnoWl1FPVxXVoadQiBRsf38-ubrqPuP1oOnrHchH3EIjJAe4 Message-ID: Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode To: Yuan Fu Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Eli Zaretskii , Daniel Colascione , 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On Sat, Jun 7, 2025 at 2:09=E2=80=AFAM Yuan Fu wrote: > > So for this tactic, point should move out of the enclosing defun if it is= inside a defun; and if point isn=E2=80=99t inside any defun it should move= to the previous defund-beginning? Care must be taken when talking about being "inside" or "not inside" a defun. Unless point is before, after, or between top-level defuns, it will always be inside some defun. I previously suggested differentiating behavior based on whether point was at a defun boundary. By boundary, I mean point is either immediately before or immediately after a defun. It's also important to point out that classes, namespaces, packages, etc. could all be defuns, not just functions. Therefore the nesting as being described is not a pathological exercise, but a much more common occurrence than one might initially consider. As far as behavior, I think the way I've observed it working in non-Tree-sitter modes was more intuitive than the current Tree-sitter behavior (but I haven't exhaustively checked). Additionally, I think it should work as described in the documentation. Much of what I'm saying was already expressed in Bug#68664. There, I tried to codify how I believed the non-Tree-sitter modes were behaving and how intuitively I thought it should work for Tree-sitter modes. Regardless of what tactic is configured, `treesit-beginning-of-defun` must go to the beginning of the enclosing defun when point is not at a defun boundary. I think this is fundamental or the assumptions made when using `beginning-of-defun` in the general case no longer hold (such as its use in `prog-fill-reindent-defun`). I think the tactic should only come into play when point is already at a defun boundary. After that, I'm less concerned about its behavior, but think the current `nested` behavior of visiting the previous sibling defun until there are no more, then visiting the parent defun makes sense. The key difference is that you only visit the previous sibling if point is at a defun boundary...otherwise visit the defun containing point. Furthermore, consider the following `top-level` tactic example using `c++-ts-mode`. Here, we have a C++ namespace (which is considered a defun for C++) as well as a "doSomething" function defun within the namespace. If we place point on the "printf" and press `M-q`, triggering `prog-fill-reindent-defun`, we'll see that the entire namespace has been re-indented (including "int i;"). I'd argue that was not intuitively what I would have expected to happen. Instead, I would have expected only "doSomething" to have been re-indented. ```cpp // -*- mode: c++-ts #include namespace Hello { int i; void doSomething(void) { printf("doSomething\n"); } }; // Local Variables: // treesit-defun-tactic: top-level // End: ``` If the behavior of `treesit-beginning-of-defun` was to first move to the beginning of the enclosing defun when point is not at a defun boundary (as previously described), the expected behavior of only reindenting "doSomething" would have occurred. If `treesit-beginning-of-defun` worked the way I propose, and you really wanted to re-indent the entire namespace, it would have been as simple as moving to the beginning of the enclosing defun and triggering `prog-fill-reindent-defun` there (i.e., `C-M-a` `M-q`). > Any suggestions for a good name for this tactic? Right now we have `neste= d` and `top-level`. See above. I don't think a new tactic is necessary, just a change in how `treesit-beginning-of-defun` works when point is not at a defun boundary, regardless of the configured tactic. From debbugs-submit-bounces@debbugs.gnu.org Tue Jun 10 02:02:57 2025 Received: (at 78703) by debbugs.gnu.org; 10 Jun 2025 06:02:57 +0000 Received: from localhost ([127.0.0.1]:60148 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uOs4W-0002dx-FN for submit@debbugs.gnu.org; Tue, 10 Jun 2025 02:02:57 -0400 Received: from mail-pg1-x529.google.com ([2607:f8b0:4864:20::529]:57817) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1uOs4R-0002c0-SI for 78703@debbugs.gnu.org; Tue, 10 Jun 2025 02:02:53 -0400 Received: by mail-pg1-x529.google.com with SMTP id 41be03b00d2f7-b2c3c689d20so3153964a12.3 for <78703@debbugs.gnu.org>; Mon, 09 Jun 2025 23:02:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1749535365; x=1750140165; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=UDTSk/d8jd23QCU1m5FB65MI3cHXuvlKN2ZGeYOHd0A=; b=WJEf4N3+lpGc/7TCxsv/TOebzw8lcmdfJOoIS/qvlvvSWVpB+iO9K/RsU78lpYR/o8 xY1uf8GNpNbolC8HIGG/xejj9URdf3iYXcHhURzUZYfBzi/DyDaEfkOaifIHI05FxXKz L71RdTU0Ab5SwxuFIAXhv2mM4Ib3xzmhE8eR7mymxRxkpROjfVvJAX5yF1l9IlIVBJJk oTBw9nt0OXV9UzpHamkzbtY4sScnf6qxA3CAyUf5s4EAnlkU5abhmggAE7lyV7ZD36vK UHt1SHejRZGvfdBc1EJwj/ofv4+PZcXTzGiQL/0HsZyhPfwtTDx41iuCEEnEWCEiDgBL LObA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749535365; x=1750140165; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=UDTSk/d8jd23QCU1m5FB65MI3cHXuvlKN2ZGeYOHd0A=; b=GDkHso3zzZjeY0yF5+77R5BGO6B6df4whUKXvmiwisvVSo2dd30xlKkuXKLzr2tNUr oy76VbEqFoXDsek8sXZseqbvbbBHvvc0fCIewXyrnxiBGx8X0XgWWtujSPg1577o9EAR 10ttneh86KJcK2KW4TcaxNV6CyOa2sac2O+AEZKQQV5Q4nrQViYV4y9HnbFFc8G42Dkc 945h8LiGqA8zaEe0MI172HcvEQcUHS/37Sk32jr7Lbb970IqGp/qo5xrKz6pUjr2QYHt Aik7YUZFNE94lQrkNemYmAbLth2V8nAeO7yiO28ltnqJk38j64CTsEWdckdmlgpB+bbV KDCA== X-Forwarded-Encrypted: i=1; AJvYcCVt/syN2rgS0oLWtfIoY/JVe9l6t8r+SlFJe2RCMNTKNqKdY72HG0kBVMaTl/ETiHJjZ/+wAw==@debbugs.gnu.org X-Gm-Message-State: AOJu0YxBUZxG/q1WRwoP6Fs66FdwniGlczl0EzfxuXh2OrOX36cdvfkr KsuJfIE4SE1v41y2YHDTtnFjUhq7xBdbN4t56IZTC/McR8otZ+PfFq5A X-Gm-Gg: ASbGncsNBQ/0fcphsjE6+TFb4SwUQMBwHrAGKBOgWbEO02lx6Ob7CiVghqp/kWJBppv ufz4ZSQa+h/ul42cf8BFDjqop+Wzfw7AAFMapuRtvdNT0aMClPgqzmxvU62T+g+lj+IK5lvd15d 7v0pSYXPmahuhutnzo3wb130ygVzi386qt+xI73kVKM5YQAy7H125zm1YdNCojkC48yR/nqWXD1 xZeRFRUx12FvCLDQLuzO2m+1EcJreTSorOcnXRfiHXigCL7oHv3Hx1Rg1c5GP4yGdiLSZCqZhpC LsgAtot/hFjB9SqnVSpUaNR3ZJSTgH4tf2L1TZIHM4XXhB+ldDyXXjEbYg/kqFMEFl72onDb34S 2lURdTVpU4WFmQ9gjqjJJQlSXTKvtY1OYOvM= X-Google-Smtp-Source: AGHT+IGjbkmeVSdBbwUsPQYTjECiQWZ0BTAzUqcAQ5W9ebTXwDCcVQN6zX6CMov8+pzFZRpXuDpixw== X-Received: by 2002:a17:90b:1f84:b0:311:fc8b:31b5 with SMTP id 98e67ed59e1d1-3134730306bmr26162034a91.14.1749535365325; Mon, 09 Jun 2025 23:02:45 -0700 (PDT) Received: from smtpclient.apple (c-24-4-247-194.hsd1.ca.comcast.net. [24.4.247.194]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-236034050a1sm64195425ad.145.2025.06.09.23.02.44 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 09 Jun 2025 23:02:44 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.500.181.1.5\)) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode From: Yuan Fu In-Reply-To: Date: Mon, 9 Jun 2025 23:02:33 -0700 Content-Transfer-Encoding: quoted-printable Message-Id: References: To: Troy Brown X-Mailer: Apple Mail (2.3826.500.181.1.5) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Eli Zaretskii , Daniel Colascione , 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) > On Jun 7, 2025, at 7:03=E2=80=AFAM, Troy Brown = wrote: >=20 > On Sat, Jun 7, 2025 at 2:09=E2=80=AFAM Yuan Fu = wrote: >>=20 >> So for this tactic, point should move out of the enclosing defun if = it is inside a defun; and if point isn=E2=80=99t inside any defun it = should move to the previous defund-beginning? >=20 > Care must be taken when talking about being "inside" or "not inside" a > defun. Unless point is before, after, or between top-level defuns, it > will always be inside some defun. I previously suggested > differentiating behavior based on whether point was at a defun > boundary. By boundary, I mean point is either immediately before or > immediately after a defun. >=20 > It's also important to point out that classes, namespaces, packages, > etc. could all be defuns, not just functions. Therefore the nesting > as being described is not a pathological exercise, but a much more > common occurrence than one might initially consider. >=20 > As far as behavior, I think the way I've observed it working in > non-Tree-sitter modes was more intuitive than the current Tree-sitter > behavior (but I haven't exhaustively checked). Additionally, I think > it should work as described in the documentation. Much of what I'm > saying was already expressed in Bug#68664. There, I tried to codify > how I believed the non-Tree-sitter modes were behaving and how > intuitively I thought it should work for Tree-sitter modes. >=20 > Regardless of what tactic is configured, `treesit-beginning-of-defun` > must go to the beginning of the enclosing defun when point is not at a > defun boundary. I think this is fundamental or the assumptions made > when using `beginning-of-defun` in the general case no longer hold > (such as its use in `prog-fill-reindent-defun`). I think the tactic > should only come into play when point is already at a defun boundary. Consider that existing code in Emacs isn=E2=80=99t set in stone, it=E2=80=99= s not really that fundamental that beginning-of-defun must work in a way = that makes prog-fill-reindent-defun behave desirably. = prog-fill-reindent-defun uses beginning-of-defun because we don=E2=80=99t = have better choices before tree-sitter. In tree-sitter major modes, what = we=E2=80=99ve been doing is to make the existing commands customizable = so tree-sitter can provide a tree-sitter version of it. We=E2=80=99ve = done this for forward-sexp: we added forward-sexp-function. Some = commands already have customization points long ago, like = beginning-of-defun, which has beginning-of-defun-function. So I added prog-fill-reindent-defun-function and a tree-sitter version = treesit-fill-reindent-defun. The tree-sitter implementation uses = treesit-defun-at-point, so it doesn=E2=80=99t even need to concern with = tactics. Now in tree-sitter major modes, prog-fill-reindent-defun should always = indent the enclosing defun. > After that, I'm less concerned about its behavior, but think the > current `nested` behavior of visiting the previous sibling defun until > there are no more, then visiting the parent defun makes sense. The > key difference is that you only visit the previous sibling if point is > at a defun boundary...otherwise visit the defun containing point. Hmmm, it doesn=E2=80=99t feel very convenient, you=E2=80=99d need to = first adjust your point to be precisely at the boundary, then press = C-M-a/e? IMO that adds too much overhead. I added a tactic = `parent-first` that always move to the beginning/end of the enclosing = defun. People that prefers this kind of defun movement can use this = tactic. >=20 > Furthermore, consider the following `top-level` tactic example using > `c++-ts-mode`. Here, we have a C++ namespace (which is considered a > defun for C++) as well as a "doSomething" function defun within the > namespace. If we place point on the "printf" and press `M-q`, > triggering `prog-fill-reindent-defun`, we'll see that the entire > namespace has been re-indented (including "int i;"). I'd argue that > was not intuitively what I would have expected to happen. Instead, I > would have expected only "doSomething" to have been re-indented. >=20 > ```cpp > // -*- mode: c++-ts > #include >=20 > namespace Hello > { > int i; >=20 > void doSomething(void) > { > printf("doSomething\n"); > } > }; >=20 > // Local Variables: > // treesit-defun-tactic: top-level > // End: > ``` >=20 > If the behavior of `treesit-beginning-of-defun` was to first move to > the beginning of the enclosing defun when point is not at a defun > boundary (as previously described), the expected behavior of only > reindenting "doSomething" would have occurred. If > `treesit-beginning-of-defun` worked the way I propose, and you really > wanted to re-indent the entire namespace, it would have been as simple > as moving to the beginning of the enclosing defun and triggering > `prog-fill-reindent-defun` there (i.e., `C-M-a` `M-q`). >=20 >> Any suggestions for a good name for this tactic? Right now we have = `nested` and `top-level`. >=20 > See above. I don't think a new tactic is necessary, just a change in > how `treesit-beginning-of-defun` works when point is not at a defun > boundary, regardless of the configured tactic. Yuan= From debbugs-submit-bounces@debbugs.gnu.org Tue Jun 10 03:25:01 2025 Received: (at 78703) by debbugs.gnu.org; 10 Jun 2025 07:25:01 +0000 Received: from localhost ([127.0.0.1]:60303 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uOtLw-0005k6-Pk for submit@debbugs.gnu.org; Tue, 10 Jun 2025 03:25:01 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]:60206) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uOtLt-0005ju-Br for 78703@debbugs.gnu.org; Tue, 10 Jun 2025 03:24:58 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID:Date: References:In-Reply-To:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=D3lonF2PFE7iM3EyWv3c4WP3AhDPuUgdHXHB0p0jggA=; b=RLIuiScJXZfndGWBxBTLwMW/ly a+sx8SvrNAJLTuDOiMvFcnhgbd7vUzXKJYgWkb/5Q7YypKIqd0UfA7Hial4eNnCZhO6dg8+zCQS4X MKTXg+B1Sv25ncoBv2s1iOM8nDAXFKFV8S6RqWR14jmLzSnjSabeTjyqdBRUe4t5BjHXi4SSJ+y/7 9LMZBdyLXQRvtscDyvIXhxw4OkzaDXe1likAHMElYdW4YlatU8PZNaHXqfzvHOxxhUkCl01PcTOfS tmTPhtOKoJg6kKBwBTmWQGj178+ZMPQTnc8DORgnuBhzhq6AELNxnv5Rc1g53+brvgVmA2C05Ojtx IeLrNErg==; Received: from dancol by dancol.org with local (Exim 4.96) (envelope-from ) id 1uOtKZ-00BWAl-1H; Tue, 10 Jun 2025 03:23:35 -0400 From: Daniel Colascione To: Yuan Fu Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode In-Reply-To: References: User-Agent: mu4e 1.12.10; emacs 31.0.50 Date: Tue, 10 Jun 2025 00:24:54 -0700 Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Eli Zaretskii , Troy Brown , 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Yuan Fu writes: >> On Jun 7, 2025, at 7:03=E2=80=AFAM, Troy Brown w= rote: >>=20 >> On Sat, Jun 7, 2025 at 2:09=E2=80=AFAM Yuan Fu wrote: >>>=20 >>> So for this tactic, point should move out of the enclosing defun if >>> it is inside a defun; and if point isn=E2=80=99t inside any defun it sh= ould >>> move to the previous defund-beginning? >>=20 >> Care must be taken when talking about being "inside" or "not inside" a >> defun. Unless point is before, after, or between top-level defuns, it >> will always be inside some defun. I previously suggested >> differentiating behavior based on whether point was at a defun >> boundary. By boundary, I mean point is either immediately before or >> immediately after a defun. >>=20 >> It's also important to point out that classes, namespaces, packages, >> etc. could all be defuns, not just functions. Therefore the nesting >> as being described is not a pathological exercise, but a much more >> common occurrence than one might initially consider. >>=20 >> As far as behavior, I think the way I've observed it working in >> non-Tree-sitter modes was more intuitive than the current Tree-sitter >> behavior (but I haven't exhaustively checked). Additionally, I think >> it should work as described in the documentation. Much of what I'm >> saying was already expressed in Bug#68664. There, I tried to codify >> how I believed the non-Tree-sitter modes were behaving and how >> intuitively I thought it should work for Tree-sitter modes. >>=20 >> Regardless of what tactic is configured, `treesit-beginning-of-defun` >> must go to the beginning of the enclosing defun when point is not at a >> defun boundary. I think this is fundamental or the assumptions made >> when using `beginning-of-defun` in the general case no longer hold >> (such as its use in `prog-fill-reindent-defun`). I think the tactic >> should only come into play when point is already at a defun boundary. > > Consider that existing code in Emacs isn=E2=80=99t set in stone, it=E2=80= =99s not > really that fundamental that beginning-of-defun must work in a way > that makes prog-fill-reindent-defun behave > desirably. Experimenting with a different UI paradigm doesn't justify introducing an inconsistency to behavior that's worked well for literally decades. If I'm using, say, c++-ts-mode, my navigation commands should do the same thing they do in c++-mode. Plenty of code as well as muscle memories rely on this behavior. The "tactic" concept is an unnecessary layer of indirection. If operation A takes you to place X and operation B takes you to different place Y, the way to express the difference between operations A and B is to make them _different commands_, not by twiddling some global switch. When you change tree-sitter "strategies" right now, you're silently turning one command into another command, that's confusing for everyone. Please give these "strategies" individual command names. We have beginning-of-defun and beginning-of-defun-comments, not a knob that alters beginning-of-defun. > prog-fill-reindent-defun uses beginning-of-defun because we > don=E2=80=99t have better choices before tree-sitter. In tree-sitter major > modes, what we=E2=80=99ve been doing is to make the existing commands > customizable so tree-sitter can provide a tree-sitter version of > it. Why does there need to be a tree-sitter version of prog-fill-reindent-defun? Isn't it enough that tree-sitter provide the low-level syntactic analysis for prog-fill-reindent-defun to do its job? Why the high level hook? > We=E2=80=99ve done this for forward-sexp: we added > forward-sexp-function. Some commands already have customization points > long ago, like beginning-of-defun, which has > beginning-of-defun-function. Modes use generally these "customization points" to _implement_ the familiar behavior, not to give them random different user-visible semantics. > So I added prog-fill-reindent-defun-function and a tree-sitter version > treesit-fill-reindent-defun. The tree-sitter implementation uses > treesit-defun-at-point, so it doesn=E2=80=99t even need to concern > with tactics. > > Now in tree-sitter major modes, prog-fill-reindent-defun should always > indent the enclosing defun. Which now means prog-fill-reindent-defun can indent something other than what mark-defun highlights? That seems odd to me. Tree sitter's job is syntactic analysis, not UI differentiation. >> After that, I'm less concerned about its behavior, but think the >> current `nested` behavior of visiting the previous sibling defun until >> there are no more, then visiting the parent defun makes sense. The >> key difference is that you only visit the previous sibling if point is >> at a defun boundary...otherwise visit the defun containing point. > > Hmmm, it doesn=E2=80=99t feel very convenient, you=E2=80=99d need to firs= t adjust your > point to be precisely at the boundary, then press C-M-a/e? IMO that > adds too much overhead. I added a tactic `parent-first` that always > move to the beginning/end of the enclosing defun. People that prefers > this kind of defun movement can use this tactic. The default should be to match behavior that's been stable for decades. Use of tree sitter should be an implementation detail for users. If we want to provide UI to better handle nested defuns, this UI should go in prog-mode.el and rely on mode-provided syntactic analysis, not just delegate to a mode function that does different random stuff in each mode. >> Furthermore, consider the following `top-level` tactic example using >> `c++-ts-mode`. Here, we have a C++ namespace (which is considered a >> defun for C++) Namespaces aren't defuns and c++-ts-mode shouldn't be indenting their contents by a level either. c++-ts-mode is unusable without hacks like pragmatically editing the indentation rules in user configuration. >> as well as a "doSomething" function defun within the >> namespace. If we place point on the "printf" and press `M-q`, >> triggering `prog-fill-reindent-defun`, we'll see that the entire >> namespace has been re-indented (including "int i;"). I'd argue that >> was not intuitively what I would have expected to happen. Instead, I >> would have expected only "doSomething" to have been re-indented. Yes, because a namespace isn't a defun. >> If the behavior of `treesit-beginning-of-defun` was to first move to >> the beginning of the enclosing defun when point is not at a defun >> boundary (as previously described), the expected behavior of only >> reindenting "doSomething" would have occurred. If >> `treesit-beginning-of-defun` worked the way I propose, and you really >> wanted to re-indent the entire namespace, it would have been as simple >> as moving to the beginning of the enclosing defun and triggering >> `prog-fill-reindent-defun` there (i.e., `C-M-a` `M-q`). >>=20 >>> Any suggestions for a good name for this tactic? Right now we have `nes= ted` and `top-level`. >>=20 >> See above. I don't think a new tactic is necessary, just a change in >> how `treesit-beginning-of-defun` works when point is not at a defun >> boundary, regardless of the configured tactic. > > Yuan From debbugs-submit-bounces@debbugs.gnu.org Tue Jun 10 08:12:39 2025 Received: (at 78703) by debbugs.gnu.org; 10 Jun 2025 12:12:40 +0000 Received: from localhost ([127.0.0.1]:36581 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uOxqJ-00033d-9r for submit@debbugs.gnu.org; Tue, 10 Jun 2025 08:12:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:33972) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uOxqF-00032c-Ge for 78703@debbugs.gnu.org; Tue, 10 Jun 2025 08:12:36 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uOxq8-00059i-2q; Tue, 10 Jun 2025 08:12:28 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=58ai1zynDlGQWazV66o3ooVjOjYgbqN1FY3Gg/kc6gM=; b=ELyF3lCZjR3OjmBd4uAE z+R2BLR9kHuU/9VXFt1QZDIYg5oB1WlRVUQkXKQMoCaiT0kKXE2RnzQeGCarKQA569HIK0iZnRfXn nHXBTc5lv7BWbOlzsYJgAjGxJeiutuMMksnWtjWhrFQcXnKU71B/EPs7eaN3B4uhOGM8k2wPas4GB GXhGUKPVn69LhauuliNlNTEp8sdRYcif3dpcPuDCr8Zx0PwBQXatgR8+MwsqpyU3VKkp9UKbyS9w5 Yx2GNWBXGs83vtQfkq5bbcsn3V/x2U+6Vv1UIfMysTaQ8Nf7iXcCoWLyfoRbbAaGZewwKsGvVKUG5 xQTARKZMH2CYWQ==; Date: Tue, 10 Jun 2025 15:12:22 +0300 Message-Id: <86cybbg5i1.fsf@gnu.org> From: Eli Zaretskii To: Daniel Colascione In-Reply-To: (message from Daniel Colascione on Tue, 10 Jun 2025 00:24:54 -0700) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode References: MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Daniel Colascione > Cc: Troy Brown , Eli Zaretskii , > 78703@debbugs.gnu.org > Date: Tue, 10 Jun 2025 00:24:54 -0700 > > If I'm using, say, c++-ts-mode, my navigation commands should do the > same thing they do in c++-mode. Plenty of code as well as muscle > memories rely on this behavior. I'm not sure I agree. That c++-mode behaved like that doesn't mean it's the last word, or that nothing can be improved in that behavior. In addition, TS-based modes make certain behaviors very hard (at least not if we base it on the parser information), and OTOH make certain behaviors very easy that were hard with the "traditional" modes. So we should keep an open mind about these aspects, and not automatically demand 110% compatibility to past behavior. > The "tactic" concept is an unnecessary layer of indirection. >From where I stand, it's a new feature that was unavailable in non-TS implementation. > If operation A takes you to place X and operation B takes you to > different place Y, the way to express the difference between operations > A and B is to make them _different commands_, not by twiddling some > global switch. But if the semantics of a command is ambiguous, then a switch makes perfect sense. In this case, what exactly "beginning of defun" means when there are nested defuns is ambiguous. > When you change tree-sitter "strategies" right now, you're silently > turning one command into another command, that's confusing for everyone. > Please give these "strategies" individual command names. We have > beginning-of-defun and beginning-of-defun-comments, not a knob that > alters beginning-of-defun. I don't want to memorize two commands when one will do. That's why we have the various optional behaviors of commands and DWIM-ish variations in their behavior. > > prog-fill-reindent-defun uses beginning-of-defun because we > > don’t have better choices before tree-sitter. In tree-sitter major > > modes, what we’ve been doing is to make the existing commands > > customizable so tree-sitter can provide a tree-sitter version of > > it. > > Why does there need to be a tree-sitter version of > prog-fill-reindent-defun? Because the way to get the indentation information from tree-sitter is significantly different from the ad-hoc ways we do that in "traditional" modes. > Isn't it enough that tree-sitter provide the > low-level syntactic analysis for prog-fill-reindent-defun to do its job? > Why the high level hook? How do you implement anything like c-set-offset or indentation styles based only on low-level syntactic analysis? where will the rest of the necessary information come from, and who and how will apply it? > > We’ve done this for forward-sexp: we added > > forward-sexp-function. Some commands already have customization points > > long ago, like beginning-of-defun, which has > > beginning-of-defun-function. > > Modes use generally these "customization points" to _implement_ the > familiar behavior, not to give them random different > user-visible semantics. I think the point in the above example was that the semantic of "sexp" is ambiguous in any language that is not Lisp. That was (and still is) the hard part of figuring out how forward-sexp should behave in TS-based modes. (In non-TS modes the behavior is just arbitrary nonsense, if you ask me.) > > So I added prog-fill-reindent-defun-function and a tree-sitter version > > treesit-fill-reindent-defun. The tree-sitter implementation uses > > treesit-defun-at-point, so it doesn’t even need to concern > > with tactics. > > > > Now in tree-sitter major modes, prog-fill-reindent-defun should always > > indent the enclosing defun. > > Which now means prog-fill-reindent-defun can indent something other than > what mark-defun highlights? They did subtly different things since long ago. It's clearly visible in the code. > Tree sitter's job is syntactic analysis, not UI differentiation. The way we use syntactic information in this commands is a leaky abstraction: the syntax aspects leak into the UI. So it is a small wonder that tree-sitter affects the UI in some (relatively minor) ways. > The default should be to match behavior that's been stable for decades. As I tried to explain above, I don't necessarily agree. > Use of tree sitter should be an implementation detail for users. Since the introduction of tree-sitter based capabilities into Emacs, we've learned that this simply doesn't work, not in Emacs. Syntax and semantics leak into our UI, and tree-sitter deals with syntactic and semantic information that is sometimes very different from what, e.g., syntax-ppss and friends let us use. So I do understands where you are coming from, but experience taught us that it cannot work that way in Emacs. If we were designing Emacs from scratch today, perhaps we could have done that in a way that would avoid these leaks, but we are not there. > If we want to provide UI to better handle nested defuns, this UI should > go in prog-mode.el and rely on mode-provided syntactic analysis, not > just delegate to a mode function that does different random stuff in > each mode. That'd be a massive rewrite of gobs of existing code, I'm afraid. I invite you to take a look at the existing code and see how it mixes syntax with UI. That's even visible at the level of the command names: "sexp" only makes sense in Lisp, and the notion of "balanced parens" has no place in languages without brackets and braces. > >> Furthermore, consider the following `top-level` tactic example using > >> `c++-ts-mode`. Here, we have a C++ namespace (which is considered a > >> defun for C++) > > Namespaces aren't defuns and c++-ts-mode shouldn't be indenting their > contents by a level either. But c++-mode does indent them. Doesn't this contradict what you said about following past practices? From debbugs-submit-bounces@debbugs.gnu.org Tue Jun 10 11:50:02 2025 Received: (at 78703) by debbugs.gnu.org; 10 Jun 2025 15:50:02 +0000 Received: from localhost ([127.0.0.1]:39249 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uP1Ea-0000xZ-H9 for submit@debbugs.gnu.org; Tue, 10 Jun 2025 11:50:02 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]:41152) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uP1EV-0000wZ-KR for 78703@debbugs.gnu.org; Tue, 10 Jun 2025 11:49:54 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID: References:In-Reply-To:Subject:CC:To:From:Date:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=n2RQ3RzNzz8Y6GVElzmC803M0HPCunuXDZYnOe8Zbls=; b=Malp55oJzU2z1qWSCit/UYlnBc gb/oIV71SWyw523MztvvgFO3AZVZCngafk1idXWTryJHHh2cVacazGZqrtTFmpsDcgdl2IKPrjJF5 VGc+ipNCEqb7CEYFIZ005wlDfGVVZ69redcrv30ne1Lh7CoY+t8toCevG1RwSE4GiLzvdPcRJCop0 TSe14wZWuNBq8VGnc85jwmTx+/OSWhFlLUQ5JFIGJh8DcewiNEDW6DKovzS9kUcVP3FXIFd06bW0z Wl2hUjkPxfg6GpUPBToRR9/OVio2O3mZowgVPoNhdS74oirSlvHZP4ESyqm2+j8KIgoIxfm08NF21 EzSXPuWg==; Received: from [2600:1010:b044:9528:0:4e:46fb:1201] (port=43694 helo=[IPv6:::1]) by dancol.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uP1DB-00BXwU-1x; Tue, 10 Jun 2025 11:48:29 -0400 Date: Tue, 10 Jun 2025 08:49:48 -0700 From: Daniel Colascione To: Eli Zaretskii Subject: =?US-ASCII?Q?Re=3A_bug=2378703=3A_beginning-of-defun_and_f?= =?US-ASCII?Q?riends_still_wrong_in_typescript-ts-mode?= User-Agent: K-9 Mail for Android In-Reply-To: <86cybbg5i1.fsf@gnu.org> References: <86cybbg5i1.fsf@gnu.org> Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On June 10, 2025 5:12:22 AM PDT, Eli Zaretskii wrote: >> From: Daniel Colascione >> Cc: Troy Brown , Eli Zaretskii , >> 78703@debbugs=2Egnu=2Eorg >> Date: Tue, 10 Jun 2025 00:24:54 -0700 >>=20 >> If I'm using, say, c++-ts-mode, my navigation commands should do the >> same thing they do in c++-mode=2E Plenty of code as well as muscle >> memories rely on this behavior=2E > >I'm not sure I agree=2E That c++-mode behaved like that doesn't mean >it's the last word, or that nothing can be improved in that behavior=2E It's not just c++-mode=2E It's how most modes have behaved=2E >In addition, TS-based modes make certain behaviors very hard (at least >not if we base it on the parser information),=20 Very hard how? You can use tree sitter like a more powerful parse partial = sexp=2E It provides strictly more information=2E There is no behavior whats= oever that's harder to implement because tree sitter is giving you more inf= ormation=2E=20 > and OTOH make certain >behaviors very easy that were hard with the "traditional" modes=2E So >we should keep an open mind about these aspects, and not automatically >demand 110% compatibility to past behavior=2E > >> The "tactic" concept is an unnecessary layer of indirection=2E > >>From where I stand, it's a new feature that was unavailable in non-TS >implementation=2E It's not a feature=2E It's a UI and programming annoyance=2E How are you s= upposed to write code against functions with behavior that shifts on a whim= with no stable functions to call instead? What am I supposed to do, let-bind every possible value around every funct= ion call? Why have functions then=2E Let's just have one function with a st= rategy=2E (let ((dwim-strategy 'call-process)) (dwim "date -R")) (let ((dwim-strategy 'switch-to-buffer)) (dwim "*scratch*")) We already have a knob for users to express the concept of what happens wh= en a key is pressed: the command binding mechanism=2E org-mode is annoying in this way too=2E I'm in org mode=2E I want to see w= hat, say, C-tab does=2E I type C-h c C-tab and I get something like "org-dw= im-control-tab"=2E Yeah, that's useful=2E Why bother having keymaps at all? Org made an inner platform for key bindi= ng=2E Inner platforms are bad and hurt generality=2E >> If operation A takes you to place X and operation B takes you to >> different place Y, the way to express the difference between operations >> A and B is to make them _different commands_, not by twiddling some >> global switch=2E > >But if the semantics of a command is ambiguous, then a switch makes >perfect sense=2E In this case, what exactly "beginning of defun" means >when there are nested defuns is ambiguous=2E Yet we use the concept of command names to express different concepts else= where=2E And if the concept is ambiguously defined, provide a minimal knob = to adjust that concept, not change the operation of primitives to be incons= istent with each other=2E=20 >> When you change tree-sitter "strategies" right now, you're silently >> turning one command into another command, that's confusing for everyone= =2E >> Please give these "strategies" individual command names=2E We have >> beginning-of-defun and beginning-of-defun-comments, not a knob that >> alters beginning-of-defun=2E > >I don't want to memorize two commands when one will do=2E That's why we >have the various optional behaviors of commands and DWIM-ish >variations in their behavior=2E This isn't DW*I*M and it's hard to imagine the current default of going to= the previous lexical function beginning being what many people mean=2E >> > prog-fill-reindent-defun uses beginning-of-defun because we >> > don=E2=80=99t have better choices before tree-sitter=2E In tree-sitte= r major >> > modes, what we=E2=80=99ve been doing is to make the existing commands >> > customizable so tree-sitter can provide a tree-sitter version of >> > it=2E >>=20 >> Why does there need to be a tree-sitter version of >> prog-fill-reindent-defun? > >Because the way to get the indentation information from tree-sitter is >significantly different from the ad-hoc ways we do that in >"traditional" modes=2E No it isn't=2E If the defun navigation functions in TS modes had their tra= ditional behavior, they'd continue to work for higher level constructs buil= t on top of them like the prog-mode reindent and mark defun=2E TS modes bro= ke a whole bunch of things that had worked fine for decades, and instead of= fixing them, they just made even more abstractions to plug inconsistent tr= ee sitter things in place of the broken things=2E You apply this procedure repeatedly and you get a new editor, and going by= the defaults I've seen from the TS modes, it's not a better editor=2E=20 >> Isn't it enough that tree-sitter provide the >> low-level syntactic analysis for prog-fill-reindent-defun to do its job= ? >> Why the high level hook? > >How do you implement anything like c-set-offset or indentation styles >based only on low-level syntactic analysis?=20 By using TS to implement c-guess-basic-syntax and friends=2E cc-mode inden= tation styles are clear expressions of user intent=2E No reason at all TS m= odes couldn't respect this intent and merely implement it a different way= =2E Want to know whether you're after a class? Inside a namespace? Where a = declaration begins? You have an AST right there! > where will the rest of the >necessary information come from, and who and how will apply it? From=20the AST=2E Where else? >> > We=E2=80=99ve done this for forward-sexp: we added >> > forward-sexp-function=2E Some commands already have customization poi= nts >> > long ago, like beginning-of-defun, which has >> > beginning-of-defun-function=2E >>=20 >> Modes use generally these "customization points" to _implement_ the >> familiar behavior, not to give them random different >> user-visible semantics=2E > >I think the point in the above example was that the semantic of "sexp" >is ambiguous in any language that is not Lisp=2E That was (and still >is) the hard part of figuring out how forward-sexp should behave in >TS-based modes=2E (In non-TS modes the behavior is just arbitrary >nonsense, if you ask me=2E) Yes, and because it's ambiguous we get annoyances like python-mode's defau= lt sexp movement=2E Now every mode is like that, and you can't turn it off = half the time? The key is the *relationships* better the commands that help users form me= ntal models of what their actions are going to do=2E For example, if blink-= paren-mode highlights the other end of some balanced construct, forward or = backward-sexp will take you there=2E Easy to learn and predict=2E Likewise,= beginning of defun should move to the start of the point that mark-defun h= ighlights, and indent defun should indent the same part of the buffer that = mark-defun highlights=2E That's why it's just weird to have a TS hook specifically for indenting a = defun: it just invites the kind of inconsistency that makes the system hard= to reason about and annoying to work with=2E >> Tree sitter's job is syntactic analysis, not UI differentiation=2E > >The way we use syntactic information in this commands is a leaky >abstraction: the syntax aspects leak into the UI=2E=20 It doesn't have to=2E There is nothing about the additional information TS= provides that *forces* you to implement beginning-of-defun in a way that f= ails to respect program hierarchy=2E That was a choice, and the existence o= f this "strategy" system shows it=2E So it is a small >wonder that tree-sitter affects the UI in some (relatively minor) >ways=2E No, it breaks the UI in unnecessary ways=2E >> The default should be to match behavior that's been stable for decades= =2E > >As I tried to explain above, I don't necessarily agree=2E > >> Use of tree sitter should be an implementation detail for users=2E > >Since the introduction of tree-sitter based capabilities into Emacs, >we've learned that this simply doesn't work, not in Emacs=2E =20 It would work fine if people cared about UI consistency=2E Subtle differen= ces in semantic analysis are to be expected=2E Gross behavioral differences= in long-stable and otherwise consistent commands are not=2E That's like saying cars have inconsistent varying UIs, so when you should = buy an electric car, you should *expect* the steering wheel to be in the ri= ght, rear seat=2E Hey, power train is a leaky abstraction! > Syntax and >semantics leak into our UI, and tree-sitter deals with syntactic and >semantic information that is sometimes very different from what, e=2Eg=2E= , >syntax-ppss and friends let us use=2E > >So I do understands where you are coming from, but experience taught >us that it cannot work that way in Emacs=2E If we were designing Emacs >from scratch today, perhaps we could have done that in a way that >would avoid these leaks, but we are not there=2E > >> If we want to provide UI to better handle nested defuns, this UI should >> go in prog-mode=2Eel and rely on mode-provided syntactic analysis, not >> just delegate to a mode function that does different random stuff in >> each mode=2E > >That'd be a massive rewrite of gobs of existing code, I'm afraid=2E=20 Would it? How? You'd start with a baseline no different way and let gradua= lly increasing lexical and syntactic knowledge provided by modes (perhaps u= sing TS as a backend) add capabilities=2E forward-class, for example, might= just signal in modes that didn't provide a definition of that construct=2E Yes, languages have different ideas about what constitutes a function, but= the idea of nesting constructs is common enough across languages that it o= ught to come with a roughly consistent way to navigate them=2E > I >invite you to take a look at the existing code and see how it mixes >syntax with UI=2E That's even visible at the level of the command >names: "sexp" only makes sense in Lisp, and the notion of "balanced >parens" has no place in languages without brackets and braces=2E > >> >> Furthermore, consider the following `top-level` tactic example using >> >> `c++-ts-mode`=2E Here, we have a C++ namespace (which is considered= a >> >> defun for C++) >>=20 >> Namespaces aren't defuns and c++-ts-mode shouldn't be indenting their >> contents by a level either=2E > >But c++-mode does indent them=2E Doesn't this contradict what you said >about following past practices? In c++-mode, I can turn it off with a documented user knob=2E In c++-ts-mo= de, I have to write fragile hacks to monkeypatch mode internals=2E They're = not the same thing=2E And no matter what indent style I choose in c++-mode,= namespace isn't magically a defun=2E From debbugs-submit-bounces@debbugs.gnu.org Tue Jun 10 12:19:32 2025 Received: (at 78703) by debbugs.gnu.org; 10 Jun 2025 16:19:33 +0000 Received: from localhost ([127.0.0.1]:39294 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uP1hA-0006Eg-JE for submit@debbugs.gnu.org; Tue, 10 Jun 2025 12:19:32 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:52120) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uP1h5-0006Cq-52 for 78703@debbugs.gnu.org; Tue, 10 Jun 2025 12:19:26 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uP1gy-0002xV-Pu; Tue, 10 Jun 2025 12:19:17 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=qgW65h0Oyfuapsn/WiBvYI/qErKFtloXQwRaWPqaNHI=; b=qRGDY2BzMqk6 WOGjr867LOL853mjhXWGCcXBffkNLsFofST7LucmnWdERQgeHo6TbhiIxlrKcPu0qVRjDNKnZekL5 pw+tC63zw+i55RiJSwtHz/FO9p4krpaYyYyVAsie3vIhkywzpJuQVV98s6aF1a6CUgwwF7EVj94Dm 1tRR5oSUx6L8+c0NO9wHAEF1FDbjSH+X33MiQsTvAoJ2xH0jUVHWLGrksoeY+cgiJprytCawaEo/c Y5+cwfJtSX2LrmqhYghIuSPbs8bkLDQ8W0VXHvm9GUm6u7U7/zDnF8jpTyoMA3OeHmTCxg4O66ub0 4m24k9q74UZbpTE0kunXVg==; Date: Tue, 10 Jun 2025 19:19:03 +0300 Message-Id: <861prrfu2w.fsf@gnu.org> From: Eli Zaretskii To: Daniel Colascione In-Reply-To: (message from Daniel Colascione on Tue, 10 Jun 2025 08:49:48 -0700) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode References: <86cybbg5i1.fsf@gnu.org> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > Date: Tue, 10 Jun 2025 08:49:48 -0700 > From: Daniel Colascione > CC: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org > > >> If I'm using, say, c++-ts-mode, my navigation commands should do the > >> same thing they do in c++-mode. Plenty of code as well as muscle > >> memories rely on this behavior. > > > >I'm not sure I agree. That c++-mode behaved like that doesn't mean > >it's the last word, or that nothing can be improved in that behavior. > > It's not just c++-mode. It's how most modes have behaved. > > >In addition, TS-based modes make certain behaviors very hard (at least > >not if we base it on the parser information), > > Very hard how? You can use tree sitter like a more powerful parse partial sexp. It provides strictly more information. Not really, not when you look closely. The tools we've built before tree-sitter are ad-hoc, so they allow us to provide information that parsers don't have and don't need to have. Our syntax tables are not exactly "less efficient parsing", and regular expressions allow us to match whatever we want and call that anything we want. Take the DEFUN recognition by CC mode as an example. Tree-sitter knows nothing about them. So "strictly more information" is perhaps an expectation, but it breaks at closer looking. > There is no behavior whatsoever that's harder to implement because tree sitter is giving you more information. I invite you to look at c-ts-mode sources. You will see plenty of what was "harder to implement". We still lack some useful functionalities that are present in CC Mode, for that very reason; what was easy to implement was done long ago. > >> The "tactic" concept is an unnecessary layer of indirection. > > > >From where I stand, it's a new feature that was unavailable in non-TS > >implementation. > > It's not a feature. It's a UI and programming annoyance. How are you supposed to write code against functions with behavior that shifts on a whim with no stable functions to call instead? We've been doing that since day one: you write code that looks at the variables to figure out what behavior to expect, or you write code that is general enough to not care. > What am I supposed to do, let-bind every possible value around every function call? Sometimes, yes. Although hopefully not so frequently and not "every possible value". > Why have functions then. Let's just have one function with a strategy. Arguments "ad absurdum" are not always useful. In this case, no one is calling for such an extremity. But sometimes this has to be done. > >But if the semantics of a command is ambiguous, then a switch makes > >perfect sense. In this case, what exactly "beginning of defun" means > >when there are nested defuns is ambiguous. > > Yet we use the concept of command names to express different concepts elsewhere. And if the concept is ambiguously defined, provide a minimal knob to adjust that concept, not change the operation of primitives to be inconsistent with each other. I think we do the former, or at least we try. > >> Why does there need to be a tree-sitter version of > >> prog-fill-reindent-defun? > > > >Because the way to get the indentation information from tree-sitter is > >significantly different from the ad-hoc ways we do that in > >"traditional" modes. > > No it isn't. If the defun navigation functions in TS modes had their traditional behavior, they'd continue to work for higher level constructs built on top of them like the prog-mode reindent and mark defun. TS modes broke a whole bunch of things that had worked fine for decades, and instead of fixing them, they just made even more abstractions to plug inconsistent tree sitter things in place of the broken things. Indentation is a lot more than just navigation. And I disagree with you extreme interpretation of the current state of indentation and navigation support in TS-based modes. > >How do you implement anything like c-set-offset or indentation styles > >based only on low-level syntactic analysis? > > By using TS to implement c-guess-basic-syntax and friends. Did you look at the implementation of how c-set-offset encode indentation information? Did you try to think how to get the same information from tree-sitter? If you did, and found the way, how about implementing c-ts-set-offset? I Think it's sorely missed. > cc-mode indentation styles are clear expressions of user intent. No reason at all TS modes couldn't respect this intent and merely implement it a different way. Want to know whether you're after a class? Inside a namespace? Where a declaration begins? You have an AST right there! Sorry, this is simplification. A typical declaration breaks down into smaller parts, and we have expectations and ideas about indentation of each one of them. But the tree-sitter classification of the AST constituents does not necessarily make that easy, because you could have the same syntactic symbol both inside a declaration and in other places. So having an AST does not always immediately tell you how to indent correctly. > > where will the rest of the > >necessary information come from, and who and how will apply it? > > From the AST. Where else? See above. > >I think the point in the above example was that the semantic of "sexp" > >is ambiguous in any language that is not Lisp. That was (and still > >is) the hard part of figuring out how forward-sexp should behave in > >TS-based modes. (In non-TS modes the behavior is just arbitrary > >nonsense, if you ask me.) > > Yes, and because it's ambiguous we get annoyances like python-mode's default sexp movement. Now every mode is like that, and you can't turn it off half the time? What else did you expect? Some users like one style, others like the other. Are we supposed to say "my way or the highway"? And that's even before we consider that the disagreement cuts through the developers themselves. I find continuing this kind of argument not constructive, so I will stop here. Let me just say that I think you are looking at this stuff from some semi-abstract, almost idealistic, aspect. As if we didn't have 40 years of development and user experience and expectations to keep and uphold. > >> >> Furthermore, consider the following `top-level` tactic example using > >> >> `c++-ts-mode`. Here, we have a C++ namespace (which is considered a > >> >> defun for C++) > >> > >> Namespaces aren't defuns and c++-ts-mode shouldn't be indenting their > >> contents by a level either. > > > >But c++-mode does indent them. Doesn't this contradict what you said > >about following past practices? > > In c++-mode, I can turn it off with a documented user knob. You've changed the subject. But by all means, let's add such a knob to c++-ts-mode, sure. > In c++-ts-mode, I have to write fragile hacks to monkeypatch mode internals. They're not the same thing. And no matter what indent style I choose in c++-mode, namespace isn't magically a defun. But beginning-of-defun nevertheless takes me to the beginning of the namespace in c++-mode. From debbugs-submit-bounces@debbugs.gnu.org Tue Jun 10 12:56:10 2025 Received: (at 78703) by debbugs.gnu.org; 10 Jun 2025 16:56:10 +0000 Received: from localhost ([127.0.0.1]:39365 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uP2Gf-0004o8-Di for submit@debbugs.gnu.org; Tue, 10 Jun 2025 12:56:10 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]:57124) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uP2Ga-0004nU-T8 for 78703@debbugs.gnu.org; Tue, 10 Jun 2025 12:56:07 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID: References:In-Reply-To:Subject:CC:To:From:Date:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=bvEpK2I8oL2edqGizAsjidYhp92dZ2/pGbcAbXYu3qs=; b=Jdly7cKfbZdZvHgGKBVY5FWUlx woM60XCnVXxy9/gYY60lO1DoF5u3DtTA90ldG2GjlrSQ/56Wx1BlBnZP8enEa6qjtyh1ifcWi4SFG LHgqDx/DqHHy6+nD1sEYFOv8iai0bTu8l5reTslS+spEGMJgOgJjO6qoDTDI+B1ToqSWZQjek8yW4 TtPlTd80D+cwcrDQHhqXNEWNovBE1FfZ3ApETg71xlqfkMDFsWh/Z3rpmN4DI8mCmiWPUONGvdP1D qqUziM0QbzVeTbxWDclP6CDA0rEhWR6PNLdH0Ws1xrC6n6sdqPJDOrFLXfV9+BwXmUY0tSHcNQofk pXx+SKaA==; Received: from [2600:1010:b044:9528:0:4e:46fb:1201] (port=39444 helo=[IPv6:::1]) by dancol.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uP2FG-00BY86-1s; Tue, 10 Jun 2025 12:54:42 -0400 Date: Tue, 10 Jun 2025 09:55:59 -0700 From: Daniel Colascione To: Eli Zaretskii Subject: =?US-ASCII?Q?Re=3A_bug=2378703=3A_beginning-of-defun_and_f?= =?US-ASCII?Q?riends_still_wrong_in_typescript-ts-mode?= User-Agent: K-9 Mail for Android In-Reply-To: <861prrfu2w.fsf@gnu.org> References: <86cybbg5i1.fsf@gnu.org> <861prrfu2w.fsf@gnu.org> Message-ID: <320605B2-AAB5-44EA-805A-185FAEBAC986@dancol.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On June 10, 2025 9:19:03 AM PDT, Eli Zaretskii wrote: >> Date: Tue, 10 Jun 2025 08:49:48 -0700 >> From: Daniel Colascione >> CC: casouri@gmail=2Ecom, brownts@troybrown=2Edev, 78703@debbugs=2Egnu= =2Eorg >>=20 >> >> If I'm using, say, c++-ts-mode, my navigation commands should do the >> >> same thing they do in c++-mode=2E Plenty of code as well as muscle >> >> memories rely on this behavior=2E >> > >> >I'm not sure I agree=2E That c++-mode behaved like that doesn't mean >> >it's the last word, or that nothing can be improved in that behavior= =2E >>=20 >> It's not just c++-mode=2E It's how most modes have behaved=2E >>=20 >> >In addition, TS-based modes make certain behaviors very hard (at least >> >not if we base it on the parser information),=20 >>=20 >> Very hard how? You can use tree sitter like a more powerful parse parti= al sexp=2E It provides strictly more information=2E > >Not really, not when you look closely=2E The tools we've built before >tree-sitter are ad-hoc, so they allow us to provide information that >parsers don't have and don't need to have=2E Our syntax tables are not >exactly "less efficient parsing", and regular expressions allow us to >match whatever we want and call that anything we want=2E There is nothing one bit of information available to c-mode not available = to c-ts-mode=2E >Take the DEFUN recognition by CC mode as an example=2E Tree-sitter >knows nothing about them=2E > >So "strictly more information" is perhaps an expectation, but it >breaks at closer looking=2E > >> There is no behavior whatsoever that's harder to implement because tree= sitter is giving you more information=2E=20 > >I invite you to look at c-ts-mode sources=2E You will see plenty of >what was "harder to implement"=2E That's a choice=2E > We still lack some useful >functionalities that are present in CC Mode, forrea that very reason; >what was easy to implement was done long ago=2E That's the opposite of reality=2E Alan and others have spent years buildin= g a flexible and fast backtracking syntactic analyser for CC mode=2E Tree s= itter does the same thing but in a more general way, in native code for bet= ter performance=2E Its availability makes doing what cc-mode does easier, n= ot harder=2E >> >> The "tactic" concept is an unnecessary layer of indirection=2E >> > >> >From where I stand, it's a new feature that was unavailable in non-TS >> >implementation=2E >>=20 >> It's not a feature=2E It's a UI and programming annoyance=2E How are yo= u supposed to write code against functions with behavior that shifts on a w= him with no stable functions to call instead? > >We've been doing that since day one: you write code that looks at the >variables to figure out what behavior to expect, or you write code >that is general enough to not care=2E I can't wait to program against our glorious new dwim function=2E The prob= lem with let binding the world is that the set of dynamic inputs becomes un= bounded=2E What if I just bind the strategy option and one day TS introduce= s, say, a new sub-strategy option that makes the function I call behave dif= ferently? To the extent possible, and in the strategy case for TS mode it's certainl= y possible, commands should do one thing and if you want to do a different = thing, you run a different command=2E >> What am I supposed to do, let-bind every possible value around every fu= nction call? > >Sometimes, yes=2E Although hopefully not so frequently and not "every >possible value"=2E > >> Why have functions then=2E Let's just have one function with a strategy= =2E > >Arguments "ad absurdum" are not always useful=2E In this case, no one >is calling for such an extremity=2E But sometimes this has to be done=2E > >> >But if the semantics of a command is ambiguous, then a switch makes >> >perfect sense=2E In this case, what exactly "beginning of defun" mean= s >> >when there are nested defuns is ambiguous=2E >>=20 >> Yet we use the concept of command names to express different concepts e= lsewhere=2E And if the concept is ambiguously defined, provide a minimal kn= ob to adjust that concept, not change the operation of primitives to be inc= onsistent with each other=2E=20 > >I think we do the former, or at least we try=2E Then let's make separate commands to express moving to a defun boundary on= e way versus another way and let users express their preference for connect= ing input to action using keymaps=2E >> >> Why does there need to be a tree-sitter version of >> >> prog-fill-reindent-defun? >> > >> >Because the way to get the indentation information from tree-sitter is >> >significantly different from the ad-hoc ways we do that in >> >"traditional" modes=2E >>=20 >> No it isn't=2E If the defun navigation functions in TS modes had their = traditional behavior, they'd continue to work for higher level constructs b= uilt on top of them like the prog-mode reindent and mark defun=2E TS modes = broke a whole bunch of things that had worked fine for decades, and instead= of fixing them, they just made even more abstractions to plug inconsistent= tree sitter things in place of the broken things=2E > >Indentation is a lot more than just navigation=2E And I disagree with >you extreme interpretation of the current state of indentation and >navigation support in TS-based modes=2E I'm right=2E >> >How do you implement anything like c-set-offset or indentation styles >> >based only on low-level syntactic analysis?=20 >>=20 >> By using TS to implement c-guess-basic-syntax and friends=2E > >Did you look at the implementation of how c-set-offset encode >indentation information? Did you try to think how to get the same >information from tree-sitter? If you did, and found the way, how >about implementing c-ts-set-offset? I Think it's sorely missed=2E > >> cc-mode indentation styles are clear expressions of user intent=2E No r= eason at all TS modes couldn't respect this intent and merely implement it = a different way=2E Want to know whether you're after a class? Inside a name= space? Where a declaration begins? You have an AST right there! > >Sorry, this is simplification=2E A typical declaration breaks down into >smaller parts, and we have expectations and ideas about indentation of >each one of them=2E But the tree-sitter classification of the AST >constituents does not necessarily make that easy, because you could >have the same syntactic symbol both inside a declaration and in other >places=2E So having an AST does not always immediately tell you how to >indent correctly=2E No, but it gives you more information than looking-at does, and cc-mode do= es its job admirable given only that simple tool=2E You can look at nesting= and context in the TS AST to figure out what to do=2E >> > where will the rest of the >> >necessary information come from, and who and how will apply it? >>=20 >> From the AST=2E Where else? > >See above=2E > >> >I think the point in the above example was that the semantic of "sexp" >> >is ambiguous in any language that is not Lisp=2E That was (and still >> >is) the hard part of figuring out how forward-sexp should behave in >> >TS-based modes=2E (In non-TS modes the behavior is just arbitrary >> >nonsense, if you ask me=2E) >>=20 >> Yes, and because it's ambiguous we get annoyances like python-mode's de= fault sexp movement=2E Now every mode is like that, and you can't turn it o= ff half the time? > >What else did you expect? Some users like one style, others like the >other=2E Are we supposed to say "my way or the highway"? And that's >even before we consider that the disagreement cuts through the >developers themselves=2E No=2E I'm expecting a generally consistent experience, and if we want to p= rovide a configuration knob, it should affect everything consistently=2E On= e shouldn't have to form independent and different muscle memory for each l= anguage mode because the whims of their authors were different=2E >I find continuing this kind of argument not constructive, so I will >stop here=2E Let me just say that I think you are looking at this stuff >from some semi-abstract, almost idealistic, aspect=2E As if we didn't >have 40 years of development and user experience and expectations to >keep and uphold=2E I'll never understand the mindset that holds that things making sense and = having a structure is bad actually because sense and structure are "academi= c" and "idealistic"=2E What 40 years of development and user experience holds is that if I'm four= pages deep into a nasty TypeScript function and hit beginning-of-defun, I = want to go to the beginning of the four page defun I am editing and not som= e random place two pages up that I didn't even know about in which someone = scribbled out some kind of nested lambda irrelevant to my present task=2E >> >> >> Furthermore, consider the following `top-level` tactic example us= ing >> >> >> `c++-ts-mode`=2E Here, we have a C++ namespace (which is conside= red a >> >> >> defun for C++) >> >>=20 >> >> Namespaces aren't defuns and c++-ts-mode shouldn't be indenting thei= r >> >> contents by a level either=2E >> > >> >But c++-mode does indent them=2E Doesn't this contradict what you sai= d >> >about following past practices? >>=20 >> In c++-mode, I can turn it off with a documented user knob=2E > >You've changed the subject=2E But by all means, let's add such a knob >to c++-ts-mode, sure=2E > >> In c++-ts-mode, I have to write fragile hacks to monkeypatch mode inter= nals=2E They're not the same thing=2E And no matter what indent style I cho= ose in c++-mode, namespace isn't magically a defun=2E > >But beginning-of-defun nevertheless takes me to the beginning of the >namespace in c++-mode=2E From debbugs-submit-bounces@debbugs.gnu.org Tue Jun 10 15:12:18 2025 Received: (at 78703) by debbugs.gnu.org; 10 Jun 2025 19:12:19 +0000 Received: from localhost ([127.0.0.1]:39601 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uP4OJ-0003EZ-5z for submit@debbugs.gnu.org; Tue, 10 Jun 2025 15:12:18 -0400 Received: from mail-pl1-x62f.google.com ([2607:f8b0:4864:20::62f]:58533) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1uP4O0-0003At-Ud for 78703@debbugs.gnu.org; Tue, 10 Jun 2025 15:12:04 -0400 Received: by mail-pl1-x62f.google.com with SMTP id d9443c01a7336-234fcadde3eso68798155ad.0 for <78703@debbugs.gnu.org>; Tue, 10 Jun 2025 12:11:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1749582706; x=1750187506; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=q7gnA/zKgiugPa/zdUA9RSbdTM78Uwer6di0yuCWCK0=; b=b8rLNGcYGnh29EKj+TkT3+dnXWoovX5yovccbOKq3veKi9gd8To6QvgpTpxHvfHc4l SjUNAnUsD3nTQE2QMmDfK8U3YgP45lFP6/WP0+mCzJHnT6cLtqREIP+G62cXTP9uaBnK bpb8QiOsebmr+OhN+kh5gYqeDUCFG3EFlggAx8nmx63fE3m0aR5LC8vrPqfxkvrJ+SMI svreZ/saeHQ0OcGH+WxSIenBMBc6TaYsH1if5FZulTUf540yaPMp2l3SNBlXbmKldfPZ Pwh1o2akdeyh6DJf5CPz5DEpoeoPEgexN+fkx63A48ZzN9WeFjETg3z5DEX6m7I3tAeZ deww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1749582706; x=1750187506; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=q7gnA/zKgiugPa/zdUA9RSbdTM78Uwer6di0yuCWCK0=; b=GncMvgSwqx7Mtfdnh2Hrkz3HH0SNFHM10R8hK1CmrxjVBDuZSvpvVSkvH+0z+eBuwj FHqNKgokzFE+EiwSaQTel3NhDNC5xqUEvdUtJ7VXTiol+4pXQ3E6Cvnu0vm0AqhPG+bv hcA6AFj2KsMeHGx381d2YDDqzVRS8XuGQ0wenzkgLP0uC5KPxIBXFgMunF2od8J5tnQd QIgm2pob99iOOgHIG32RHEJkcGc1GTnHzK8/6u24R27IynJK65ylRxu4JQpS5J3WA1JN pJXqJxZBfXwZYQOy9EsAtaBQF7WkpY0mXUFuhFb6nOh6F1xCw9qiLa0y4T5aj9IwB4BB e/3Q== X-Forwarded-Encrypted: i=1; AJvYcCUyXzdeUhxv4E1hEhTfl07avpddpgt6TTZLC5DkVKbt8H2TnIp5Uf3LCT7GRIyL8IRXvoFOcg==@debbugs.gnu.org X-Gm-Message-State: AOJu0YwoiJxKzdiGkx8oBFr4Zlu3ljT6XIiyqe6AYV3go79RN484pNQP vBkFuh4mW3wp6+R4X2v9D84Gw2eP5SSoU3VLweovSXidFiFmrxdRE+XA X-Gm-Gg: ASbGncsEJY6cqJ0yAPK9cLZfWYhqcsiziTteZJ8Nu31IMHP+VUUk4R35PRHkc/LfCze 1ap0/rsWeBzCOWgX3lUa50jDEGpUzj4lRotR2lZ7b1MP5Nern2P3aJQod78b0gzdzIo8kc0UIq2 dhaekt23OoWl3S28QXnXWc3VLrhm4aqg85TRZ7I4qUQV8zpgG3Ozb7+KcJQsChicYvMGvtY6LA0 AmkBalaybFfVLn/rfFEF0/olCBJR8aZrhB5gQme2DbyV1cyToHPYGdsMtmWKhf3m2smyb9PmfAT k0gIkZG3aUsFT5RGtxPsQ/nLpQBpLKKmHmNxv/hmYwgLr/LDAMTry9y35l2TUiug/HIQi4bookd AUEtv4tViiRWc/tFpDdssEh7QY2h1uQ1lNEo= X-Google-Smtp-Source: AGHT+IHC1auFVMbTHu9BJfRu2Y5xRBxWoG8EIZ5lRNDplTIwTW80oMomAv/oAXoKdKV20DBS4RXiBg== X-Received: by 2002:a17:902:f54c:b0:235:ea0d:ae10 with SMTP id d9443c01a7336-23641a9a44amr7059435ad.12.1749582706193; Tue, 10 Jun 2025 12:11:46 -0700 (PDT) Received: from smtpclient.apple (c-24-4-247-194.hsd1.ca.comcast.net. [24.4.247.194]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-23603078175sm73852265ad.9.2025.06.10.12.11.45 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 10 Jun 2025 12:11:45 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.500.181.1.5\)) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode From: Yuan Fu In-Reply-To: Date: Tue, 10 Jun 2025 12:11:34 -0700 Content-Transfer-Encoding: quoted-printable Message-Id: <36BD3D50-4EE7-438E-9548-A1251E80171C@gmail.com> References: To: Daniel Colascione X-Mailer: Apple Mail (2.3826.500.181.1.5) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Eli Zaretskii , Troy Brown , 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) I=E2=80=99m hesitant to get into another long debate, but let me give my = two cents. >> Consider that existing code in Emacs isn=E2=80=99t set in stone, = it=E2=80=99s not >> really that fundamental that beginning-of-defun must work in a way >> that makes prog-fill-reindent-defun behave >> desirably. >=20 > Experimenting with a different UI paradigm doesn't justify introducing > an inconsistency to behavior that's worked well for literally decades. > If I'm using, say, c++-ts-mode, my navigation commands should do the > same thing they do in c++-mode. Plenty of code as well as muscle > memories rely on this behavior. >=20 > The "tactic" concept is an unnecessary layer of indirection. > If operation A takes you to place X and operation B takes you to > different place Y, the way to express the difference between = operations > A and B is to make them _different commands_, not by twiddling some > global switch. c-defun-tactic exists since Emacs 24, treesit-defun-tactic is actually = modeled after it. Treesit-defun-tactic=E2=80=99s `top-level` and = `nested` corresponds to c-defun-tactic=E2=80=99s `t` and `go-outward`. = The only difference is that tree-sitter defaults to the `nested` option. = So we=E2=80=99re not breaking the UI paradigm as you imagined. Also = c++-ts-mode is a new separate mode, and provides vastly different = features to c++-mode, so some difference is warranted. A lot of features in c++-mode is missing simply because we don=E2=80=99t = have the resource to recreate them in c++-ts-mode. After all, Alan and = others spend decades developing c++-mode. We also can=E2=80=99t just = build c++-ts-mode on top of c++-mode because the engine in c++ mode is = very heavy (meaning slow), if we use both tree-sitter parser (which has = its own overhead) and the cc engine, it=E2=80=99ll be even slower than = c++-mode for not much benefit. It just makes no sense. Also, cc-mode is a huge codebase, and I don=E2=80=99t have expertise in = it. If Alan or some other cc-mode expert decides to incorporate = tree-sitter into cc-mode, they might get strictly more information as = you claimed. But I and other people willing to work on c++-ts-mode = don=E2=80=99t have that ability. (Also Theo is the maintainer of c++-ts-mode, I=E2=80=99m just a = co-maintainer trying to fix things up when he=E2=80=99s not available.) > When you change tree-sitter "strategies" right now, you're silently > turning one command into another command, that's confusing for = everyone. > Please give these "strategies" individual command names. We have > beginning-of-defun and beginning-of-defun-comments, not a knob that > alters beginning-of-defun. Using variables to alter a commands behavior is a very well accepted = practice, it=E2=80=99s everywhere in Emacs. Both approach are equally = valid and are suitable for difference circumstances. In our case, = there=E2=80=99s already the long-existed tactic concept so we want to = keep to it, and also people usually only want the command behave one way = or another, so they can just set the variable and be done with it. = Multiple commands are more suitable for cases where the user wants to = use different behaviors in the same time, then they can bind each = command to different keys. Multiple commands have their own downsides = like more hassle to configure and harder to discover, so they=E2=80=99re = not strictly better. >> prog-fill-reindent-defun uses beginning-of-defun because we >> don=E2=80=99t have better choices before tree-sitter. In tree-sitter = major >> modes, what we=E2=80=99ve been doing is to make the existing commands >> customizable so tree-sitter can provide a tree-sitter version of >> it. >=20 > Why does there need to be a tree-sitter version of > prog-fill-reindent-defun? Isn't it enough that tree-sitter provide = the > low-level syntactic analysis for prog-fill-reindent-defun to do its = job? > Why the high level hook? If we want to use a lower-level abstraction, we=E2=80=99d need to create = some framework to get the defun at point, and add a tree-sitter provider = of it. That just brings a whole can of worms: what should this API look = like exactly? Should we change all other existing functions (many of = which are hundred line monsters that are hard to understand and refactor = without introducing breakage) to use this new framework? Should it limit = to only defun, or should it support other constructs? If we want to = support other constructs, how do we implement the provider for those = constructs in non-tree-sitter settings? Many other functions that use = beginning/end-of-defun needs more than getting the defun at point, they = might want to know if point is at the beginning of a defun, they might = want to know if there=E2=80=99s another defun after this one. How do we = design the framework so these requests are met? For the reasons above, thing-at-point isn=E2=80=99t really suitable for = our purpose, or at least we need to make significant changes to its API = to make it suitable. Thing-at-point is mostly a simple API to get = things like url and symbol and word at point, not something that can = give us rich information of syntactic construct at point. You might think prog-fill-reindent-defun can just use tree-sitter = functions to get syntax information, but that=E2=80=99s a big no-no. = Existing Emacs features like imenu, font-lock, prog-fill-reindent-defun, = etc, shouldn=E2=80=99t even know about tree-sitter, they are user-facing = and only provide customization points for major = modes/tree-sitter/eglot/etc to plugin and provide functionality. So things aren=E2=80=99t that simple if you start thinking about how to = actually doing it. If you can design something that give the right = abstraction that major mode/tree-sitter/eglot/etc can plugin to, and can = make it work for both non-tree-sitter and tree-sitter, and potential = future tools that provide parse trees, I=E2=80=99ll be very happy, = because we do want that. So given all that consideration, I decided to go with a higher-level = abstraction you saw. After my refactor of prog-fill-reindent-defun, = reimplementing it for tree-sitter is just 8 lines of code. The small = code duplication is perfectly acceptable IMO. A higher-level abstraction = also has plenty benefits: major modes can define their own version if = it=E2=80=99s necessary, we have more freedom in our implementation = because there=E2=80=99s a looser coupling, etc. >=20 >> We=E2=80=99ve done this for forward-sexp: we added >> forward-sexp-function. Some commands already have customization = points >> long ago, like beginning-of-defun, which has >> beginning-of-defun-function. >=20 > Modes use generally these "customization points" to _implement_ the > familiar behavior, not to give them random different > user-visible semantics. Let me also reply to your later messages here: > It's not a feature. It's a UI and programming annoyance. How are you = supposed to write code against functions with behavior that shifts on a = whim with no stable functions to call instead? >=20 > Yet we use the concept of command names to express different concepts = elsewhere. And if the concept is ambiguously defined, provide a minimal = knob to adjust that concept, not change the operation of primitives to = be inconsistent with each other.=20 I agree that beginning/end-of-defun has evolved into a kind of primitive = function for getting the defun at point, because we didn=E2=80=99t have = a parse tree or an API for getting defun at point. But I disagree your = conclusion that one can=E2=80=99t write code against = beginning/end-of-defun that can change behavior. I mean, that=E2=80=99s = the point of abstraction, no? User can choose they want top-level or = nested kind of defun, and by changing that, all the functions that use = beginning/end-of-defun automatically switch to the chosen behavior. = Isn=E2=80=99t that better than having no choice? But of course there'll be cases where the abstraction doesn=E2=80=99t = work, like prog-fill-reindent-defun. It=E2=80=99s mostly because = beginning/end-of-defun is a god awful abstraction, but that=E2=80=99s = what all the existing functions use and we have to live with it, until = someone creates a better abstraction and refactor all the existing = functions to use it. Anyway, in cases where the abstraction doesn=E2=80=99= t work well, we just need to do a bit more to make it work, and I added = prog-fill-reindent-defun-function.=20 >> So I added prog-fill-reindent-defun-function and a tree-sitter = version >> treesit-fill-reindent-defun. The tree-sitter implementation uses >> treesit-defun-at-point, so it doesn=E2=80=99t even need to concern >> with tactics. >>=20 >> Now in tree-sitter major modes, prog-fill-reindent-defun should = always >> indent the enclosing defun. >=20 > Which now means prog-fill-reindent-defun can indent something other = than > what mark-defun highlights? That seems odd to me. Tree sitter's job = is > syntactic analysis, not UI differentiation. >=20 >>> After that, I'm less concerned about its behavior, but think the >>> current `nested` behavior of visiting the previous sibling defun = until >>> there are no more, then visiting the parent defun makes sense. The >>> key difference is that you only visit the previous sibling if point = is >>> at a defun boundary...otherwise visit the defun containing point. >>=20 >> Hmmm, it doesn=E2=80=99t feel very convenient, you=E2=80=99d need to = first adjust your >> point to be precisely at the boundary, then press C-M-a/e? IMO that >> adds too much overhead. I added a tactic `parent-first` that always >> move to the beginning/end of the enclosing defun. People that prefers >> this kind of defun movement can use this tactic. >=20 > The default should be to match behavior that's been stable for = decades. > Use of tree sitter should be an implementation detail for users. >=20 > If we want to provide UI to better handle nested defuns, this UI = should > go in prog-mode.el and rely on mode-provided syntactic analysis, As I described above, it=E2=80=99s not as simple as you imagined. > not > just delegate to a mode function that does different random stuff in > each mode. If the mode use tree-sitter provided default (which they 99.99% will), = the behavior is well defined. Even if major mode decide to provide their = own version, I trust the major mode author to know what they=E2=80=99re = doing and have a good reason to implement their own, and provide a = function that fits the docstring of prog-fill-reindent-defun. So no, it = won=E2=80=99t be random stuff. >>> Furthermore, consider the following `top-level` tactic example using >>> `c++-ts-mode`. Here, we have a C++ namespace (which is considered a >>> defun for C++) >=20 > Namespaces aren't defuns and c++-ts-mode shouldn't be indenting their > contents by a level either. c++-ts-mode is unusable without hacks = like > pragmatically editing the indentation rules in user configuration. If it=E2=80=99s a bug in the indentation rule, we can fix it. But can = you open another bug report and describe what exactly is wrong? Yuan= From debbugs-submit-bounces@debbugs.gnu.org Tue Jun 10 16:12:25 2025 Received: (at 78703) by debbugs.gnu.org; 10 Jun 2025 20:12:25 +0000 Received: from localhost ([127.0.0.1]:40928 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uP5Ka-0000wl-IH for submit@debbugs.gnu.org; Tue, 10 Jun 2025 16:12:25 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]:49912) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uP5KX-0000wY-LT for 78703@debbugs.gnu.org; Tue, 10 Jun 2025 16:12:23 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Transfer-Encoding:Content-Type:MIME-Version:Message-ID: References:In-Reply-To:Subject:CC:To:From:Date:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=3zJLY+lOAcPW1ya9d/mawJTy/xZC8h9Bv74PLo5I6sY=; b=IirskLASeV+FQ6tl44ypBnhxX3 zig4grzIrlv6raG8m9KGmzr3pTzfPKUmDXvPdboROkiu1ekGn7qBbgKkpwchauxwph9wGPhPMkgJY EosU3nJIZA+CRv2O/NMD9DhbGNZ0H8pMGgsmhg9GeEwVYVuGLee1rbUw2g1jSRkerbu/Hb/kjDf+V NXHrWkG7X1AqrUHdU7xYoDwB1MvIh0XLZl7EUYPwXAmlOPcXo0bFW1wpflLE34Kl7Q3afSSf31YB6 dq35+jQu62CjbLRJjpXVYJwKg4SZz6YiDaJq+Y5ShI/zysdlohtPpEdgkEvesg5jpJ2da3ktM4REt OG2Hc3sg==; Received: from [2600:1010:b044:9528:0:4e:46fb:1201] (port=57316 helo=[IPv6:::1]) by dancol.org with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1uP5JC-00BZOk-2Q; Tue, 10 Jun 2025 16:10:58 -0400 Date: Tue, 10 Jun 2025 13:12:18 -0700 From: Daniel Colascione To: Yuan Fu Subject: =?US-ASCII?Q?Re=3A_bug=2378703=3A_beginning-of-defun_and_f?= =?US-ASCII?Q?riends_still_wrong_in_typescript-ts-mode?= User-Agent: K-9 Mail for Android In-Reply-To: <36BD3D50-4EE7-438E-9548-A1251E80171C@gmail.com> References: <36BD3D50-4EE7-438E-9548-A1251E80171C@gmail.com> Message-ID: <177D3B4D-A395-4D2F-82D8-9CEDE39E6B58@dancol.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Eli Zaretskii , Troy Brown , 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On June 10, 2025 12:11:34 PM PDT, Yuan Fu wrote: >I=E2=80=99m hesitant to get into another long debate, but let me give my = two cents=2E > >>> Consider that existing code in Emacs isn=E2=80=99t set in stone, it=E2= =80=99s not >>> really that fundamental that beginning-of-defun must work in a way >>> that makes prog-fill-reindent-defun behave >>> desirably=2E >>=20 >> Experimenting with a different UI paradigm doesn't justify introducing >> an inconsistency to behavior that's worked well for literally decades= =2E >> If I'm using, say, c++-ts-mode, my navigation commands should do the >> same thing they do in c++-mode=2E Plenty of code as well as muscle >> memories rely on this behavior=2E >>=20 >> The "tactic" concept is an unnecessary layer of indirection=2E >> If operation A takes you to place X and operation B takes you to >> different place Y, the way to express the difference between operations >> A and B is to make them _different commands_, not by twiddling some >> global switch=2E > >c-defun-tactic exists since Emacs 24, treesit-defun-tactic is actually mo= deled after it=2E Treesit-defun-tactic=E2=80=99s `top-level` and `nested` c= orresponds to c-defun-tactic=E2=80=99s `t` and `go-outward`=2E The only dif= ference is that tree-sitter defaults to the `nested` option=2E So we=E2=80= =99re not breaking the UI paradigm as you imagined=2E Also c++-ts-mode is a= new separate mode, and provides vastly different features to c++-mode, so = some difference is warranted=2E I don't think I've seen that cc-mode variable change=2E And there's still = no point in changing the default from cc-mode=2E If there's an exact corres= pondence, we should use it to minimize disruption=2E >A lot of features in c++-mode is missing simply because we don=E2=80=99t = have the resource to recreate them in c++-ts-mode=2E After all, Alan and ot= hers spend decades developing c++-mode=2E We also can=E2=80=99t just build = c++-ts-mode on top of c++-mode because the engine in c++ mode is very heavy= (meaning slow), if we use both tree-sitter parser (which has its own overh= ead) and the cc engine, it=E2=80=99ll be even slower than c++-mode for not = much benefit=2E It just makes no sense=2E Sure=2E That's not to say that c++-ts-mode can do less than cc-mode by its= nature, however=2E It's an as-yet unimplemented feature, not an architectu= ral gap=2E And given how powerful having an AST is, I'd expect the effort t= o implement parity with cc-mode's lexical and syntactic analysis to be a fe= w OOMs less than it was for cc-mode=2E >Also, cc-mode is a huge codebase, and I don=E2=80=99t have expertise in i= t=2E If Alan or some other cc-mode expert decides to incorporate tree-sitte= r into cc-mode, they might get strictly more information as you claimed=2E = But I and other people willing to work on c++-ts-mode don=E2=80=99t have th= at ability=2E > >(Also Theo is the maintainer of c++-ts-mode, I=E2=80=99m just a co-mainta= iner trying to fix things up when he=E2=80=99s not available=2E) > >> When you change tree-sitter "strategies" right now, you're silently >> turning one command into another command, that's confusing for everyone= =2E >> Please give these "strategies" individual command names=2E We have >> beginning-of-defun and beginning-of-defun-comments, not a knob that >> alters beginning-of-defun=2E > >Using variables to alter a commands behavior is a very well accepted prac= tice,=20 I for one disapprove of this practice=2E I don't like DWIM commands becaus= e they make it hard to discover the actual behavior and hard to make user c= ustomizations=2E Instead of DWIM commands we should have keymaps a mode adj= usts dynamically depending on context=2E For example, in org, we should have a function that says "do the tab key t= hing"=2E Org should have an org-dwim keymap from which org-mode-map inherit= s and that org changes depending on context as point moves=2E This way, C-h= c would correctly say that *here* TAB indents and *there* it cycles visibi= lity whenever the user invoked it -- and the user could override org-mode-m= ap to either override TAB globally or remap a specific operation (e=2Eg=2E = whatever the org indent function is) Likewise, for prog modes, instead of having a DWIM function movement comma= nd, we should have a customize option that changes the default command key = binding in that composed keymap without affecting user bindings and while m= aking C-h c tell the user about the true behavior=2E > it=E2=80=99s everywhere in Emacs=2E=20 Unfortunately=2E > Both approach are equally valid and are suitable for difference circumst= ances=2E=20 Commands that make big changes to their behavior based on user preferences= are an approach to avoid=2E > In our case, there=E2=80=99s already the long-existed tactic concept so = we want to keep to it, and also people usually only want the command behave= one way or another, so they can just set the variable and be done with it= =2E Multiple commands are more suitable for cases where the user wants to u= se different behaviors at the same time, then they can bind each command to= different keys=2E The multiple keymap approach I described above is compatible with users ex= plicitly binding commands to different keys=2E >>> prog-fill-reindent-defun uses beginning-of-defun because we >>> don=E2=80=99t have better choices before tree-sitter=2E In tree-sitter= major >>> modes, what we=E2=80=99ve been doing is to make the existing commands >>> customizable so tree-sitter can provide a tree-sitter version of >>> it=2E >>=20 >> Why does there need to be a tree-sitter version of >> prog-fill-reindent-defun? Isn't it enough that tree-sitter provide the >> low-level syntactic analysis for prog-fill-reindent-defun to do its job= ? >> Why the high level hook? I get there being a TS version of a routine to get the bounds of the curre= nt defun=2E I can understand a TS hook for filling a region=2E What I don't= understand is why we need to go even higher level than that and make a mod= e hook for *filling* the defun in particular=2E Why wouldn't composing the = two hooks above be correct generic code we could put in prog-mode? >If we want to use a lower-level abstraction, we=E2=80=99d need to create = some framework to get the defun at point, and add a tree-sitter provider of= it=2E=20 Yeah=2E That's what CEDET's functions are for and can be for if we rehabil= itate them=2E It's not like we're the first people talking about this=2E Instead of modes defining random beginning of defun and other low level pr= imitives, we: 1) define user level begining of defun, etc=2E in terms of CEDET tags (if = provided) 2) provide options for users to customize these semantic movement commands= in a generic way, e=2Eg=2E go to parent, go to sibling, whatever=20 3) provide fallbacks for exiting modes This way, TS modes (and other modes) can use arbitrarily sophisticated ana= lysis to determine what a defun *is* and the nesting structure of defuns an= d we decouple this analysis from movement between constructs, which we can = implement with existing infrastructure=2E This way, we get UI consistency= =2E > That just brings a whole can of worms: what should this API look like ex= actly? Should we change all other existing functions (many of which are hun= dred line monsters that are hard to understand and refactor without introdu= cing breakage) to use this new framework? Should it limit to only defun, or= should it support other constructs? If we want to support other constructs= , how do we implement the provider for those constructs in non-tree-sitter = settings?=20 We've had such a framework for years and years now=2E Shame nobody is usin= g it=2E > Many other functions that use beginning/end-of-defun needs more than get= ting the defun at point, they might want to know if point is at the beginni= ng of a defun, they might want to know if there=E2=80=99s another defun aft= er this one=2E How do we design the framework so these requests are met? > >For the reasons above, thing-at-point isn=E2=80=99t really suitable for o= ur purpose, or at least we need to make significant changes to its API to m= ake it suitable=2E Thing-at-point is mostly a simple API to get things lik= e url and symbol and word at point, not something that can give us rich inf= ormation of syntactic construct at point=2E > >You might think prog-fill-reindent-defun can just use tree-sitter functio= ns to get syntax information, but that=E2=80=99s a big no-no=2E Existing Em= acs features like imenu, font-lock, prog-fill-reindent-defun, etc, shouldn= =E2=80=99t even know about tree-sitter, they are user-facing and only provi= de customization points for major modes/tree-sitter/eglot/etc to plugin and= provide functionality=2E > >So things aren=E2=80=99t that simple if you start thinking about how to a= ctually doing it=2E If you can design something that give the right abstrac= tion that major mode/tree-sitter/eglot/etc can plugin to, and can make it w= ork for both non-tree-sitter and tree-sitter, and potential future tools th= at provide parse trees, I=E2=80=99ll be very happy, because we do want that= =2E > >So given all that consideration, I decided to go with a higher-level abst= raction you saw=2E After my refactor of prog-fill-reindent-defun, reimpleme= nting it for tree-sitter is just 8 lines of code=2E The small code duplicat= ion is perfectly acceptable IMO=2E A higher-level abstraction also has plen= ty benefits: major modes can define their own version if it=E2=80=99s neces= sary, we have more freedom in our implementation because there=E2=80=99s a = looser coupling, etc=2E > >>=20 >>> We=E2=80=99ve done this for forward-sexp: we added >>> forward-sexp-function=2E Some commands already have customization poin= ts >>> long ago, like beginning-of-defun, which has >>> beginning-of-defun-function=2E >>=20 >> Modes use generally these "customization points" to _implement_ the >> familiar behavior, not to give them random different >> user-visible semantics=2E > >Let me also reply to your later messages here: > >> It's not a feature=2E It's a UI and programming annoyance=2E How are yo= u supposed to write code against functions with behavior that shifts on a w= him with no stable functions to call instead? >>=20 >> Yet we use the concept of command names to express different concepts e= lsewhere=2E And if the concept is ambiguously defined, provide a minimal kn= ob to adjust that concept, not change the operation of primitives to be inc= onsistent with each other=2E=20 > >I agree that beginning/end-of-defun has evolved into a kind of primitive = function for getting the defun at point, because we didn=E2=80=99t have a p= arse tree or an API for getting defun at point=2E But I disagree your concl= usion that one can=E2=80=99t write code against beginning/end-of-defun that= can change behavior=2E I mean, that=E2=80=99s the point of abstraction, no= ? User can choose they want top-level or nested kind of defun, and by chang= ing that, all the functions that use beginning/end-of-defun automatically s= witch to the chosen behavior=2E Isn=E2=80=99t that better than having no ch= oice? You can write code against these functions only if their behavior changes = in consistent ways=2E For example, mark-defun in prog today moves backwards= and forwards over defuns to find the defun region=2E This sibling strategy= for movement van results in this region finding algorithm producing nonsen= se, yes? >But of course there'll be cases where the abstraction doesn=E2=80=99t wor= k, like prog-fill-reindent-defun=2E It=E2=80=99s mostly because beginning/e= nd-of-defun is a god awful abstraction, but that=E2=80=99s what all the exi= sting functions use and we have to live with it, until someone creates a be= tter abstraction and refactor all the existing functions to use it=2E Anywa= y, in cases where the abstraction doesn=E2=80=99t work well, we just need t= o do a bit more to make it work, and I added prog-fill-reindent-defun-funct= ion=2E=20 I agree it's not the best abstraction, but 1) a better one is available, a= nd 2) it's worked for many years=2E Adding a better abstraction doesn't pre= clude implementing the current one as best we can=2E > >>> So I added prog-fill-reindent-defun-function and a tree-sitter version >>> treesit-fill-reindent-defun=2E The tree-sitter implementation uses >>> treesit-defun-at-point, so it doesn=E2=80=99t even need to concern >>> with tactics=2E >>>=20 >>> Now in tree-sitter major modes, prog-fill-reindent-defun should always >>> indent the enclosing defun=2E >>=20 >> Which now means prog-fill-reindent-defun can indent something other tha= n >> what mark-defun highlights? That seems odd to me=2E Tree sitter's job= is >> syntactic analysis, not UI differentiation=2E >>=20 >>>> After that, I'm less concerned about its behavior, but think the >>>> current `nested` behavior of visiting the previous sibling defun unti= l >>>> there are no more, then visiting the parent defun makes sense=2E The >>>> key difference is that you only visit the previous sibling if point i= s >>>> at a defun boundary=2E=2E=2Eotherwise visit the defun containing poin= t=2E >>>=20 >>> Hmmm, it doesn=E2=80=99t feel very convenient, you=E2=80=99d need to f= irst adjust your >>> point to be precisely at the boundary, then press C-M-a/e? IMO that >>> adds too much overhead=2E I added a tactic `parent-first` that always >>> move to the beginning/end of the enclosing defun=2E People that prefer= s >>> this kind of defun movement can use this tactic=2E >>=20 >> The default should be to match behavior that's been stable for decades= =2E >> Use of tree sitter should be an implementation detail for users=2E >>=20 >> If we want to provide UI to better handle nested defuns, this UI should >> go in prog-mode=2Eel and rely on mode-provided syntactic analysis, > >As I described above, it=E2=80=99s not as simple as you imagined=2E > >> not >> just delegate to a mode function that does different random stuff in >> each mode=2E > >If the mode use tree-sitter provided default (which they 99=2E99% will), = the behavior is well defined=2E Even if major mode decide to provide their = own version, I trust the major mode author to know what they=E2=80=99re doi= ng and have a good reason to implement their own, and provide a function th= at fits the docstring of prog-fill-reindent-defun=2E So no, it won=E2=80=99= t be random stuff=2E And TS modes will still be randomly inconsistent with everything else in E= macs=2E Users shouldn't have to use the editor differently because a mode h= appens to use tree sitter=2E > >>>> Furthermore, consider the following `top-level` tactic example using >>>> `c++-ts-mode`=2E Here, we have a C++ namespace (which is considered = a >>>> defun for C++) >>=20 >> Namespaces aren't defuns and c++-ts-mode shouldn't be indenting their >> contents by a level either=2E c++-ts-mode is unusable without hacks li= ke >> pragmatically editing the indentation rules in user configuration=2E > >If it=E2=80=99s a bug in the indentation rule, we can fix it=2E But can y= ou open another bug report and describe what exactly is wrong? It's not a bug=2E It's a missing feature=2E Lots of customization rules ca= n't be expressed using the knobs TS affords right now, and moreover, those = knobs depend on unstable raw AST nodes and so are fragile=2E I have an existing bug somewhere about TS modes supporting high level inde= ntation style customization using cc-mode's quite good rules and anchor sys= tem=2E There's more than enough information in the TS AST to implement c-gu= ess-basic-syntax=2E From debbugs-submit-bounces@debbugs.gnu.org Wed Jun 11 08:08:48 2025 Received: (at 78703) by debbugs.gnu.org; 11 Jun 2025 12:08:48 +0000 Received: from localhost ([127.0.0.1]:47826 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uPKG7-0001ac-C0 for submit@debbugs.gnu.org; Wed, 11 Jun 2025 08:08:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:38404) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uPKG2-0001Zy-7A for 78703@debbugs.gnu.org; Wed, 11 Jun 2025 08:08:43 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uPKFq-0005n7-5b; Wed, 11 Jun 2025 08:08:31 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=4wvqMOzmDc7hgZNJum/I/3d/Kx8NNj5qZElGgyDFTOo=; b=k44qlJq5SiMb Wlyyb33dNSVs93cmsMLr0GZP+oqy59q9k/JxOoJ7lIXqFaeeLBfItiK412R3RKpXQf4ynUEXUmE8Q enIP4FGp0SKv1jZ9/oDDhkhlrLvcAjwHU3mSPCfqhIc+iLgM/65ODiF3bAzPiRIiEHNv/L+s1ZY4m kAljz/c/0PvV2pF3DIY0j//ncvrvy7N3YZ2PejbAwjb/tIYPk6AYX6+4X25VqbirWaIOej5msBNsf ET/PfHsEHWw91vAt2esDUb2bURl26pKU1IMbKeE8p15RlERbOfFci3WF0AYzLfFMqu17eIJDs8WnR SC8BYUlVwYm3Ad4sbck5UA==; Date: Wed, 11 Jun 2025 15:08:24 +0300 Message-Id: <86y0tyeb0n.fsf@gnu.org> From: Eli Zaretskii To: Daniel Colascione In-Reply-To: <320605B2-AAB5-44EA-805A-185FAEBAC986@dancol.org> (message from Daniel Colascione on Tue, 10 Jun 2025 09:55:59 -0700) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode References: <86cybbg5i1.fsf@gnu.org> <861prrfu2w.fsf@gnu.org> <320605B2-AAB5-44EA-805A-185FAEBAC986@dancol.org> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > Date: Tue, 10 Jun 2025 09:55:59 -0700 > From: Daniel Colascione > CC: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org > > >Not really, not when you look closely. The tools we've built before > >tree-sitter are ad-hoc, so they allow us to provide information that > >parsers don't have and don't need to have. Our syntax tables are not > >exactly "less efficient parsing", and regular expressions allow us to > >match whatever we want and call that anything we want. > > There is nothing one bit of information available to c-mode not available to c-ts-mode. Sure, if you want c-ts-mode do everything c-mode did, plus what it does based on the parser. But the idea is to toss as much of the ad-hoc "parsing" and "matching" we have, so that we don't need to keep updating that forever, as the languages evolve and add/redefine features. That was the main purpose of integrating tree-sitter in Emacs, after all. So from where I stand, going back to all the stuff we have in c-mode would mean we wasted a lot of efforts for nothing. People who just want the c-mode behavior 1:1 should simply use c-mode, it will never be removed from Emacs. > > We still lack some useful > >functionalities that are present in CC Mode, forrea that very reason; > >what was easy to implement was done long ago. > > That's the opposite of reality. Alan and others have spent years building a flexible and fast backtracking syntactic analyser for CC mode. Tree sitter does the same thing but in a more general way, in native code for better performance. Its availability makes doing what cc-mode does easier, not harder. We expected that, yes. The reality disappointed us to some extent. > >We've been doing that since day one: you write code that looks at the > >variables to figure out what behavior to expect, or you write code > >that is general enough to not care. > > I can't wait to program against our glorious new dwim function. The problem with let binding the world is that the set of dynamic inputs becomes unbounded. What if I just bind the strategy option and one day TS introduces, say, a new sub-strategy option that makes the function I call behave differently? If we decide it's a good idea, yes. But these additions are not a force of nature: we decide whether to add or not to add, and we should consider the adverse effects each such addition has when we do. If we do a good job, there won't be unbounded set of dynamic inputs to consider in each case. > >> Yet we use the concept of command names to express different concepts elsewhere. And if the concept is ambiguously defined, provide a minimal knob to adjust that concept, not change the operation of primitives to be inconsistent with each other. > > > >I think we do the former, or at least we try. > > Then let's make separate commands to express moving to a defun boundary one way versus another way and let users express their preference for connecting input to action using keymaps. I'm not saying we should never do that. I was responding to your much more general remarks, not to this particular case. IOW, if you argue about this specific issue, and with arguments specific to it, it's possible we will eventually agree. Just let's not introduce general arguments like "this should never be done", because I don't think I agree, based on our experiences and practices. So such arguments will not convince. > >> No it isn't. If the defun navigation functions in TS modes had their traditional behavior, they'd continue to work for higher level constructs built on top of them like the prog-mode reindent and mark defun. TS modes broke a whole bunch of things that had worked fine for decades, and instead of fixing them, they just made even more abstractions to plug inconsistent tree sitter things in place of the broken things. > > > >Indentation is a lot more than just navigation. And I disagree with > >you extreme interpretation of the current state of indentation and > >navigation support in TS-based modes. > > I'm right. I beg to differ. > >Sorry, this is simplification. A typical declaration breaks down into > >smaller parts, and we have expectations and ideas about indentation of > >each one of them. But the tree-sitter classification of the AST > >constituents does not necessarily make that easy, because you could > >have the same syntactic symbol both inside a declaration and in other > >places. So having an AST does not always immediately tell you how to > >indent correctly. > > No, but it gives you more information than looking-at does, and cc-mode does its job admirable given only that simple tool. You can look at nesting and context in the TS AST to figure out what to do. Once again, going the looking-at way means we bring back all the ad-hoc stuff that attempts to "parse" the code using heuristic regexps, with the serious disadvantage that these heuristics need to be well understood by someone who has a good knowledge of the underlying language, and updated as the language evolves. So I'd like to do that only when absolutely necessary, and as little as possible even then. > >> Yes, and because it's ambiguous we get annoyances like python-mode's default sexp movement. Now every mode is like that, and you can't turn it off half the time? > > > >What else did you expect? Some users like one style, others like the > >other. Are we supposed to say "my way or the highway"? And that's > >even before we consider that the disagreement cuts through the > >developers themselves. > > No. I'm expecting a generally consistent experience, and if we want to provide a configuration knob, it should affect everything consistently. One shouldn't have to form independent and different muscle memory for each language mode because the whims of their authors were different. Consistency is problematic here, because "sexp" doesn't translate consistently between languages, and even "defun" not always does (cf. the "namespace" case). > >I find continuing this kind of argument not constructive, so I will > >stop here. Let me just say that I think you are looking at this stuff > >from some semi-abstract, almost idealistic, aspect. As if we didn't > >have 40 years of development and user experience and expectations to > >keep and uphold. > > I'll never understand the mindset that holds that things making sense and having a structure is bad actually because sense and structure are "academic" and "idealistic". There's no such mindset. I have no disagreement with you on that level. The disagreement is on a very practical level: we did try to do things that way at the beginning, two years ago. We are where we are because that didn't work well enough. > What 40 years of development and user experience holds is that if I'm four pages deep into a nasty TypeScript function and hit beginning-of-defun, I want to go to the beginning of the four page defun I am editing and not some random place two pages up that I didn't even know about in which someone scribbled out some kind of nested lambda irrelevant to my present task. It turns out other users have other preferences and expectations, especially if we include other languages in the context. We cannot tell them to get lost. From debbugs-submit-bounces@debbugs.gnu.org Wed Jun 11 08:59:37 2025 Received: (at 78703) by debbugs.gnu.org; 11 Jun 2025 12:59:37 +0000 Received: from localhost ([127.0.0.1]:48205 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uPL3I-0005tA-GZ for submit@debbugs.gnu.org; Wed, 11 Jun 2025 08:59:37 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]:48078) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uPL3E-0005sm-6r for 78703@debbugs.gnu.org; Wed, 11 Jun 2025 08:59:33 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=9HgDQWbS8hQCQlheEcXtal68KA4YI0xTysoIlyaWQqQ=; b=RBn9dNbIxsZ5dNG0cE9/I94zHv JpM9y1wDfaX13AliBuu9QZ/0lnf7xWWZgmkBHD6YaHknjc8O1y7NR4nijVd4C9eDrzv/FGfgmKZ+E U7+kqzvQdxamJMOn7BhDpCwu6XvO8ei/8dTSieZb6tN9hwOJoRDzoQRr/E0zKNnZwv5B5SMH6AWEW 2YX39J/vGjfAGA4snnVs8DM28kEnr0Q1MLd+pjknbHu4x5SxAfSgHIX403GmA2GWHugBUMzPQhzqD +ZMnlF4uhmWxN1yM9CVcHMsITWYfjAHt6PGsxKL/bMCKPYft3JudxI0DkgOQqN12mFDkQWiftzkKe b84gRXcQ==; Received: from dancol by dancol.org with local (Exim 4.96) (envelope-from ) id 1uPL1s-00Be6g-1L; Wed, 11 Jun 2025 08:58:08 -0400 From: Daniel Colascione To: Eli Zaretskii Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode In-Reply-To: <86y0tyeb0n.fsf@gnu.org> References: <86cybbg5i1.fsf@gnu.org> <861prrfu2w.fsf@gnu.org> <320605B2-AAB5-44EA-805A-185FAEBAC986@dancol.org> <86y0tyeb0n.fsf@gnu.org> User-Agent: mu4e 1.12.10; emacs 31.0.50 Date: Wed, 11 Jun 2025 05:59:28 -0700 Message-ID: MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Eli Zaretskii writes: >> Date: Tue, 10 Jun 2025 09:55:59 -0700 >> From: Daniel Colascione >> CC: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org >> >> >Not really, not when you look closely. The tools we've built before >> >tree-sitter are ad-hoc, so they allow us to provide information that >> >parsers don't have and don't need to have. Our syntax tables are not >> >exactly "less efficient parsing", and regular expressions allow us to >> >match whatever we want and call that anything we want. >> >> There is nothing one bit of information available to c-mode not available to c-ts-mode. > > Sure, if you want c-ts-mode do everything c-mode did, plus what it > does based on the parser. But the idea is to toss as much of the > ad-hoc "parsing" and "matching" we have, so that we don't need to keep > updating that forever, as the languages evolve and add/redefine > features. That was the main purpose of integrating tree-sitter in > Emacs, after all. So from where I stand, going back to all the stuff > we have in c-mode would mean we wasted a lot of efforts for nothing. > People who just want the c-mode behavior 1:1 should simply use c-mode, > it will never be removed from Emacs. > >> > We still lack some useful >> >functionalities that are present in CC Mode, forrea that very reason; >> >what was easy to implement was done long ago. >> >> That's the opposite of reality. Alan and others have spent years >> building a flexible and fast backtracking syntactic analyser for CC >> mode. Tree sitter does the same thing but in a more general way, in >> native code for better performance. Its availability makes doing >> what cc-mode does easier, not harder. > > We expected that, yes. The reality disappointed us to some extent. What specific information is missing from the TS AST? >> >We've been doing that since day one: you write code that looks at the >> >variables to figure out what behavior to expect, or you write code >> >that is general enough to not care. >> >> I can't wait to program against our glorious new dwim function. The >> problem with let binding the world is that the set of dynamic inputs >> becomes unbounded. What if I just bind the strategy option and one >> day TS introduces, say, a new sub-strategy option that makes the >> function I call behave differently? > > If we decide it's a good idea, yes. But these additions are not a > force of nature: we decide whether to add or not to add, and we should > consider the adverse effects each such addition has when we do. If we > do a good job, there won't be unbounded set of dynamic inputs to > consider in each case. > >> >> Yet we use the concept of command names to express different >> >> concepts elsewhere. And if the concept is ambiguously defined, >> >> provide a minimal knob to adjust that concept, not change the >> >> operation of primitives to be inconsistent with each other. >> > >> >I think we do the former, or at least we try. >> >> Then let's make separate commands to express moving to a defun boundary one way versus another way and let users express their preference for connecting input to action using keymaps. > > I'm not saying we should never do that. I was responding to your much > more general remarks, not to this particular case. By default, commands should do one thing. One can rebut the presumption that a command should do one simple thing for certain special cases, I guess, but I don't see a strong argument for for beginning-of-defun being one of these cases when it's easy to provide commands for the various supported behaviors. > IOW, if you argue about this specific issue, and with arguments > specific to it, it's possible we will eventually agree. Just let's > not introduce general arguments like "this should never be done", > because I don't think I agree, based on our experiences and practices. > So such arguments will not convince. > >> >> No it isn't. If the defun navigation functions in TS modes had >> >> their traditional behavior, they'd continue to work for higher >> >> level constructs built on top of them like the prog-mode reindent >> >> and mark defun. TS modes broke a whole bunch of things that had >> >> worked fine for decades, and instead of fixing them, they just >> >> made even more abstractions to plug inconsistent tree sitter >> >> things in place of the broken things. >> > >> >Indentation is a lot more than just navigation. And I disagree with >> >you extreme interpretation of the current state of indentation and >> >navigation support in TS-based modes. >> >> I'm right. > > I beg to differ. > >> >Sorry, this is simplification. A typical declaration breaks down into >> >smaller parts, and we have expectations and ideas about indentation of >> >each one of them. But the tree-sitter classification of the AST >> >constituents does not necessarily make that easy, because you could >> >have the same syntactic symbol both inside a declaration and in other >> >places. So having an AST does not always immediately tell you how to >> >indent correctly. >> >> No, but it gives you more information than looking-at does, and cc-mode does its job admirable given only that simple tool. You can look at nesting and context in the TS AST to figure out what to do. > > Once again, going the looking-at way means we bring back all the > ad-hoc stuff that attempts to "parse" the code using heuristic > regexps, with the serious disadvantage that these heuristics need to > be well understood by someone who has a good knowledge of the > underlying language, and updated as the language evolves. So I'd like > to do that only when absolutely necessary, and as little as possible > even then. I'm not saying c++-ts-mode should parse using regexps like cc-mode does. I am saying that the AST should contain all the information cc-mode would instead get from this parsing and can be put to the same use. What information is the AST missing? >> >> Yes, and because it's ambiguous we get annoyances like python-mode's default sexp movement. Now every mode is like that, and you can't turn it off half the time? >> > >> >What else did you expect? Some users like one style, others like the >> >other. Are we supposed to say "my way or the highway"? And that's >> >even before we consider that the disagreement cuts through the >> >developers themselves. >> >> No. I'm expecting a generally consistent experience, and if we want >> to provide a configuration knob, it should affect everything >> consistently. One shouldn't have to form independent and different >> muscle memory for each language mode because the whims of their >> authors were different. > > Consistency is problematic here, because "sexp" doesn't translate > consistently between languages, and even "defun" not always does > (cf. the "namespace" case). That "sexp" and "defun" mean different things in different languages doesn't mean movement commands between defuns should do different things in different languages. Movement _between_ defuns should work the same way everywhere even if the _definition_ of a defun is language-specific. I can write with a pen or a pencil. I don't have to switch from left-handed to right-handed writing when I want to write with ink instead of graphite. >> >I find continuing this kind of argument not constructive, so I will >> >stop here. Let me just say that I think you are looking at this stuff >> >from some semi-abstract, almost idealistic, aspect. As if we didn't >> >have 40 years of development and user experience and expectations to >> >keep and uphold. >> >> I'll never understand the mindset that holds that things making sense and having a structure is bad actually because sense and structure are "academic" and "idealistic". > > There's no such mindset. I have no disagreement with you on that > level. The disagreement is on a very practical level: we did try to > do things that way at the beginning, two years ago. We are where we > are because that didn't work well enough. Maybe we didn't try hard enough. If there's something missing in the AST, perhaps it could be added. >> What 40 years of development and user experience holds is that if >> I'm four pages deep into a nasty TypeScript function and hit >> beginning-of-defun, I want to go to the beginning of the four page >> defun I am editing and not some random place two pages up that I >> didn't even know about in which someone scribbled out some kind of >> nested lambda irrelevant to my present task. > > It turns out other users have other preferences and expectations, > especially if we include other languages in the context. We cannot > tell them to get lost. Users really prefer go-to-sibling behavior for beginning-of-defun? Says who? From debbugs-submit-bounces@debbugs.gnu.org Wed Jun 11 09:16:45 2025 Received: (at 78703) by debbugs.gnu.org; 11 Jun 2025 13:16:45 +0000 Received: from localhost ([127.0.0.1]:48340 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uPLJt-0007WJ-7O for submit@debbugs.gnu.org; Wed, 11 Jun 2025 09:16:45 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:48314) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uPLJg-0007VZ-FI for 78703@debbugs.gnu.org; Wed, 11 Jun 2025 09:16:33 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1uPLJW-0006cX-3t; Wed, 11 Jun 2025 09:16:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=References:Subject:In-Reply-To:To:From:Date: mime-version; bh=9mJlvNSNgJWGD5sEut3sq5dsC9pk4/sg2NgOENhSozY=; b=D31AwbV6PD9p 3TneN8UZoAnako9ZgUBnZx1+hH2+iDU9aEezkXHdSU/X4i3cTi0q9x8eMu64ud/K74jMqV9fhTBMG uJ+fCaKtQFgXYyabSA9TLm2LdUSvN32ybuyMk1WcI9yRmmTEs9zhwiG0x+8+Qxnul6W+QmYz2IByw mS6hFaltS/K99sMKIWCBKD7zBw6icYlvist3oXtBawg53Vo4ybxLqH6yEYP66sEhNx8PR8JMMxT5i L8AKh46MLulbvvkmajpbhWjxWhHpbUUszBWRn+tpTj/PBvN6XMVVFxUc4nk530YRIbC4STLaMDEHO 5nh9RcM4Lwm8gnST1pMQOA==; Date: Wed, 11 Jun 2025 16:16:14 +0300 Message-Id: <86ldpye7vl.fsf@gnu.org> From: Eli Zaretskii To: Daniel Colascione In-Reply-To: (message from Daniel Colascione on Wed, 11 Jun 2025 05:59:28 -0700) Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode References: <86cybbg5i1.fsf@gnu.org> <861prrfu2w.fsf@gnu.org> <320605B2-AAB5-44EA-805A-185FAEBAC986@dancol.org> <86y0tyeb0n.fsf@gnu.org> X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: Daniel Colascione > Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org > Date: Wed, 11 Jun 2025 05:59:28 -0700 > > Eli Zaretskii writes: > > >> > We still lack some useful > >> >functionalities that are present in CC Mode, forrea that very reason; > >> >what was easy to implement was done long ago. > >> > >> That's the opposite of reality. Alan and others have spent years > >> building a flexible and fast backtracking syntactic analyser for CC > >> mode. Tree sitter does the same thing but in a more general way, in > >> native code for better performance. Its availability makes doing > >> what cc-mode does easier, not harder. > > > > We expected that, yes. The reality disappointed us to some extent. > > What specific information is missing from the TS AST? Anything that is not part of the C grammar. I already gave one example: the way we support DEFUN. Handling of cpp directives is also not entirely satisfactory (because macros are not C, so TS added them as a semi-kludgey feature). > > I'm not saying we should never do that. I was responding to your much > > more general remarks, not to this particular case. > > By default, commands should do one thing. One can rebut the presumption > that a command should do one simple thing for certain special cases, I > guess, but I don't see a strong argument for for beginning-of-defun > being one of these cases when it's easy to provide commands for the > various supported behaviors. In this case, the different behavior is from user preference of either preferring the nested function or the top-level one. That preference affects more than just beginning-of-defun. I think Yuan explained why we are where we are with this. > > Once again, going the looking-at way means we bring back all the > > ad-hoc stuff that attempts to "parse" the code using heuristic > > regexps, with the serious disadvantage that these heuristics need to > > be well understood by someone who has a good knowledge of the > > underlying language, and updated as the language evolves. So I'd like > > to do that only when absolutely necessary, and as little as possible > > even then. > > I'm not saying c++-ts-mode should parse using regexps like cc-mode does. > I am saying that the AST should contain all the information cc-mode > would instead get from this parsing and can be put to the same use. > What information is the AST missing? See above. As another example that I saw only recently (which is why I still remember it): the C grammar library only now added support for __cdecl, something that c-mode supported long ago. So we also have features missing from tree-sitter just because they are missing. > > Consistency is problematic here, because "sexp" doesn't translate > > consistently between languages, and even "defun" not always does > > (cf. the "namespace" case). > > That "sexp" and "defun" mean different things in different languages > doesn't mean movement commands between defuns should do different things > in different languages. Movement _between_ defuns should work the same > way everywhere even if the _definition_ of a defun is language-specific. Yes, but here the definition of the defun differs. > > There's no such mindset. I have no disagreement with you on that > > level. The disagreement is on a very practical level: we did try to > > do things that way at the beginning, two years ago. We are where we > > are because that didn't work well enough. > > Maybe we didn't try hard enough. If there's something missing in the > AST, perhaps it could be added. I certainly hope so. Please be sure to propose improvements based on the AST, I don't think anyone will object. What we do (or don't do) now is just because we didn't yet get tro implementing it or found it hard, not because we don't want the same features as in non-TS modes. > >> What 40 years of development and user experience holds is that if > >> I'm four pages deep into a nasty TypeScript function and hit > >> beginning-of-defun, I want to go to the beginning of the four page > >> defun I am editing and not some random place two pages up that I > >> didn't even know about in which someone scribbled out some kind of > >> nested lambda irrelevant to my present task. > > > > It turns out other users have other preferences and expectations, > > especially if we include other languages in the context. We cannot > > tell them to get lost. > > Users really prefer go-to-sibling behavior for beginning-of-defun? Turns out that way. > Says who? Users. From debbugs-submit-bounces@debbugs.gnu.org Wed Jun 11 10:15:35 2025 Received: (at 78703) by debbugs.gnu.org; 11 Jun 2025 14:15:35 +0000 Received: from localhost ([127.0.0.1]:49687 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uPMEo-0007GF-L0 for submit@debbugs.gnu.org; Wed, 11 Jun 2025 10:15:34 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]:37672) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uPMEk-0007Fw-3c for 78703@debbugs.gnu.org; Wed, 11 Jun 2025 10:15:32 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=FU3RcHe4x0Y+SXiJrfteHLzRbi8o261AMGIfVzmCJGg=; b=aCxpc428CUHzPp02TftKKNq/9x cFz132CG0FcAiodXUSGBhALav4wQ4Fmc6CykETiDKEmcmL3YtSoNzPXSvAX5YdZ245yaiIM3aWLsA UhaEqs7zfryuTZUTp8s3JLobzjarKgFQGhBy2rOswE+HX2x7+imhMMrVP091LFDCXFVApU1N2OiXi l44MGm4b/qe6/BKCXDYj5UniyC9ZDaS0ogUgpTMkmEGaSE4QaLFBOz04qpVY46JMGRcUSDWPhjqKO 0vg6ymWeQVqudeiPQwPp5uPpkMCnjiO6U597E1BiVF2JcEP3vGCPbCZQKyVoTBXCdBhE0aqu7sGs8 oWBGX7eg==; Received: from dancol by dancol.org with local (Exim 4.96) (envelope-from ) id 1uPMDP-00Bf6Z-1h; Wed, 11 Jun 2025 10:14:07 -0400 From: Daniel Colascione To: Eli Zaretskii Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode In-Reply-To: <86ldpye7vl.fsf@gnu.org> References: <86cybbg5i1.fsf@gnu.org> <861prrfu2w.fsf@gnu.org> <320605B2-AAB5-44EA-805A-185FAEBAC986@dancol.org> <86y0tyeb0n.fsf@gnu.org> <86ldpye7vl.fsf@gnu.org> User-Agent: mu4e 1.12.10; emacs 31.0.50 Date: Wed, 11 Jun 2025 07:15:27 -0700 Message-ID: MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Eli Zaretskii writes: >> >> Users really prefer go-to-sibling behavior for beginning-of-defun? > > Turns out that way. > >> Says who? > > Users. Do they? Which ones? What every user I've seen dislike more than any default is inconsistency, especially gratuitous inconsistencies between things that are logically the same and happen to have divergent implementation details. I find it impossible to believe that real users, in code like this: function foo() { blah; function bar() { ... } // [Snip four pages] for (let x of y) { [point] } } When pressing C-M-a, want to go to the definition of bar, not the definition foo. It doesn't make any sense to me that anyone would want to perform that operation. If you're going to insist on bad defaults, you're just going to drive more people to Doom and such. From debbugs-submit-bounces@debbugs.gnu.org Wed Jun 11 10:23:36 2025 Received: (at 78703) by debbugs.gnu.org; 11 Jun 2025 14:23:36 +0000 Received: from localhost ([127.0.0.1]:49735 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uPMMa-0007rX-3X for submit@debbugs.gnu.org; Wed, 11 Jun 2025 10:23:36 -0400 Received: from dancol.org ([2600:3c01:e000:3d8::1]:45362) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1uPMMQ-0007pf-T9 for 78703@debbugs.gnu.org; Wed, 11 Jun 2025 10:23:29 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dancol.org; s=x; h=Content-Type:MIME-Version:Message-ID:Date:References:In-Reply-To: Subject:Cc:To:From:Sender:Reply-To:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=SnJEyyZWnK2zLivxGiQXXgcnXHtiSOfgP+rLuy6aMKc=; b=LsSL79x5lCBY0JsAO2AZZ1perN l7Rg/6x5p2Domszqjm8noKvHpnJE5gmVTh2a2MokxexXd5NoI/UCnxsiVp14ZduBV/hbybn+mY81v 2KxhhDN+H9gP9pZ1ZetKqQZ+s9N4UdSapSArgLNh2pVgoy2Cl48kqKPNFlr6vcucwX1xkZ17QJ81N JzlnS0TwopdtWU0bWprk0tZ+mWFjkRhtoeb4poTRN6ppt+niMcYciHNMEsAuobr/AxJnAHIK/oal4 XwEgOpqNP9gQDqRr82MGTJVeHZdsPht8No7blkDqPXWag6vBf1IOdWarP3MaJor83INLmFvVq0Ekw vq2eBNng==; Received: from dancol by dancol.org with local (Exim 4.96) (envelope-from ) id 1uPML6-00BfQ0-2L; Wed, 11 Jun 2025 10:22:04 -0400 From: Daniel Colascione To: Eli Zaretskii Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode In-Reply-To: References: <86cybbg5i1.fsf@gnu.org> <861prrfu2w.fsf@gnu.org> <320605B2-AAB5-44EA-805A-185FAEBAC986@dancol.org> <86y0tyeb0n.fsf@gnu.org> <86ldpye7vl.fsf@gnu.org> User-Agent: mu4e 1.12.10; emacs 31.0.50 Date: Wed, 11 Jun 2025 07:23:24 -0700 Message-ID: MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: -0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: casouri@gmail.com, brownts@troybrown.dev, 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Daniel Colascione writes: > Eli Zaretskii writes: >>> >>> Users really prefer go-to-sibling behavior for beginning-of-defun? >> >> Turns out that way. >> >>> Says who? >> >> Users. > > Do they? Which ones? What every user I've seen dislike more than any > default is inconsistency, especially gratuitous inconsistencies between > things that are logically the same and happen to have divergent > implementation details. I find it impossible to believe that real > users, in code like this: > > function foo() { > blah; > function bar() { > ... > } > // [Snip four pages] > for (let x of y) { > [point] > } > } > > When pressing C-M-a, want to go to the definition of bar, not the > definition foo. It doesn't make any sense to me that anyone would want > to perform that operation. If you're going to insist on bad defaults, > you're just going to drive more people to Doom and such. To clarify, the behavior above is useless because it's impossible to predict. With standard behavior, I can see, in the modeline, that I'm in a defun called "foo". I can reason, therefore, that if I type C-M-a, I will go to the start of foo. I can predict the effect of my actions. I can't predict the behavior of C-M-a with the current TS default. Maybe it'll go to bar. Maybe someone deleted bar in a merge and it'll go to foo. Maybe someone added a guy after bar and C-M-a will go there instead. I can't know in advance. This lack of predictability makes C-M-a as a whole less useful. From debbugs-submit-bounces@debbugs.gnu.org Thu Jun 12 08:05:25 2025 Received: (at 78703) by debbugs.gnu.org; 12 Jun 2025 12:05:26 +0000 Received: from localhost ([127.0.0.1]:57040 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1uPggP-0000iL-I4 for submit@debbugs.gnu.org; Thu, 12 Jun 2025 08:05:25 -0400 Received: from m228-15.mailgun.net ([159.135.228.15]:54130) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1uPggN-0000ht-6t for 78703@debbugs.gnu.org; Thu, 12 Jun 2025 08:05:24 -0400 DKIM-Signature: a=rsa-sha256; v=1; c=relaxed/relaxed; d=mg.troybrown.dev; q=dns/txt; s=mx; t=1749729912; x=1749737112; h=Content-Transfer-Encoding: Content-Type: Cc: To: To: Subject: Subject: Message-ID: Date: From: From: In-Reply-To: References: MIME-Version: Sender: Sender; bh=+mKZ4VkezR8b8OKwAgoLeSchJ+XlARSAa3ntkcCI3tk=; b=M0kVgdEUlXfuHCqm+dST8UHdwrE/mGGxgyjQSwUIKKKyTaOYiBAG12KqHhUKM+0Vxhh34c3S0aIbYBiUapeFTZxEWZIop/zBaLZRo1eGI+riXUiAu8MIYcqwOC26Iz3X3dRVtv7plqFeR2De7lMLlYPepjK9cFcZbfunyxBZMeE= X-Mailgun-Sid: WyIwMzZhOSIsIjc4NzAzQGRlYmJ1Z3MuZ251Lm9yZyIsIjVmZDVkMiJd Received: from mail-ed1-f54.google.com (mail-ed1-f54.google.com [209.85.208.54]) by 367d75307acf with SMTP id 684ac2743050543e9e8c10ba (version=TLS1.3, cipher=TLS_AES_128_GCM_SHA256); Thu, 12 Jun 2025 12:05:08 GMT X-Mailgun-Sending-Ip: 159.135.228.15 Received: by mail-ed1-f54.google.com with SMTP id 4fb4d7f45d1cf-60780d74c8cso1674702a12.2 for <78703@debbugs.gnu.org>; Thu, 12 Jun 2025 05:05:08 -0700 (PDT) X-Forwarded-Encrypted: i=1; AJvYcCXEp9dNHv3vYTiX0Khh5iIdcAK5LW318vkwUg3u3D6CDnJxtRXozijqBq8q1HmQzhlaWvDZCA==@debbugs.gnu.org X-Gm-Message-State: AOJu0Yz7Ey/39WvtTrvfrz17DbB8CciAaM34PlCrKcDJj8O4sx8L4wRP xBUHyFPFqZikctpHTLZqBB+bvZPFyVNAl8POCoZjKTmVFxO78fI0iN7YQm2hYUWaiiE+Y3Uurkl 9Cw0+020wlnnU1YWMrkP8mB0AtqGxPi4= X-Google-Smtp-Source: AGHT+IHIsfINcn6NLg3ptYCYHYEh0283dfC1DNx3ebkQNvcdfGUM+yNCQOBa20LPGn4f9fSaMUaS0YENjQL9/BwclO4= X-Received: by 2002:a05:6402:278e:b0:604:e6fb:e2e1 with SMTP id 4fb4d7f45d1cf-6086b5d0bcbmr2283015a12.33.1749729906910; Thu, 12 Jun 2025 05:05:06 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Troy Brown Date: Thu, 12 Jun 2025 08:04:55 -0400 X-Gmail-Original-Message-ID: X-Gm-Features: AX0GCFvCqouwzn5rVQsDfRsPvTFPkceOifGD6JMwnDK-6ANkP5U55cFfQQW2YRU Message-ID: Subject: Re: bug#78703: beginning-of-defun and friends still wrong in typescript-ts-mode To: Yuan Fu Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 78703 Cc: Eli Zaretskii , Daniel Colascione , 78703@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) On Tue, Jun 10, 2025 at 2:02=E2=80=AFAM Yuan Fu wrote: > > > After that, I'm less concerned about its behavior, but think the > > current `nested` behavior of visiting the previous sibling defun until > > there are no more, then visiting the parent defun makes sense. The > > key difference is that you only visit the previous sibling if point is > > at a defun boundary...otherwise visit the defun containing point. > > Hmmm, it doesn=E2=80=99t feel very convenient, you=E2=80=99d need to firs= t adjust your point to be precisely at the boundary, then press C-M-a/e? IM= O that adds too much overhead. You shouldn't need to adjust point at all. By boundary, I'm referring to the place that `beginning-of-defun` (or `beginning-of-defun-comments`) would place you after running. I think something like the following demonstrates what I mean by this. When you're within a defun, it takes you to the beginning of the enclosing defun. After that, it moves according to the tactic. To me, this is much more intuitive than the current behavior, and I believe would have fixed the issues I described with the prog-fill-reindent-defun behavior. ```elisp (defun defun-boundary-p () (or ;; Just before a defun (save-excursion (forward-comment (point-max)) (when-let* ((treesit-defun-tactic 'nested) (node (treesit-defun-at-point))) (eq (point) (treesit-node-start node)))) ;; Just after a defun (save-excursion (skip-chars-backward " \t\n") (when (not (bobp)) (goto-char (1- (point))) (when-let* ((treesit-defun-tactic 'nested) (node (treesit-defun-at-point))) (eq (1+ (point)) (treesit-node-end node))))) ;; No enclosing defun (null (treesit-defun-at-point)))) (defun my/beginning-of-defun () (interactive) (if (defun-boundary-p) ;; adhere to tactic (beginning-of-defun) (let* ((treesit-defun-tactic 'nested) (node (treesit-defun-at-point))) (goto-char (treesit-node-start node)) (beginning-of-line)))) ```