unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* line/wrap-prefix patch
@ 2008-06-30  3:38 Miles Bader
  2008-06-30  4:18 ` Miles Bader
  2008-07-01 22:19 ` Stephen Berman
  0 siblings, 2 replies; 13+ messages in thread
From: Miles Bader @ 2008-06-30  3:38 UTC (permalink / raw)
  To: emacs-devel

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

Here's a patch that implements the "wrap-prefix" feature discussed
earlier.  It allows a prefix to be added to the beginning of each line
wrapped by redisplay.  It works with both word-wrapping and non-word
wrapping.

I also added a "line-prefix" feature which is the same thing for _non_
wrapped lines.

There are both buffer-local variables (`line-prefix', `wrap-prefix') and
text-property/overlay versions of both.

They may contain a string, an image or a `display'-property style
"space" spec.

Besides my current usage (adding "hanging indents" to word-wrapped-lines
in rcirc buffers), these features could be used to add other sorts of
word-processor-style spacing frobs, such as an implicit paragraph indent
(using line-prefix), additional vertical whitespace between "paragraphs"
(using a line-prefix with a value like (space :height 1.5)), etc.

Any comments?

-Miles


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: line/wrap-prefix patch --]
[-- Type: text/x-patch, Size: 10005 bytes --]

orig = emacs@sv.gnu.org/emacs--devo--0--patch-1298
mod = emacs@sv.gnu.org/emacs--devo--0--patch-1298

M  src/dispextern.h
M  src/ChangeLog
M  src/xdisp.c

--- orig/src/ChangeLog
+++ mod/src/ChangeLog
@@ -1,3 +1,19 @@
+2008-06-30  Miles Bader  <Miles Bader <miles@gnu.org>>
+
+	* dispextern.h (struct glyph, struct it, struct iterator_stack_entry):
+	Add `avoid_cursor_p' field.
+
+	* xdisp.c (push_it, pop_it): Save/restore avoid_cursor_p field.
+	(set_cursor_from_row): Skip glyphs with avoid_cursor_p set.
+	(append_glyph, append_composite_glyph, produce_image_glyph)
+	(append_stretch_glyph): Initialize avoid_cursor_p
+	(get_it_property): Renamed from `get_line_height_property'.
+	(x_produce_glyphs): Use get_it_property.
+	(handle_line_prefix, push_display_prop): New functions.
+	(display_line, move_it_in_display_line_to): Handle line/wrap prefixes.
+	(Vwrap_prefix, Qwrap_prefix, Vline_prefix, Qline_prefix): New variables.
+	(syms_of_xdisp): Initialize them.
+
 2008-06-30  Chong Yidong  <cyd@stupidchicken.com>
 
 	* xfaces.c (Finternal_merge_in_global_face): If default face was


--- orig/src/dispextern.h
+++ mod/src/dispextern.h
@@ -366,7 +366,11 @@
      doesn't have a glyph in a font.  */
   unsigned glyph_not_available_p : 1;
 
-#define FACE_ID_BITS	21
+ 
+  /* Non-zero means don't display cursor here.  */
+  unsigned avoid_cursor_p : 1;
+
+#define FACE_ID_BITS	20
 
   /* Face of the glyph.  This is a realized face ID,
      an index in the face cache of the frame.  */
@@ -1887,6 +1891,9 @@
      this is 1 if we're doing an ellipsis.  Otherwise meaningless.  */
   unsigned ellipsis_p : 1;
 
+  /* True means cursor shouldn't be displayed here.  */
+  unsigned avoid_cursor_p : 1;
+
   /* Display table in effect or null for none.  */
   struct Lisp_Char_Table *dp;
 
@@ -1987,6 +1994,7 @@
     unsigned multibyte_p : 1;
     unsigned string_from_display_prop_p : 1;
     unsigned display_ellipsis_p : 1;
+    unsigned avoid_cursor_p : 1;
 
     /* properties from display property that are reset by another display property. */
     Lisp_Object space_width;


--- orig/src/xdisp.c
+++ mod/src/xdisp.c
@@ -262,6 +262,9 @@
    cursor moves into it.  */
 Lisp_Object Vmouse_autoselect_window;
 
+Lisp_Object Vwrap_prefix, Qwrap_prefix;
+Lisp_Object Vline_prefix, Qline_prefix;
+
 /* Non-zero means draw tool bar buttons raised when the mouse moves
    over them.  */
 
@@ -853,6 +856,10 @@
 static int redisplay_mode_lines P_ ((Lisp_Object, int));
 static char *decode_mode_spec_coding P_ ((Lisp_Object, char *, int));
 
+static Lisp_Object get_it_property P_ ((struct it *it, Lisp_Object prop));
+
+static void handle_line_prefix P_ ((struct it *));
+
 #if 0
 static int invisible_text_between_p P_ ((struct it *, int, int));
 #endif
@@ -5210,6 +5217,7 @@
   p->string_nchars = it->string_nchars;
   p->area = it->area;
   p->multibyte_p = it->multibyte_p;
+  p->avoid_cursor_p = it->avoid_cursor_p;
   p->space_width = it->space_width;
   p->font_height = it->font_height;
   p->voffset = it->voffset;
@@ -5271,6 +5279,7 @@
   it->string_nchars = p->string_nchars;
   it->area = p->area;
   it->multibyte_p = p->multibyte_p;
+  it->avoid_cursor_p = p->avoid_cursor_p;
   it->space_width = p->space_width;
   it->font_height = p->font_height;
   it->voffset = p->voffset;
@@ -6677,6 +6686,12 @@
        || (it->method == GET_FROM_DISPLAY_VECTOR		\
 	   && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
 
+  /* If there's a line-/wrap-prefix, handle it.  */
+  if (it->hpos == 0 && it->method == GET_FROM_BUFFER
+      && it->current_y < it->last_visible_y)
+    {
+      handle_line_prefix (it);
+    }
 
   while (1)
     {
@@ -12222,7 +12237,8 @@
   while (glyph < end
 	 && !INTEGERP (glyph->object)
 	 && (!BUFFERP (glyph->object)
-	     || (last_pos = glyph->charpos) < pt_old))
+	     || (last_pos = glyph->charpos) < pt_old
+	     || glyph->avoid_cursor_p))
     {
       if (! STRINGP (glyph->object))
 	{
@@ -16290,6 +16306,78 @@
   return cursor_row_p;
 }
 
+\f
+
+/* Push the display property PROP so that it will be rendered at the
+   current position in IT.  */
+
+static void
+push_display_prop (struct it *it, Lisp_Object prop)
+{
+  push_it (it);
+
+  /* Never display a cursor on the prefix.  */
+  it->avoid_cursor_p = 1;
+
+  if (STRINGP (prop))
+    {
+      if (SCHARS (prop) == 0)
+	{
+	  pop_it (it);
+	  return;
+	}
+
+      it->string = prop;
+      it->multibyte_p = STRING_MULTIBYTE (it->string);
+      it->current.overlay_string_index = -1;
+      IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
+      it->end_charpos = it->string_nchars = SCHARS (it->string);
+      it->method = GET_FROM_STRING;
+      it->stop_charpos = 0;
+    }
+  else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
+    {
+      it->method = GET_FROM_STRETCH;
+      it->object = prop;
+    }
+#ifdef HAVE_WINDOW_SYSTEM
+  else if (IMAGEP (prop))
+    {
+      it->what = IT_IMAGE;
+      it->image_id = lookup_image (it->f, prop);
+      it->method = GET_FROM_IMAGE;
+    }
+#endif /* HAVE_WINDOW_SYSTEM */
+  else
+    {
+      pop_it (it);		/* bogus display property, give up */
+      return;
+    }
+}
+
+/* See if there's a line- or wrap-prefix, and if so, push it on IT.  */
+
+static void
+handle_line_prefix (struct it *it)
+{
+  Lisp_Object prefix;
+  if (it->continuation_lines_width > 0)
+    {
+      prefix = get_it_property (it, Qwrap_prefix);
+      if (NILP (prefix))
+	prefix = Vwrap_prefix;
+    }
+  else
+    {
+      prefix = get_it_property (it, Qline_prefix);
+      if (NILP (prefix))
+	prefix = Vline_prefix;
+    }
+  if (! NILP (prefix))
+    push_display_prop (it, prefix);
+}
+
+\f
 
 /* Construct the glyph row IT->glyph_row in the desired matrix of
    IT->w from text at the current position of IT.  See dispextern.h
@@ -16348,6 +16436,13 @@
       move_it_in_display_line_to (it, ZV, it->first_visible_x,
 				  MOVE_TO_POS | MOVE_TO_X);
     }
+  else
+    {
+      /* We only do this when not calling `move_it_in_display_line_to'
+	 above, because move_it_in_display_line_to calls
+	 handle_line_prefix itself.  */
+      handle_line_prefix (it);
+    }
 
   /* Get the initial row height.  This is either the height of the
      text hscrolled, if there is any, or zero.  */
