[comp.emacs] line numbers in emacs

michel@euteal.UUCP (Michel Berkelaar) (02/01/89)

I'm looking for an emacs minor mode which will add line numbers to all lines
and still allow editing, scrolling, saving (without those numbers),
etc to go on. It seems so basic that someone must have worked on it.
If there are any hints, please post, or mail to:

Michel Berkelaar
Eindhoven University of Technology
The Netherlands
mcvax!hp4nl!euteal!michel

cantrell@killer.DALLAS.TX.US (Keith Cantrell) (02/01/89)

In article <22@euteal.UUCP> michel@euteal.UUCP (Michel Berkelaar) writes:
>
>I'm looking for an emacs minor mode which will add line numbers to all lines
>and still allow editing, scrolling, saving (without those numbers),
>etc to go on. It seems so basic that someone must have worked on it.
>If there are any hints, please post, or mail to:
>

Has anybody at least hacked up the status line to show the line number of the
line that is at the top of the screen?  I think this should be enough
information for most applications.

Keith

-----------------------------------------------------------------------
Keith Cantrell                Phones:  hm: 214-492-1088
Integrated Telecom                     wk: 214-234-3340

USMAIL:                       EMAIL:
2100 Sonata Ln                cantrell@killer.DALLAS.TX.US
Carrollton Tx 75007                   or
                              ...!uunet!killer!dalitc!keith
-----------------------------------------------------------------------

inc@tc.fluke.COM (Gary Benson) (02/04/89)

Me too! Me too!  I have long wanted a line number indicator in emacs. We
have an indication of percent, but that is precious little use if you don't
know how big the file is! For example, right now my status line is
indicating "53%". So what? I can't see the whole file, so all I know is that
I'm about halfway in; and now (2 lines later) the line reads 57% it must be
"kind of small". I HATE GUESSWORK!!

What I'd *really* like on the status line is:

              Line 101 of 3745 (3%)

That gives me not only real numbers to use for estimating numbers when I use
"goto-line", and "goto-percent", it also gives me enough information to know
where I am in a document I may not have created. Even some I *did* create, I
may forget how big they are after not seeing them for 6 or 8 months. These
things happen.

While writing this message, I also noticed that the particular incantation
of emacs I am using only updates the percentage on the status line when I
type a character! Not when I go forward and backward...anyone have any idea
how much performance would suffer if I had those operations also update the
status line?

Gary Benson
inc@tc.fluke.COM

mesard@bbn.com (Wayne Mesard) (02/07/89)

In article <22@euteal.UUCP> michel@euteal.UUCP (Michel Berkelaar) writes:
>
>I'm looking for an emacs minor mode which will add line numbers to all lines
>and still allow editing, scrolling, saving (without those numbers),
>etc to go on.  It seems so basic that someone must have worked on it.

One would think so, but Control-X L seems adequate for most people's needs.

>If there are any hints, please post, or mail to:

I have what may be an answer.  Well, two answers.  And since I'm in
M-x verbose-mode today.  You're gonna have to wade through a bunch of
prose to get to them.

Some time ago, I wrote commands to stuff line numbers into the current
region or buffer.  This solution has the benefits of simplicity:

------------LINE-NUMBERS-TAKE-1---------
(defun line-number-region (beg end &optional relative)
  "Insert line number labels at the beginning of every line in the region.
Each label will be the same length so that it's trivial to write a function
or keyboard macro to delete them at a later time.
With optional [third] argument, RELATIVE, start counting from 1 no matter
where we are in the buffer.  Otherwise, begin counting from the starting 
line number.
"
  (interactive "r\nP")
  (save-excursion
    (let ((num (if relative 1 (1+ (count-lines (point-min) beg))))
	  (digitc
	   (length (int-to-string (count-lines 
				   (if relative beg (point-min))
				   end))))
	  )
      (goto-char end)
      (end-of-line)
      (setq end (point-marker))
      (goto-char beg)
      (beginning-of-line)
      (while (< (point) end)
	(insert (substring "0000000" 0 (- digitc (length (int-to-string num))))
		(int-to-string num)
		?:)
	(setq num (1+ num))
	(forward-line 1)
	)))
)


(defun line-number-buffer ()
  "Put line numbers at the start of every line in the buffer."
  (interactive)
  (line-number-region (point-min) (point-max) t)
  )
------------LINE-NUMBERS-TAKE-1---------

