unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* the overloading of `tab-width'
@ 2002-06-15 17:38 Colin Walters
  2002-06-15 18:21 ` Colin Walters
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Colin Walters @ 2002-06-15 17:38 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 2831 bytes --]

So, I've been doing a lot of work on another project, whose authors
start out every file with: 

/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */

Now, personally, I find this irritating in the extreme.  If I nest about
four blocks, with a long function name or two, the lines begin to wrap
very quickly.  One thing I do like about the GNU Coding style is that it
says to perform indentation by 2 columns. 

Unfortunately, believe it or not, Emacs gives me no way to deal with
this.  You may say, "You can just change `tab-width'", but in fact I
can't.  If I set `tab-width' to 2, then everything shrinks nicely to the
left.  However, I can't just hit TAB anymore to do indentation, because
CC mode decides it has to insert *four* tabs in order to make up to the
`c-basic-offset' value of 8. 

Now, your next response might be, "Why can't you just set *both*
c-basic-offset and tab-width to 2"?  And the answer is because that can
change the buffer's representation on disk.  For example, in the
following code: 

static char *
get_file_content (EMsgComposer *composer, const char *file_name, gboolean want_html, guint flags, gboolean warn)
{
[...]
	if (fd == -1) {
[...]
		if (warn) {
			msg = g_strdup_printf (_("Error while reading file %s:\n%s"),
					       file_name, g_strerror (errno));
If I hit TAB on the last line while `c-basic-offset' and `tab-width' are
both 8, everything is fine.  However, If I set them both to 2, then hit
TAB, CC mode will insert a bunch of tab characters to try to line it up
with the end of function name, which is wrong.  Really, I don't want to
change the representation on disk at all. 

I think this problem came about because packages started using
`tab-width' to convert between actual TAB and space characters. 
According to its docstring, it is only for display purposes, but CC mode
and functions like `tabify' use it for other purposes. 

So I finally got fed up enough with this situation to write the
following patch.  It should basically be self-explanatory. 