@@ -20310,6 +20405,7 @@
       glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = CHAR_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20348,6 +20444,7 @@
       glyph->descent = it->descent;
       glyph->voffset = it->voffset;
       glyph->type = COMPOSITE_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20529,6 +20626,7 @@
 	  glyph->descent = it->descent;
 	  glyph->voffset = it->voffset;
 	  glyph->type = IMAGE_GLYPH;
+	  glyph->avoid_cursor_p = it->avoid_cursor_p;
 	  glyph->multibyte_p = it->multibyte_p;
 	  glyph->left_box_line_p = it->start_of_box_run_p;
 	  glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20573,6 +20671,7 @@
       glyph->descent = height - ascent;
       glyph->voffset = it->voffset;
       glyph->type = STRETCH_GLYPH;
+      glyph->avoid_cursor_p = it->avoid_cursor_p;
       glyph->multibyte_p = it->multibyte_p;
       glyph->left_box_line_p = it->start_of_box_run_p;
       glyph->right_box_line_p = it->end_of_box_run_p;
@@ -20740,12 +20839,10 @@
   take_vertical_position_into_account (it);
 }
 
-/* Get line-height and line-spacing property at point.
-   If line-height has format (HEIGHT TOTAL), return TOTAL
-   in TOTAL_HEIGHT.  */
+/* Return the character-property PROP at the current position in IT.  */
 
 static Lisp_Object