This is basically useless if you want the line numbers there while
you're editing.

When I saw your message, it renewed my frustration at the fact that
there's no way to write a minor mode in GNU elisp.  The basic mechanism
needed to get line numbers displayed is to have an interrupt facility
(or something) periodically call an elisp function which checks to see
if the window has been scrolled recently, and does the right thing if it
has.

My first thought was that it would be interesting to create a new
keymap, bind every key to the same function, and have that function do
its minor-mode-type-thing and then call the function which is normally
bound to that key:

	(let ((cmd (aref *old-map* (this-command-keys))))
	  ...
	  (call-interactively cmd))))

Well, that is interesting, except it doesn't work so good.  (Left as an
exercise to the reader.)

My second thought was, lacking an explicit interrupt or
on-redisplay-hook type of thing, I could abuse the procedure facility
(used in emacs/lisp/time.el) to do the equivalent.  All that's needed is
a program which will periodically dump a character onto its output.
loadst(1) which comes with GNU Emacs and BSD's yes(1) both fit this
bill.  But I used the "peep" shellscript below:

------peep--------Put this on your PATH------------
while [ 1 ]
do
 echo -n x
 sleep $1
done
------peep--------

start-process will invoke this program, and everytime it prints
something out (i.e. approxiamtely every LINE-NUM-UPDATE seconds), the
process-filter will get called.

Put "peep" in your PATH somewhere, then the following will maintain a
line number buffer to the left of the buffer you are editing.  The
biggest disadvantage with this method is that Emacs can't do smart
scrolling with horizontally split windows (at least not on vt100s).
This can be a pain at 1200 baud.

I'd be interested in any comments on this code.

------------LINE-NUMBERS-TAKE-2---------
;; display-line-numbers:  Show line-numbers for an Emacs buffer.
;; Copyright (C) 1989 Wayne Mesard
;;
;; This file is not officially part of GNU EMACS.  But it is being 
;; distributed under the terms of the GNU Emacs General Public License.
;; The copyright notice and this notice must be preserved in all copies.

;; Call M-x display-line-nums  to show 'em.
;;      M-x hide-line-nums     to make 'em go away.
;; Or bind these guys to keys in your .emacs file.