The final question is probably "What's the disadvantage?".  Given that
the tab/space problem has plagued programmers for decades, one would
have every right to be surprised if this patch could make things Just
Work the way each person wants it to.  And indeed, there is a
disadvantage:  If I keep the (awful) settings of `c-basic-offset' and
`tab-width' => 8, which I must do in order to prevent spurious conflicts
and bloated patches, but I set `display-tab-width' => 2, then in the
above situation, the parameters no longer line up with the function name
(in display terms). 

But I'm willing to live with that disadvantage, in order to get much
less line wrapping. 

Another solution we should pursue is giving some way to tell CC mode to
*only* insert tabs when performing indentation.




[-- Attachment #2: disptabwidth.patch --]
[-- Type: text/x-patch, Size: 3435 bytes --]

Index: src/buffer.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/buffer.h,v
retrieving revision 1.85
diff -u -d -r1.85 buffer.h
--- src/buffer.h	10 Jan 2002 11:13:17 -0000	1.85
+++ src/buffer.h	15 Jun 2002 17:38:29 -0000
@@ -594,10 +594,11 @@
   Lisp_Object category_table;
 
   /* Values of several buffer-local variables.  */
-  /* tab-width is buffer-local so that redisplay can find it
-     in buffers that are not current.  */
+  /* tab-width and display-tab-width are buffer-local so that
+     redisplay can find it in buffers that are not current.  */
   Lisp_Object case_fold_search;
   Lisp_Object tab_width;
+  Lisp_Object display_tab_width;
   Lisp_Object fill_column;
   Lisp_Object left_margin;
   /* Function to call when insert space past fill column.  */
Index: src/buffer.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/buffer.c,v
retrieving revision 1.388
diff -u -d -r1.388 buffer.c
--- src/buffer.c	8 Jun 2002 20:25:31 -0000	1.388
+++ src/buffer.c	15 Jun 2002 17:38:30 -0000
@@ -4859,6 +4859,7 @@
   XSETFASTINT (buffer_defaults.overlay_center, BEG);
 
   XSETFASTINT (buffer_defaults.tab_width, 8);
+  buffer_defaults.display_tab_width = Qnil;
   buffer_defaults.truncate_lines = Qnil;
   buffer_defaults.ctl_arrow = Qt;
   buffer_defaults.direction_reversed = Qnil;
@@ -4919,6 +4920,7 @@
   XSETFASTINT (buffer_local_flags.selective_display_ellipses, idx); ++idx;
 #endif
   XSETFASTINT (buffer_local_flags.tab_width, idx); ++idx;
+  XSETFASTINT (buffer_local_flags.display_tab_width, idx); ++idx;
   XSETFASTINT (buffer_local_flags.truncate_lines, idx); ++idx;
   XSETFASTINT (buffer_local_flags.ctl_arrow, idx); ++idx;
   XSETFASTINT (buffer_local_flags.fill_column, idx); ++idx;
@@ -5288,7 +5290,28 @@
 
   DEFVAR_PER_BUFFER ("tab-width", &current_buffer->tab_width,
 		     make_number (Lisp_Int),
-		     doc: /* *Distance between tab stops (for display of tab characters), in columns.  */);
+		     doc: /* *Distance between tab stops, in columns.
+Historically, this variable was only meant to represent the number of
+columns which compose a tab character for display purposes.  However,
+a number of packages began to use it for conversion between tab and
+space characters (e.g. `tabify'), as well as calculating how many
+tab/space characters to insert into a buffer (e.g. CC mode).
+
+Therefore, the variable `display-tab-width' (which see) was introduced
+to allow you to control the display of a tab character, independently
+of how many columns (space characters) you wish it to actually occupy
+in the buffer.  */);
+
+  DEFVAR_PER_BUFFER ("display-tab-width", &current_buffer->display_tab_width,
+		     make_number (Lisp_Int),
+		     doc: /* *Distance between tab stops (for display of tab characters), in columns.
+In addition to an integer, this variable can also be nil, in which
+case the value of `tab-width' is used.
+
+This variable is only meant for controlling how literal tab characters
+are displayed to the user; do not use it to convert between tab and
+actual space characters or other purposes!  Instead, use the variable
+`tab-width' for that. */);
 
   DEFVAR_PER_BUFFER ("ctl-arrow", &current_buffer->ctl_arrow, Qnil,
 		     doc: /* *Non-nil means display control chars with uparrow.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: the overloading of `tab-width'
  2002-06-15 17:38 the overloading of `tab-width' Colin Walters
@ 2002-06-15 18:21 ` Colin Walters
  2002-06-15 18:57 ` Kai Großjohann
  2002-06-16 23:28 ` Richard Stallman
  2 siblings, 0 replies; 4+ messages in thread
From: Colin Walters @ 2002-06-15 18:21 UTC (permalink / raw)