-get_line_height_property (it, prop)
+get_it_property (it, prop)
      struct it *it;
      Lisp_Object prop;
 {
@@ -21048,7 +21145,7 @@
 	  it->pixel_width = 0;
 	  it->nglyphs = 0;
 
-	  height = get_line_height_property(it, Qline_height);
+	  height = get_it_property(it, Qline_height);
 	  /* Split (line-height total-height) list */
 	  if (CONSP (height)
 	      && CONSP (XCDR (height))
@@ -21110,7 +21207,7 @@
 		spacing = calc_line_height_property(it, total_height, font, boff, 0);
 	      else
 		{
-		  spacing = get_line_height_property(it, Qline_spacing);
+		  spacing = get_it_property(it, Qline_spacing);
 		  spacing = calc_line_height_property(it, spacing, font, boff, 0);
 		}
 	      if (INTEGERP (spacing))
@@ -24924,6 +25021,32 @@
     doc: /* Non-nil means don't update menu bars.  Internal use only.  */);
   inhibit_menubar_update = 0;
 
+  DEFVAR_LISP ("wrap-prefix", &Vwrap_prefix,
+    doc: /* Prefix added to the beginning of all continuation lines at display-time.
+May be a string, an image, or a stretch-glyph such as used by the
+`display' text-property.
+
+This variable is overridden by any `wrap-prefix' text-property.
+
+To add a prefix to non-continuation lines, use the `line-prefix' variable.  */);
+  Vwrap_prefix = Qnil;
+  staticpro (&Qwrap_prefix);
+  Qwrap_prefix = intern ("wrap-prefix");
+  Fmake_variable_buffer_local (Qwrap_prefix);
+
+  DEFVAR_LISP ("line-prefix", &Vline_prefix,
+    doc: /* Prefix added to the beginning of all non-continuation lines at display-time.
+May be a string, an image, or a stretch-glyph such as used by the
+`display' text-property.
+
+This variable is overridden by any `line-prefix' text-property.
+
+To add a prefix to continuation lines, use the `wrap-prefix' variable.  */);
+  Vline_prefix = Qnil;
+  staticpro (&Qline_prefix);
+  Qline_prefix = intern ("line-prefix");
+  Fmake_variable_buffer_local (Qline_prefix);
+
   DEFVAR_BOOL ("inhibit-eval-during-redisplay", &inhibit_eval_during_redisplay,
     doc: /* Non-nil means don't eval Lisp during redisplay.  */);
   inhibit_eval_during_redisplay = 0;




[-- Attachment #3: Type: text/plain, Size: 66 bytes --]



-- 
Success, n. The one unpardonable sin against one's fellows.

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

* Re: line/wrap-prefix patch
  2008-06-30  3:38 line/wrap-prefix patch Miles Bader
@ 2008-06-30  4:18 ` Miles Bader
  2008-07-01  0:36   ` Miles Bader
  2008-07-01 22:19 ` Stephen Berman
  1 sibling, 1 reply; 13+ messages in thread
From: Miles Bader @ 2008-06-30  4:18 UTC (permalink / raw)
  To: emacs-devel

BTW here's the rcirc-mode-hook I use to enable these features for rcirc:

   (add-hook 'rcirc-mode-hook
             (lambda ()
               (setq rcirc-fill-flag nil)
               (setq word-wrap t)
               (setq wrap-prefix '(space :width 8))
               (push '(continuation) fringe-indicator-alist)
               (variable-pitch-mode t)))

[The `push' turns off wrapping indicators.]

-MIles

-- 
If you can't beat them, arrange to have them beaten.  [George Carlin]




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

* Re: line/wrap-prefix patch
  2008-06-30  4:18 ` Miles Bader
@ 2008-07-01  0:36   ` Miles Bader
  2008-07-01  4:52     ` Chong Yidong
  0 siblings, 1 reply; 13+ messages in thread
From: Miles Bader @ 2008-07-01  0:36 UTC (permalink / raw)
  To: emacs-devel

Hmm, if there aren't any objections, I'll write a bit of documentation
and commit my patch.

-Miles

-- 
I'd rather be consing.




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

* Re: line/wrap-prefix patch
  2008-07-01  0:36   ` Miles Bader
@ 2008-07-01  4:52     ` Chong Yidong
  2008-07-01  5:38       ` Miles Bader
  0 siblings, 1 reply; 13+ messages in thread
From: Chong Yidong @ 2008-07-01  4:52 UTC (permalink / raw)
  To: Miles Bader; +Cc: emacs-devel

Miles Bader <miles@gnu.org> writes:

> Hmm, if there aren't any objections, I'll write a bit of documentation
> and commit my patch.

Sure.  If possible, could you also take a look at making
move_it_in_display_line_to work, or at least try to ensure that it
doesn't work any worse (:-P) with your patch?




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

* Re: line/wrap-prefix patch
  2008-07-01  4:52     ` Chong Yidong
@ 2008-07-01  5:38       ` Miles Bader
  2008-07-01 14:10         ` Chong Yidong
  0 siblings, 1 reply; 13+ messages in thread
From: Miles Bader @ 2008-07-01  5:38 UTC (permalink / raw)
  To: Chong Yidong; +Cc: emacs-devel

Incidentally, there doesn't seem to be an entry for `word-wrap' in the
elisp manual... correct?

-Miles

-- 
Un-American, adj. Wicked, intolerable, heathenish.




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

* Re: line/wrap-prefix patch
  2008-07-01  5:38       ` Miles Bader
@ 2008-07-01 14:10         ` Chong Yidong
  0 siblings, 0 replies; 13+ messages in thread
From: Chong Yidong @ 2008-07-01 14:10 UTC (permalink / raw)
  To: Miles Bader; +Cc: emacs-devel

Miles Bader <miles.bader@necel.com> writes:

> Incidentally, there doesn't seem to be an entry for `word-wrap' in the
> elisp manual... correct?

Correct.  I haven't documented it yet (it's in NEWS, without a +++
sign).




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

* Re: line/wrap-prefix patch
  2008-06-30  3:38 line/wrap-prefix patch Miles Bader
  2008-06-30  4:18 ` Miles Bader
@ 2008-07-01 22:19 ` Stephen Berman
  2008-07-03  4:19   ` Miles Bader
  1 sibling, 1 reply; 13+ messages in thread
From: Stephen Berman @ 2008-07-01 22:19 UTC (permalink / raw)
  To: emacs-devel

On Sun, 29 Jun 2008 23:38:02 -0400 Miles Bader <miles@gnu.org> wrote:

> Here's a patch that implements the "wrap-prefix" feature discussed
> earlier.  It allows a prefix to be added to the beginning of each line
> wrapped by redisplay.
[...]
> Any comments?

I really like it.  I haven't tested it extensively yet, but it appears
to work for the most part as well as -- and in all likelihood in some
cases better than -- the modified version of longlines.el I wrote to get
this feature (posted at
<http://permalink.gmane.org/gmane.emacs.devel/100074>).  One nice
advantage of your implementation is that it does not, in conjunction
with auto-composition-mode, break isearch (see
<http://permalink.gmane.org/gmane.emacs.devel/90167>).  However, your
implementation does suffer from the same display problem at
(window-start) that mine does (see
<http://permalink.gmane.org/gmane.emacs.devel/86019>).  Here is a recipe
in terms of your implementation to show the problem:

1. emacs -Q

2. In an empty buffer type "test " enough time to make the line of text
longer than fill-column.

3. Type (setq word-wrap t wrap-prefix '(space :width 5)) and put the
cursor on the first `t' after the indentation.  Now the buffer displays
the following, where `|' marks the left fringe, and `^' the cursor:

|test test test test test test test test test test test test test test
|     test test 
      ^

4. Type M-: (scroll-up 1); now the buffer displays the following,
where again `|' marks the left fringe, and `^' the cursor:

|test test
 ^

That is, the displayed indentation is lost at window-start.  When I
reported this as a bug involving a display property with a newline
(which is what I use in my modification of longlines.el), RMS responded
thus:

> It seems to me that it is impossible to avoid this behavior,
> because the window-start value says to start the redisplay
> with the t that starts `test'.
> So it's more of a misfeature than a bug.

It still seems like a bug to me and I hope that you or someone else can
fix it.  

In fact, the problem is slightly worse (or at least different) in your
implementation than in mine.  Make the "test" line longer, so that after
wrapping it displays two indented lines, thus:

|test test test test test test test test test test test test test test test
|     test test test test test test test test test test test test test test
|     test test 

and append enough copies of that line to be able to scroll through
several screens, then scroll until you see this at the top of the
window:

|test test test test test test test test test test test test test test test
|     test test test test test test test test test test test test test test

The first line is in fact indented but this is not displayed due to the
"misfeature".  Now move the cursor up one line at a time until it gets
to the top and point is recentered.  Now you'll see this:

...
|test test test test test test test test test test test test test test test
|     test test test test test test test test test test test test test test
|     test test 
|test test test test test test test test test test test test test test test
|test test test test test test test test test test test test test test test
|     test test 
|test test test test test test test test test test test test test test test
|     test test test test test test test test test test test test test test
|     test test 
...

That is, the display bug is still visible, but now in the middle of the
window instead of at window-start.  Scrolling (but not line movement)
restores the proper display.  (In my implementation the display problem
seem confined to window-start, though it also has additional problems
that yours does not.)

I have two more comments.  One involves the continuation glyphs in the
fringes.  Probably it will usually be desirable to suppress them, but I
know of one case where it would be nice to suppress them only partially:
namely, if you have a long line that contains a string that cannot be
wrapped because it is longer than (window-width), such as a URL.  In
this case it would be nice to suppress the continuation glyphs on
wrappable long lines but display them on such unwrappable ones.

My final comment concerns adaptive filling.  In my modification of
longlines.el long lines are appropriately wrapped at different levels of
indentation, resulting in displays like this:

* test test test test test test test test test test test test test test 
  test test test test test test test test test test 
  * test test test test test test test test test test test test test 
    test test test test test test test test test test test test test 
    * test test test test test test test test test test test test test 
      test test test test test test test test test test test test test 
    * test test test test test test test test test test test test test 
      test test test test test test test test test test test test test 
  * test test test test test test test test test test test test test 
    test test test test test test test test test test

I get this by setting my equivalent of wrap-prefix to
(fill-context-prefix (line-beginning-position) (line-end-position)) each
time a new line is wrapped.  With your patch, doing (setq wrap-prefix
(fill-context-prefix (line-beginning-position) (line-end-position)))
results in a display like this:

* test test test test test test test test test test test test test test 
  test test test test test test test test test test 
  * test test test test test test test test test test test test test 
  test test test test test test test test test test test test test 
    * test test test test test test test test test test test test test 
  test test test test test test test test test test test test test 
    * test test test test test test test test test test test test test 
  test test test test test test test test test test test test test 
  * test test test test test test test test test test test test test 
  test test test test test test test test test test

It would be nice to get the appropriate indentation.

Steve Berman





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

* Re: line/wrap-prefix patch
  2008-07-01 22:19 ` Stephen Berman
@ 2008-07-03  4:19   ` Miles Bader
  2008-07-04 20:50     ` Stephen Berman
  0 siblings, 1 reply; 13+ messages in thread
From: Miles Bader @ 2008-07-03  4:19 UTC (permalink / raw)
  To: Stephen Berman; +Cc: emacs-devel

Stephen Berman <stephen.berman@gmx.net> writes:
> My final comment concerns adaptive filling.  In my modification of
> longlines.el long lines are appropriately wrapped at different levels of
> indentation, resulting in displays like this:
..
> With your patch, doing (setq wrap-prefix
> (fill-context-prefix (line-beginning-position) (line-end-position)))
> results in a display like this:
...
> It would be nice to get the appropriate indentation.

To get varying prefixes, you can use the `wrap-prefix' text property.

To do so automatically and dynamically would be interesting, but is
obviously more work.  I wonder what ways of specifying the prefix would
be practical (e.g., a text-property covering the "header" text at the
beginning of the physical line, which would be replaced by spaces to get
the wrap prefix, or a regexp used to match the header)?

-Miles

-- 
x
y
Z!




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

* Re: line/wrap-prefix patch
  2008-07-03  4:19   ` Miles Bader
@ 2008-07-04 20:50     ` Stephen Berman
  2008-07-04 21:25       ` Stefan Monnier
  2008-07-05  0:52       ` Miles Bader
  0 siblings, 2 replies; 13+ messages in thread
From: Stephen Berman @ 2008-07-04 20:50 UTC (permalink / raw)
  To: emacs-devel

On Thu, 03 Jul 2008 13:19:10 +0900 Miles Bader <miles.bader@necel.com> wrote:

> Stephen Berman <stephen.berman@gmx.net> writes:
>> My final comment concerns adaptive filling.  In my modification of
>> longlines.el long lines are appropriately wrapped at different levels of
>> indentation, resulting in displays like this:
> ..
>> With your patch, doing (setq wrap-prefix
>> (fill-context-prefix (line-beginning-position) (line-end-position)))
>> results in a display like this:
> ...
>> It would be nice to get the appropriate indentation.
>
> To get varying prefixes, you can use the `wrap-prefix' text property.

Yes, I see this when I evaluate e.g. (put-text-property (point) (1+
(point)) 'wrap-prefix "    ") with the cursor on the first character of
a wrapped word.  Is this the right way to use this text property?

> To do so automatically and dynamically would be interesting, but is
> obviously more work.  

If my usage above is correct, I think this approach would effectively
need to be augmented by something like longlines.el.  If I just enable
word wrapping and set wrap-prefix text properties as above, then as soon
as I add enough text to force new word wrapping before a position
indented by the wrap-prefix property, that indentation is lost.  Without
line wrapping via post-command-hook a la longlines.el I don't see how to
reliably retain the indentation after such changes in the previous text,
at least at the lisp level (the alternative would be to integrate
"adaptive indentation" into redisplay, as you did with "simple"
indentation).

>                       I wonder what ways of specifying the prefix would
> be practical (e.g., a text-property covering the "header" text at the
> beginning of the physical line, which would be replaced by spaces to get
> the wrap prefix, or a regexp used to match the header)?

I don't see how any "static" text property assignment will insure the
right indentation when the preceding text changes and forces new word
wrapping.

*********
I was really hoping you would respond to the display problem at
window-start.  I find it very dissatisfying to regard this as a
"misfeature" of Emacs redisplay and leave it that, as RMS seemed to
conclude was the only course to take.  Is it so infeasible to rework
window-start to handle indented wrapped lines?  I feel pretty helpless
when it comes to the Emacs C core, but if you or anyone would you point
me to the locus of this "misfeature" in the code I would be grateful.

Steve Berman





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

* Re: line/wrap-prefix patch
  2008-07-04 20:50     ` Stephen Berman
@ 2008-07-04 21:25       ` Stefan Monnier
  2008-07-05  0:52       ` Miles Bader
  1 sibling, 0 replies; 13+ messages in thread
From: Stefan Monnier @ 2008-07-04 21:25 UTC (permalink / raw)
  To: Stephen Berman; +Cc: emacs-devel

> If my usage above is correct, I think this approach would effectively
> need to be augmented by something like longlines.el.  If I just enable
> word wrapping and set wrap-prefix text properties as above, then as soon
> as I add enough text to force new word wrapping before a position
> indented by the wrap-prefix property, that indentation is lost.  Without
> line wrapping via post-command-hook a la longlines.el I don't see how to
> reliably retain the indentation after such changes in the previous text,
> at least at the lisp level (the alternative would be to integrate
> "adaptive indentation" into redisplay, as you did with "simple"
> indentation).

I'd expect it to be a job for jit-lock.


        Stefan




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

* Re: line/wrap-prefix patch
  2008-07-04 20:50     ` Stephen Berman
  2008-07-04 21:25       ` Stefan Monnier
@ 2008-07-05  0:52       ` Miles Bader
  2008-07-05 21:30         ` Stephen Berman
  1 sibling, 1 reply; 13+ messages in thread
From: Miles Bader @ 2008-07-05  0:52 UTC (permalink / raw)
  To: Stephen Berman; +Cc: emacs-devel

Stephen Berman <stephen.berman@gmx.net> writes:
>> To get varying prefixes, you can use the `wrap-prefix' text property.
>
> Yes, I see this when I evaluate e.g. (put-text-property (point) (1+
> (point)) 'wrap-prefix "    ") with the cursor on the first character of
> a wrapped word.  Is this the right way to use this text property?

You can put the property over the entire region of text that the
wrap-prefix applies to; there's no need to know which words will
actually get wrapped.

>> To do so automatically and dynamically would be interesting, but is
>> obviously more work.  
>
> If my usage above is correct, I think this approach would effectively
> need to be augmented by something like longlines.el

No.

>>                       I wonder what ways of specifying the prefix would
>> be practical (e.g., a text-property covering the "header" text at the
>> beginning of the physical line, which would be replaced by spaces to get
>> the wrap prefix, or a regexp used to match the header)?
>
> I don't see how any "static" text property assignment will insure the
> right indentation when the preceding text changes and forces new word
> wrapping.

The "right" indendation depends only on the text following the
preceding _hard_ line-start, i.e, the preceding "non-wrap prefix".

E.g., if you have the following long line:

     - This is a long-line-aka-paragraph blah blah blah blah blah blah blah

and you want to have it wrapped (at display-time) like:

     - This is a long-line-aka-paragraph blah
       blah blah blah blah blah blah

The tricky part is getting the wrap-prefix "       " by examining the
current non-wrap prefix, "     - " in this case.  Currently there's no
way of having the display engine do it, so one could alternatively have
a font-lock-like mechanism that turned hard paragraph prefixes into
wrap-prefix text properties.  One could also try to come up with a
mechanism to have the display engine do it dynamically (as I talked
about a bit in my previous message).

> *********
> I was really hoping you would respond to the display problem at
> window-start.  I find it very dissatisfying to regard this as a
> "misfeature" of Emacs redisplay and leave it that, as RMS seemed to
> conclude was the only course to take.

I haven't been able the reproduce it so far, so I need to try to do so
more thoroughly.  I'll try to do so this weekend.

-Miles

-- 
Friendship, n. A ship big enough to carry two in fair weather, but only one
in foul.




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

* Re: line/wrap-prefix patch
  2008-07-05  0:52       ` Miles Bader
@ 2008-07-05 21:30         ` Stephen Berman
  2008-07-06  1:05           ` Stefan Monnier
  0 siblings, 1 reply; 13+ messages in thread
From: Stephen Berman @ 2008-07-05 21:30 UTC (permalink / raw)
  To: emacs-devel

On Sat, 05 Jul 2008 09:52:17 +0900 Miles Bader <miles@gnu.org> wrote:

> Stephen Berman <stephen.berman@gmx.net> writes:
>>> To get varying prefixes, you can use the `wrap-prefix' text property.
>>
>> Yes, I see this when I evaluate e.g. (put-text-property (point) (1+
>> (point)) 'wrap-prefix "    ") with the cursor on the first character of
>> a wrapped word.  Is this the right way to use this text property?
>
> You can put the property over the entire region of text that the
> wrap-prefix applies to; there's no need to know which words will
> actually get wrapped.

Ah, thank you, that didn't occur to me.

[...]
> The "right" indendation depends only on the text following the
> preceding _hard_ line-start, i.e, the preceding "non-wrap prefix".
[...]
> The tricky part is getting the wrap-prefix "       " by examining the
> current non-wrap prefix, "     - " in this case.  Currently there's no
> way of having the display engine do it, so one could alternatively have
> a font-lock-like mechanism that turned hard paragraph prefixes into
> wrap-prefix text properties.

On Fri, 04 Jul 2008 17:25:15 -0400 Stefan Monnier
<monnier@iro.umontreal.ca> wrote: 

> I'd expect it to be a job for jit-lock.

Thanks to both of you for these suggestions.  The following seems to
DTRT, at least according to my minimal testing; no doubt it could be
improved:

(defun srb-adaptive-indent (beg end)
  "Indent the region between BEG and END with adaptive filling."
  (goto-char beg)
  (let ((lbp (line-beginning-position))
	(lep (line-end-position)))
    (put-text-property lbp lep 'wrap-prefix (fill-context-prefix lbp lep)))
  (while (re-search-forward "\n" (point-max) t)
    (forward-char)
    (let ((lbp (line-beginning-position))
	  (lep (line-end-position)))
      (put-text-property lbp lep 'wrap-prefix (fill-context-prefix lbp lep)))))

(define-minor-mode srb-adaptive-wrap-mode
  "Wrap the buffer text with adaptive filling."
  :lighter ""
  (save-excursion
    (save-restriction
      (widen)
      (let ((buffer-undo-list t)
	    (inhibit-read-only t)
	    (mod (buffer-modified-p)))
	(if srb-adaptive-wrap-mode
	    (progn
	      (setq word-wrap t)
	      (unless (member '(continuation) fringe-indicator-alist)
		(push '(continuation) fringe-indicator-alist))
	      (jit-lock-register 'srb-adaptive-indent))
	  (jit-lock-unregister 'srb-adaptive-indent)
	  (remove-text-properties (point-min) (point-max) '(wrap-prefix pref))
	  (setq fringe-indicator-alist
		(delete '(continuation) fringe-indicator-alist))
	  (setq word-wrap nil))
	(set-buffer-modified-p mod)))))

Miles continued:

>> *********
>> I was really hoping you would respond to the display problem at
>> window-start.  I find it very dissatisfying to regard this as a
>> "misfeature" of Emacs redisplay and leave it that, as RMS seemed to
>> conclude was the only course to take.
>
> I haven't been able the reproduce it so far, so I need to try to do so
> more thoroughly.  I'll try to do so this weekend.

Do you use a proportional font?  I always used a monospaced font (mostly
Dejavu Sans Mono) and with that the recipe I gave is reliable.  But I
just tried it with a proportional font (Dejavu Sans), and to my surprise
my recipe failed, i.e. the indentation remained visible at window-start.
No idea why fixed and proportional fonts differ here.

Steve Berman





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

* Re: line/wrap-prefix patch
  2008-07-05 21:30         ` Stephen Berman
@ 2008-07-06  1:05           ` Stefan Monnier
  0 siblings, 0 replies; 13+ messages in thread
From: Stefan Monnier @ 2008-07-06  1:05 UTC (permalink / raw)
  To: Stephen Berman; +Cc: emacs-devel

> (defun srb-adaptive-indent (beg end)
>   "Indent the region between BEG and END with adaptive filling."
>   (goto-char beg)
>   (let ((lbp (line-beginning-position))
> 	(lep (line-end-position)))
>     (put-text-property lbp lep 'wrap-prefix (fill-context-prefix lbp lep)))
>   (while (re-search-forward "\n" (point-max) t)
>     (forward-char)
>     (let ((lbp (line-beginning-position))
> 	  (lep (line-end-position)))
>       (put-text-property lbp lep 'wrap-prefix (fill-context-prefix lbp lep)))))

Toi avoid code-duplication:

 (defun srb-adaptive-indent (beg end)
   "Indent the region between BEG and END with adaptive filling."
   (goto-char beg)
   (while
       (let ((lbp (line-beginning-position))
 	     (lep (line-end-position)))
         (put-text-property lbp lep 'wrap-prefix (fill-context-prefix lbp lep))
         (search-forward "\n" end t))))

Actually this also fixes a "point-max vs end" confusion, and removes
a `forward-char' which didn't seem necessary.

> 	  (setq word-wrap nil))

Actually, this minor-mode seems independent from word-wrap, so it had
better not touch word-wrap at all.  Similarly, I'm not sure that
fringe-indicator-alist should be touched here.

>	(set-buffer-modified-p mod)))))

You should use restore-buffer-modified-p instead.

        Stefan




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

end of thread, other threads:[~2008-07-06  1:05 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-30  3:38 line/wrap-prefix patch Miles Bader
2008-06-30  4:18 ` Miles Bader
2008-07-01  0:36   ` Miles Bader
2008-07-01  4:52     ` Chong Yidong
2008-07-01  5:38       ` Miles Bader
2008-07-01 14:10         ` Chong Yidong
2008-07-01 22:19 ` Stephen Berman
2008-07-03  4:19   ` Miles Bader
2008-07-04 20:50     ` Stephen Berman
2008-07-04 21:25       ` Stefan Monnier
2008-07-05  0:52       ` Miles Bader
2008-07-05 21:30         ` Stephen Berman
2008-07-06  1:05           ` Stefan Monnier

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).