From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.ciao.gmane.io!not-for-mail From: Yuan Fu Newsgroups: gmane.emacs.devel Subject: Re: Support paragraph-local tab stops Date: Wed, 27 May 2020 11:48:35 -0400 Message-ID: References: <83a71ttn0b.fsf@gnu.org> Mime-Version: 1.0 (Mac OS X Mail 13.4 \(3608.80.23.2.2\)) Content-Type: multipart/mixed; boundary="Apple-Mail=_71AC5603-3F53-401E-A0F0-175F47D30C6A" Injection-Info: ciao.gmane.io; posting-host="ciao.gmane.io:159.69.161.202"; logging-data="62060"; mail-complaints-to="usenet@ciao.gmane.io" Cc: emacs-devel To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed May 27 17:49:14 2020 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jdyIs-000G6k-7c for ged-emacs-devel@m.gmane-mx.org; Wed, 27 May 2020 17:49:14 +0200 Original-Received: from localhost ([::1]:46544 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jdyIr-0000Us-AI for ged-emacs-devel@m.gmane-mx.org; Wed, 27 May 2020 11:49:13 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:53076) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jdyIK-0008Tk-9K for emacs-devel@gnu.org; Wed, 27 May 2020 11:48:40 -0400 Original-Received: from mail-qk1-x72e.google.com ([2607:f8b0:4864:20::72e]:41937) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1jdyIJ-0004E7-9n; Wed, 27 May 2020 11:48:39 -0400 Original-Received: by mail-qk1-x72e.google.com with SMTP id n11so19311691qkn.8; Wed, 27 May 2020 08:48:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:message-id:mime-version:subject:date:in-reply-to:cc:to :references; bh=3Sv8EGLG4nzldpOerhsRuqlsz3m2T/LDrq5YWr1eLJI=; b=BNFRE4X6IPqqmMwd3g9HgfuSZGLQB3M1VHvfpezz+/MaLaXAK8IDNaWA0Lb8WgofS4 061UkrPAvfy3Z7/VgYMzcLmEkSFwtS38N9+je8agr+5gW48fKusCOjGYZrrlhKoGOiE0 Iq5TA8FkgN1wKmJJo6Qae6S8LaKGfqIQiE3za6D0+AIv4eaLcZX3Pe5SqcMbRaDt+ui0 jhYWTkOXD5q7RttMO3kJHe5sourBoa8uY3S97IcecgFrxOLg/uiKx5GU9ZRpfzcuLW+B zBJIRhbr5pFzpDt+/g1wGY+rsNVdQiTAaqToDtGZG/bzDP7cORBCIGOZ2XoQmChcwk8M iktw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:message-id:mime-version:subject:date :in-reply-to:cc:to:references; bh=3Sv8EGLG4nzldpOerhsRuqlsz3m2T/LDrq5YWr1eLJI=; b=f8aCSgtr/Z2aOoSOF36Oh2/LWKAf/lGS95W11B01nyZkOG9CKhLCU9HvCfKcZqofjm tT7QTPKOWl+gGvyIjyYweZjB1U80ogxrwJDodA/fGVYE7NELJTzadhaG8eGK3uJ+vKQq /EqKWOwo7rAp3iBysSDRSp9pz8tM7ZKi/v9DCLUvcmkWCN+Ks6e8ePJ+Yl+zBxF4HAYu hmBNXXMdlLYxFO5U92XOldkVb6KrwJQf3vTqMm07hX8nyZIsd93ES0X2rxFUMHJXc1L1 JPjKz2SA8YOGSMMUutNelL3LqBOAs8JFwUI7+p9lrkJ+aRz6KfsfPAh6W/pOHAOXk/7K P4eg== X-Gm-Message-State: AOAM532w0FpjGvWwkBXCo1WWJq9fitX687g4PINmnCPNMg27sAHrHv70 xAHAb8MTKYgiROFKf3pHV1U8mAV8bYnSpw== X-Google-Smtp-Source: ABdhPJxnqUN8QWf3A0sRB9rV5MuagWOcTGmnoyLKHFYqpKGx2kzkMPcY+LoyLjV70utCPnxlsFW0Ew== X-Received: by 2002:a05:620a:c0f:: with SMTP id l15mr4795766qki.183.1590594517393; Wed, 27 May 2020 08:48:37 -0700 (PDT) Original-Received: from [192.168.1.10] (c-174-60-229-153.hsd1.pa.comcast.net. [174.60.229.153]) by smtp.gmail.com with ESMTPSA id v2sm2701279qtq.8.2020.05.27.08.48.36 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 May 2020 08:48:36 -0700 (PDT) In-Reply-To: <83a71ttn0b.fsf@gnu.org> X-Mailer: Apple Mail (2.3608.80.23.2.2) Received-SPF: pass client-ip=2607:f8b0:4864:20::72e; envelope-from=casouri@gmail.com; helo=mail-qk1-x72e.google.com X-detected-operating-system: by eggs.gnu.org: No matching host in p0f cache. That's all we know. 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, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=_AUTOLEARN X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:251509 Archived-At: --Apple-Mail=_71AC5603-3F53-401E-A0F0-175F47D30C6A Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On May 27, 2020, at 11:29 AM, Eli Zaretskii wrote: >=20 >> From: Yuan Fu >> Date: Tue, 26 May 2020 19:26:01 -0400 >>=20 >> As show above, the second table has longer tab stops since they have = longer headers. >>=20 >> In Emacs, both table would have to use long tab stops, and the first = table with short headers would waste a lot of space. In order to set = proper tab stops, you have to go through the whole buffer and use the = longest header for each column. >>=20 >> Word processors doesn=E2=80=99t have this problem because they have = paragraph-local tab stops, so each table can have their own tabs stops. = I wonder if Emacs can do the same. Can we add a text property that = points to a list that specifies the tabs stops to use? Is that possible? >=20 > IMO, TAB stops are not the right tool for the job here. You need to > use the :align-to display property, which allows to align text with > pixel granularity. I think both approach are equally appropriate. And the tab-based one = aligns more closely to word processors. If we want to gradually add = WYSIWYG editor features, and enable Emacs to edit rich text, this is an = unavoidable feature. I just wrote a (very rough) proof-of-concept patch=E2=80=94it=E2=80=99s = much easier than I thought. With the patch you can do something like (put-text-property (region-beginning) (region-end) 'pixel-tab-stop-list '(70 140 210 280 350 420)) Yuan --Apple-Mail=_71AC5603-3F53-401E-A0F0-175F47D30C6A Content-Disposition: attachment; filename=tab-stop.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="tab-stop.patch" Content-Transfer-Encoding: 7bit diff --git a/src/xdisp.c b/src/xdisp.c index 01f272033e..303bb7df37 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -29818,6 +29818,25 @@ #define IT_APPLY_FACE_BOX(it, face) \ } \ } while (false) + +/* Return the next tab stop according to the current x position + CURRENT_X_POS and given TAB_STOP_LIST. Return -1 if none + found. */ +static int next_tab_stop_x (Lisp_Object tab_stop_list, + ptrdiff_t current_x_pos) +{ + Lisp_Object tail = tab_stop_list; + for (; CONSP (tail); tail = XCDR (tail)) + { + CHECK_FIXNAT (XCAR (tail)); + double this_tab_stop = XFIXNUM (XCAR (tail)); + if (current_x_pos < this_tab_stop) + return (int) this_tab_stop; + } + return -1; +} + + /* RIF: Produce glyphs/get display metrics for the display element IT is loaded with. See the description of struct it in dispextern.h @@ -30090,13 +30109,20 @@ gui_produce_glyphs (struct it *it) x += it->tab_offset; } - int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; + /* Try to calculate tab stop by text property. */ + ptrdiff_t charpos = IT_CHARPOS (*it); + Lisp_Object pixel_tab_stop_list = Fget_text_property + (make_fixnum (charpos), Qpixel_tab_stop_list, Qnil); + + int next_tab_x = next_tab_stop_x(pixel_tab_stop_list, x); + if (next_tab_x == -1) + next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width; /* If the distance from the current position to the next tab stop is less than a space character width, use the tab stop after that. */ - if (next_tab_x - x < font->space_width) - next_tab_x += tab_width; + /* if (next_tab_x - x < font->space_width) */ + /* next_tab_x += tab_width; */ if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p) { next_tab_x += it->lnum_pixel_width; @@ -30138,7 +30164,7 @@ gui_produce_glyphs (struct it *it) if (it->descent < 0) it->descent = 0; } - else + else /* I.e., !(FONT_TOO_HIGH (font)). */ { it->ascent = FONT_BASE (font) + boff; it->descent = FONT_DESCENT (font) - boff; @@ -30152,11 +30178,12 @@ gui_produce_glyphs (struct it *it) it->ascent + it->descent, it->ascent); } } - else + else /* I.e., (font->space_width <= 0). */ { it->pixel_width = 0; it->nglyphs = 1; } + /* End of (it->char_to_display == '\t'). */ } if (FONT_TOO_HIGH (font)) @@ -34231,6 +34258,7 @@ syms_of_xdisp (void) DEFSYM (QCfile, ":file"); DEFSYM (Qfontified, "fontified"); DEFSYM (Qfontification_functions, "fontification-functions"); + DEFSYM (Qpixel_tab_stop_list, "pixel-tab-stop-list"); /* Name of the symbol which disables Lisp evaluation in 'display' properties. This is used by enriched.el. */ --Apple-Mail=_71AC5603-3F53-401E-A0F0-175F47D30C6A--