[-- Attachment #1: Type: text/plain, Size: 58 bytes --]

Ah, and you probably need the patch for xdisp.c...








[-- Attachment #2: xdisp.patch --]
[-- Type: text/x-patch, Size: 708 bytes --]

Index: src/xdisp.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/xdisp.c,v
retrieving revision 1.755
diff -u -d -r1.755 xdisp.c
--- src/xdisp.c	12 Jun 2002 09:37:34 -0000	1.755
+++ src/xdisp.c	15 Jun 2002 18:20:51 -0000
@@ -1614,7 +1614,8 @@
     it->redisplay_end_trigger_charpos = XINT (w->redisplay_end_trigger);
 
   /* Correct bogus values of tab_width.  */
-  it->tab_width = XINT (current_buffer->tab_width);
+  it->tab_width = INTEGERP (current_buffer->display_tab_width) ?
+    current_buffer->display_tab_width : XINT (current_buffer->tab_width);
   if (it->tab_width <= 0 || it->tab_width > 1000)
     it->tab_width = 8;
 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: the overloading of `tab-width'
  2002-06-15 17:38 the overloading of `tab-width' Colin Walters
  2002-06-15 18:21 ` Colin Walters
@ 2002-06-15 18:57 ` Kai Großjohann
  2002-06-16 23:28 ` Richard Stallman
  2 siblings, 0 replies; 4+ messages in thread
From: Kai Großjohann @ 2002-06-15 18:57 UTC (permalink / raw)
  Cc: emacs-devel

Colin Walters <walters@gnu.org> writes:

> Unfortunately, believe it or not, Emacs gives me no way to deal with
> this.  You may say, "You can just change `tab-width'", but in fact I
> can't.  If I set `tab-width' to 2, then everything shrinks nicely to the
> left.  However, I can't just hit TAB anymore to do indentation, because
> CC mode decides it has to insert *four* tabs in order to make up to the
> `c-basic-offset' value of 8. 
>
> Now, your next response might be, "Why can't you just set *both*
> c-basic-offset and tab-width to 2"?  And the answer is because that can
> change the buffer's representation on disk.  For example, in the
> following code: 

It was my impression that the problem can only be solved by
introducing two kinds of indentation.  When going one brace level
deeper in the structure of the program, there is whitespace at the
beginning of the line to indicate this.  But then, there are
statements which are split over several lines and the second line
contains whitespace to line it up with the first.

For the "brace-level" indentation, it would work to use one tab for
each level and to then change the displayed width of a tab.

But for the "alignment" indentation, this does not work.  Consider
this piece of code:

if ( a == b ) {
    foo(a,
        b);
//  X   Y
}

Consider the third line.  The first part of whitespace comes (up to
the X indicated in fourth (comment) line) is of the "indentation"
kind.  The second part, from X to Y, is of the "alignment" kind.

I think it would be useful to teach modes about the two kinds of
alignment.  Then there could be a user option to use "one tab per
level" for the indentation and "spaces only" for the alignment.

So with a tab-width of 4, the third line in the example would start
with one tab (for the brace level), and four spaces.

What do people think?

This change is not easy, since every mode has to be changed
separately.

kai
-- 
~/.signature is: umop 3p!sdn    (Frank Nobis)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: the overloading of `tab-width'
  2002-06-15 17:38 the overloading of `tab-width' Colin Walters
  2002-06-15 18:21 ` Colin Walters
  2002-06-15 18:57 ` Kai Großjohann
@ 2002-06-16 23:28 ` Richard Stallman
  2 siblings, 0 replies; 4+ messages in thread
From: Richard Stallman @ 2002-06-16 23:28 UTC (permalink / raw)
  Cc: emacs-devel

    Now, personally, I find this irritating in the extreme.  If I nest about
    four blocks, with a long function name or two, the lines begin to wrap
    very quickly.  One thing I do like about the GNU Coding style is that it
    says to perform indentation by 2 columns. 

    Unfortunately, believe it or not, Emacs gives me no way to deal with
    this.

What does it mean to "deal with this"?

In general, if you don't like the way a file is indented, the only way
you can see it differently is to reindent it.  That means changing the
text.  I don't see that it is particularly useful to try to avoid that
consequence in this one special case.

    I think this problem came about because packages started using
    `tab-width' to convert between actual TAB and space characters. 
    According to its docstring, it is only for display purposes, but CC mode
    and functions like `tabify' use it for other purposes. 

Everything that affects how wide characters are in display also
affects the indentation functions.

I don't think this feature makes sense, and I don't think it should be
installed.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-06-16 23:28 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-06-15 17:38 the overloading of `tab-width' Colin Walters
2002-06-15 18:21 ` Colin Walters
2002-06-15 18:57 ` Kai Großjohann
2002-06-16 23:28 ` Richard Stallman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).