;; [N.B.  I haven't tested this rigorously.  It may be buggy.]
;; I will get around to these things eventually.  Other suggestions
;; are welcome.  Mail to Mesard@BBN.COM.   -wsm
;; To do:  [wsm060289]
;;     o Support for line numbers in multiple windows is not adequate.
;;       Things like this should be possible and fool proof:
;;
;;                          +---------------------+
;;                          | 1| GNU, which stands|
;;                          | 2|for Gnu's not Unix|
;;                          | 3|is the name for   |
;;                          | 4|the complete ...  |
;;                          +---------------------+
;;                          |20|I canna change the|
;;                          |21|laws o physics    |
;;                          |22|Cap'n!            |
;;                          +---------------------+
;;
;;     o  Ctrl-X 1 hides the line number window, but doesn't kill
;;        The line-num process.  It should.  (Have the filter function
;;        check for the case when the line num window isn't on screen.)
;;     o  Ctrl-X o should not go to the num buf.
;;     o  Similarly, The *Help* buffer should NOT be allowed to come
;;        up in the line number window!
;;     o  Some function documentation would be nice.


(defvar *win-min-width* 6)
(defvar *line-num-update* 1)
(defvar line-num-process nil)
(defvar *line-num-buf* nil)

(defun display-line-nums ()
  (interactive)
  (if (> window-min-width *win-min-width*)
	(setq window-min-width *win-min-width*))
    (split-window-horizontally *win-min-width*)
    (switch-to-buffer " Line-Numbers" t)
    (setq *line-num-buf* (current-buffer))
    (other-window 1)

    (if (not (and line-num-process
		  (eq (process-status line-num-process) 'run)))
	(progn
	  (setq line-num-process
		(start-process "line-nums" nil "peep"
			       (int-to-string *line-num-update*)))
	  (set-process-sentinel line-num-process 'line-num-sentinel)
	  (set-process-filter line-num-process 'update-when-scrolled)))
	  (process-kill-without-query line-num-process)
    )

  
(defun line-num-sentinel (ignore reason)
  (hide-line-nums)
  (message "The line number process died unexpectedly: %s." reason))


(defun hide-line-nums ()
  (interactive)
  (if (and line-num-process
	   (eq (process-status line-num-process) 'run))
      (progn
	(set-process-sentinel line-num-process nil)
	(delete-process line-num-process)))
  (let ((first-window (current-buffer))
	(first-time t))
    (while (or (not (eq first-window (current-buffer)))
	       first-time)
      (setq first-time nil)
      (if (eq *line-num-buf* (current-buffer))
	  (delete-window)
	(other-window 1)))
    ))



(defvar prev-top -99)

(defun update-when-scrolled (ignore ignore)
  "When window has been scrolled, do something."
  (save-excursion
      (move-to-window-line 0)
      (if (and (not (eq (current-buffer) *line-num-buf*))
	       (/= (point) prev-top))
	  (let* ((cur-line-num  (count-lines (point-min) (point)))
		 (i (+ cur-line-num (window-height))))
	    (setq prev-top (point))
	    (other-window -1)
	    (if (eq (current-buffer) *line-num-buf*)
		(progn 
		  (newline (goto-line i))
		  (while (> i cur-line-num)
		    (setq i (1- i))
		    (forward-line -1)
		    (if (looking-at "$")
			(progn
			  (if (< i 10)
			      (insert "  ")
			    (if (< i 100)
				(insert ?\040)))
			  (insert (int-to-string i))))
		    )
		  (move-to-window-line 0)
		  (scroll-up (- i (count-lines (point-min) (point))))
		  (move-to-window-line 0)
		  ))
	    (other-window 1))
	)))

------------LINE-NUMBERS-TAKE-2---------
-- 
void Wayne_Mesard();
Mesard@BBN.COM             Edith Keillor died for your sins.
BBN, Cambridge, MA

tale@its.rpi.edu (David C Lawrence) (02/07/89)

In article <35659@bbn.COM> mesard@bbn.com (Wayne Mesard) writes:

   When I saw your message, it renewed my frustration at the fact that
   there's no way to write a minor mode in GNU elisp.

Whoa!  Hang on ... that's just not so.  You don't have to redefine
entire keymaps or anything.  Whoa.
 
Heck, auto-fill can be written in Elisp.  Overwrite could too, though
it's not as nice and pretty as in C.  More to the point though, minor
modes can most certainly be written in Elisp.

--
      tale@rpitsmts.bitnet, tale%mts@rpitsgw.rpi.edu, tale@pawl.rpi.edu

gph@hpsemc.HP.COM (Old run-down actor) (02/08/89)

tale@its.rpi.edu (David C Lawrence) writes:

>Heck, auto-fill can be written in Elisp.  Overwrite could too, though
>it's not as nice and pretty as in C.  More to the point though, minor
>modes can most certainly be written in Elisp.

    Okay.  How?

    Does anyone know how I can get documentation on writing EMACS functions
in ELISP?  Anything at all on ELISP? 

    Thanks for your help!

bob@tinman.cis.ohio-state.edu (Bob Sutterfield) (02/09/89)

In article <690025@hpsemc.HP.COM> gph@hpsemc.HP.COM (Old run-down actor) writes:
   Does anyone know how I can get documentation on writing EMACS
   functions in ELISP?  Anything at all on ELISP?

Look in a.cs.uiuc.edu:pub/gnuemacs/elisp for the GNU Emacs Lisp
Manual.  Join the mailing list gnu-manual@a.cs.uiuc.edu or subscribe
to the newsgroup gnu.emacs.lisp.manual to watch the chatter.

fox@marlow.uucp (Paul Fox) (02/17/89)

In article <6831@fluke.COM> inc@tc.fluke.COM (Gary Benson) writes:
>
>What I'd *really* like on the status line is:
>
>              Line 101 of 3745 (3%)
>
Well,  if you ever get bored of emacs et al., theres always the
editor CRISP (formerly known as GRIEF) a clone of the PC
editor BRIEF - but MUCH better. Has lots of the Emacs things, and
is a LOT smaller and less memory hungry (on the Sun it is 1/4 the
size of Emacs (18.52) - ie about 120K of code).

If anyones interested I'll post a resume of it.


=====================
     //        o      All opinions are my own.
   (O)        ( )     The powers that be ...
  /    \_____( )
 o  \         |
    /\____\__/        Tel: +44 628 891313 x. 212
  _/_/   _/_/         UUCP:     fox%marlow.uucp@idec.stc.co.uk