Truncation in Emacs Powerline (mode line) - emacs

Is there a way to get some elements truncated in the (excellent) Emacs Powerline? I'm thinking, in particular, at the which-func-mode section in the default mode line. It'd be good to see only the first N characters of a function name or section name (when in Org mode), N to be defined.
A side question is: can we simply get components being disabled (that is, not displayed) if the frame is too narrow (80 chars wide, for example)?

Generally you can customize which-func-format accordingly, e.g.:
(setq which-func-format
`("["
(:propertize (:eval (my-which-func-current))
local-map ,which-func-keymap
face which-func
mouse-face mode-line-highlight
help-echo "mouse-1: go to beginning\n\
mouse-2: toggle rest visibility\n\
mouse-3: go to end")
"]")
)
Where my-which-func-current is a function that truncates the current function name accordingly:
(defun my-which-func-current ()
(let ((current (gethash (selected-window) which-func-table)))
(if current
(truncate-string-to-width current 20 nil nil "…")
which-func-unknown)))
This approach works with the standard mode line, and with any mode line extension package that supports standard mode line data. I know that Smart Mode Line does, but I am not sure of Powerline. I don't use either of these packages.

Related

Emacs: contextual margin settings or filling text to narrow range of columns?

I'd like to quickly generate text in a buffer that looks like this:
(fact "This is some text which will hang out
only on this part of the screen, ideally
automatically flowing to the correct
margins as I type."
(+ 1 1) => 2
;; more Clojure tests...
)
I have an Elisp keybinding which quickly spits out a starting template and puts my cursor in the right place:
(global-set-key "\C-of" (lambda ()
(interactive)
(insert "(fact \"\"\n\n )")
(backward-char 6)))
Now, when I am typing in the string portion ("This is some text..."), it'd be awesome if I could get Emacs to automatically flow text to the "correct" margins. Is there some way Emacs can be made to adjust margins and wraparound behavior based on where you're typing? At least, the first time you are typing there?
Barring that, for a given selection of text, how can I do the equivalent of fill-region, but with the desired left and right margins? Currently fill-region deletes all space between fact and "This is...., and left-justifies the rest.
There might be a simpler way that I'm overlooking now, but I would just do this:
Configure the text block in a temporary buffer, by doing this there:
a. Set fill-column to the width of the text block that you want.
b. Put the text at the beginning of the line, i.e., not indented.
c. Fill the text.
d. Use indent-rigidly to indent the text to the column you want, except for the first line.
Insert into your target buffer (fact followed by the indentation you want for the first line of the text block. Then insert the contents of the temporary buffer. Then insert whatever other text/code you need.
IOW, I would separate filling the text block from indenting it.
The following seems to work for the moment for my alternative (weaker) case:
;; Set up Midje fact with mark inserted at beginning of comment text
;; (refill as needed in appropriate columns, using C-oF).
(global-set-key "\C-of" (lambda ()
(interactive)
(insert "(fact \"\"\n\n )")
(backward-char 6)
(set-mark (point))))
;; Perform the refill operation to properly reformat the text string
;; in a Midje fact, started with C-of:
(global-set-key "\C-oF" (lambda ()
(interactive)
(set-left-margin (mark) (point) 37)
(fill-region (mark) (point))))
I expect I'll have to tweak this as I get experience using it, but it is pretty close. Still, it'd be nice to figure out how to have this happen automatically, while I'm typing inside the string.

Emacs: line numbers that respect line-wrapping

Modes: I'm using linum for line numbers, the package linum-relative for relative line numbers. If it matters, I am also using visual-line-mode. These are flexible.
Currently, a single line (i.e. text without a newline) is numbered as only one line, regardless of how many times it is wrapped. I am wondering if there is a way to change the numbering to respect these wraps. So, for example,
263 This is all in
a single line
without newlines
might become:
263 This is all in
264 a single line
265 without newlines
and, in relative mode:
0 This is all in
a single line
without newlines
might become:
-1 This is all in
0 a single line
1 without newlines
I really only want the change in relative mode, but would not mind if it spills over into absolute mode.
A toggled change that works on both would be most useful - that way, the user can specifically select when, or with which modes, to turn it off or on.
If the goal is navigation, I suggest a similar solution via the popular ace-jump-mode.
If the goal is just persistent line numbering, you might consider longlines-mode instead of visual-line-mode (but I would avoid this, personally).
ace-jump # GitHub
https://github.com/winterTTr/ace-jump-mode
Demo:
http://dl.dropboxusercontent.com/u/3254819/AceJumpModeDemo/AceJumpDemo.htm
With it, you can jump to any line with as little as two keypresses.
In addition to lines, you can jump to the start of any word; there's also individual character-level jump precision. If desired, it can be configured to restrict jumps to the current window/buffer, or across all windows in the current frame, and even multi-frames.
It doesn't, however, recognize wrapped lines as jump-able locations. Again, you might consider longlines-mode as a fix for this if it is really important to you, but as I understand, it's considered hack'ish and deprecated in favor of visual-line-mode. Though, with longlines-mode, the lines are renumbered exactly as you want in your first example.
I'm assuming the goal is navigation, and as such, I think you'll find with just a little practice that word-based jumping or even jumping via incremental search to be a superior solution.
Update
Here's a simple solution to trick ace-jump to scan within N lines using emacs narrowing features; perhaps others can improve upon it. You could also do something similar for word and line modes.
(defun brian-ace-jump-to-char-within-N-lines (&optional n)
(interactive "p")
(let* ((N (or n 0))
(query-char (read-char "Query Char:"))
(start (save-excursion
(forward-line (- N))
(point)))
(stop (save-excursion
(forward-line (1+ N))
(point))))
(unwind-protect
(condition-case err
(progn
(narrow-to-region start stop)
(ace-jump-char-mode query-char))
(error
(message (error-message-string err))))
(widen))))

How can I put DISPLAY name in frame-title of GNU EMACS

I use GNU EMACS on multiple monitors from a Windoze PC via VNC.
(Currently 5 - 4 big, 1 the small monitor on my tablet PC. Two vertical 1200x1920, two horizontal 1920x1200, plus the small.)
The way I am currently doing this is to run a separate VNC on each monitor. I then open a single emacs, and use make-frame-other-display to open emacs' frames in the other VNC window.
To make things more complicated - I run the VNCs on an up-to-date Ubuntu system, but I run the emacs on a quite out of date machine where the rest of the build tools live. I.e. the VNC displays are not local to the same machine as emacs.
Rather than xhost+, I open an xterm in each of the VNCs, and ssh to the machine running emacs. This creates DISPLAYS of the form localhost:16.0. I then use make-frame-on-display using these localhost DISPLAYs.
This gets confusing.
It helps if I leave an "echo $DISPLAY" in the xterm windows. Or chamnge the xterm's title.
I'd like to similarly change the EMACS' frames' titles, to reflect what each frame things is its current DISPLAY. But doing
(defvar frame-title-specific-ag "emacs"
"title element from frame-title-format that is specific to a particular emacs instance; andy glew")
(setq frame-title-format
(list
"frame=%F "
(format "%s" frame-title-specific-ag)
" " 'system-name
" DISPLAY="
(getenv "DISPLAY")
" %b"
" " (format "pid:%d" (emacs-pid))
" user:"(user-login-name))
)
only gets the DISPLAY variable for the entire emacs.
Q: is there a way to find out the display associated with any particular frame?
To get the display name for the current frame, use
(frame-parameter nil 'display)
or replace nil with a specific frame to get the name of its display instead of the current one. For example, use this to show the display in the title:
(setq frame-title-format
'("DISPLAY=" (:eval (frame-parameter nil 'display))))
Note that it is important that this form is completely quoted, so the list that is used has an :eval which tells Emacs to run the code whenever it renders a frame title. Without that, you might be tempted to write something like:
(setq frame-title-format
(list "DISPLAY=" (frame-parameter nil 'display)))
but this doesn't work. The problem is that the function call happens immediately when this form is evaluated, and the result is a list holding a particular string, which is the name of whatever frame was in effect this evaluation happened, and the string will not change magically.
Eli Barzilay pointed us to
(frame-parameter nil 'display)
which is 90% of the way there.
The following puts the display associated with the currently selected frame in its frame title.
(setq frame-title-format
'(
"DISPLAY="
(:eval (frame-parameter nil 'display))
)
)
Glew: This puts the display of the currently selected frame, at the time the frame is created
(e.g. via make-frame-on-display) in the
title. Since this may be a different frame, in a completely different
display, it is not always what is wanted.
The unquoted, un-:eval'ed, form, puts the display of the currently selected frame,
at the time the setq is evaluated, in the title. This is even less of what is wanted.
Here is what I ended up with:
I set the default frame-title-format as above. But I do bnot really use it because I
hook the following:
(defun ag-set-frame-title (frame)
"set frame-title to glew preference, optional arg FRAME / default nil (currently selected frame)"
(interactive)
;; TBD: make-variable-frame-local is deprecated in more recent versions of emacs
;; than the antiquated version at my work. use modify-frame-parameters instead
(let (x)
(setq x
(concat
(or frame-title-specific-ag "emacs")
" " system-name
" DISPLAY=" (frame-parameter frame 'display)
" " (format "pid:%d" (emacs-pid))
" user:" (user-login-name)
;;" " (buffer-name)
)
)
(modify-frame-parameters frame (list (cons 'title x)))
)
)
;; TBD: this old emacs does not have modern hooks
(setq after-make-frame-functions '(ag-set-frame-title))
For good measure:
(defun ag-fix-frame-titles ()
"run ag-set-frame-title on frame-lits"
(interactive)
(mapc 'ag-set-frame-title (frame-list))
)
(ag-fix-frame-titles)
NOTE: per comment string it is possible that the fix described here is only needed on an old version of emacs, such as 21.4.1. #EliBarzilay says not needed on whatever version of emacs he is using.
Subtract points all you want, folks. Truth.

How to make emacs behave closer to the regular editors?

I'm using Emacs 23.1.1 on Ubuntu with Emacs starter kit. I primarily work in the lua-mode.
Is there a way to stop Emacs being so smart about indentation? I'm used to the dumb editors, and press all the required keys manually.
I want to use two spaces per indent, tabs-to-spaces.
When I press RETURN, the new line indentation must match the previous line.
When I press TAB on the leading whitespace, the line contents must be indented by one indentation unit.
When I press TAB on the beginning of empty line, the cursor must move one indentation unit to the right.
Oh, and I'd like to get soft word wrap on 80th column and trim-trailing-spaces on save as well.
Update:
(Would put this in a comment, but it needs formatting)
If I use Thomas's solution, auto-indent on RETURN is "fixed", but TAB still indents weirdly:
local run = function(...)
x
"x" marks the spot where cursor appears after I type the first line and hit RETURN, TAB.
Emacs has a concept of modes, which means that depending on what type of file you're editing it provides special functionality that is useful for that file. Every buffer has one major mode associated and optionally a number of minor modes.
Indentation is one of the things that is typically mode-dependent. That is, you may have to configure indentation separately for every major-mode, because otherwise when you load a new file, its associated major mode may override your indentation settings. It's possible though to write a function that configures indentation and set up Emacs in a way that the function is invoked whenever a new major-mode is started.
In order to realize the settings you want, you'll need to run a few lines of elisp code. (Unfortunately your description of what should happen when you hit TAB leaves out some details, I've implemented the simplest version I could think of below -- if it's not what you want, that can be changed, of course.)
Put the following code in the file named .emacs in your home directory (~):
(setq-default indent-tabs-mode nil) ; use spaces for indentation
(defvar my-indentation-width 2
"The number of spaces I prefer for line indentation.")
(defun my-enter ()
"Inserts a newline character then indents the new line just
like the previous line"
(interactive)
(newline)
(indent-relative-maybe))
(defun my-indent ()
"When point is on leading white-space of a non-empty line, the
line is indented `my-indentation-width' spaces. If point is at
the beginning of an empty line, inserts `my-indentation-width'
spaces."
(interactive)
(insert (make-string my-indentation-width ? )))
(defun my-indentation-setup ()
"Binds RETURN to the function `my-enter' and TAB to call
`my-indent'"
(local-set-key "\r" 'my-enter)
(setq indent-line-function 'my-indent))
(defun delete-trailing-whitespace-and-blank-lines ()
"Deletes all whitespace at the end of a buffer (or, rather, a
buffer's accessible portion, see `Narrowing'), including blank
lines."
(interactive)
(let ((point (point)))
(delete-trailing-whitespace)
(goto-char (point-max))
(delete-blank-lines)
(goto-char (min point (point-max)))))
;; make sure trailing whitespace is removed every time a buffer is saved.
(add-hook 'before-save-hook 'delete-trailing-whitespace-and-blank-lines)
;; globally install my indentation setup
(global-set-key "\r" 'my-enter)
(setq indent-line-function 'my-indent)
;; also override key setting of major-modes, if any
(add-hook 'after-change-major-mode-hook 'my-indentation-setup)
This works for me in Emacs 23, although I may have missed some edge cases. However, these changes are so fundamental that I predict you will run into incompatibilities sooner or later with some major-modes that expect indentation to work they set it up. If you really want to get into Emacs it's worthwhile adapting the habits you inherited from other editors to the way Emacs does things.
For soft word-wrap there is a minor-mode called "longlines" which you can download from here: http://www.emacswiki.org/cgi-bin/emacs/download/longlines.el I haven't used it so I can't tell you how well it works.
Fixing TAB and RETURN:
(global-set-key "\t" 'self-insert-command)
(global-set-key "\r" 'newline-and-indent)
Fill column (haven't tried): say ESC x customize-var, enter fill-column, set to 80.

Emacs C-mode indent problem with Doxygen style comment

I am having a problem with doxygen style multi-line comments with emacs indent feature in c-mode. According to doxygen manual (http://www.doxygen.nl/manual/docblocks.html) the form below is accepted.
/********************************************//**
* ... text
***********************************************/
I am trying to use this format in emacs but when I tab in on the line '* ... text' the * ends up below the /** at the end of the first line like so:
/********************************************//**
* ... text
***********************************************/
Any suggestions on how to fix this? Still learning all the in-and-outs of emacs.
The reason it is indenting as such is that (by default) multi-line comments are lined up with the start of the comment on the previous line. In this case, the start of the containing comment is in column 47.
Now, how to fix it. Here's how I figured out how to fix it, the solution is at the end.
First, there's the cc-mode manual, specifically the section on customizing indentation. A useful key is C-c C-s which tells you which syntax is being used for indentation. In this case it is ((c 61)) - the c is the important part for now.
To customize it interactively, you can type C-c C-o (when the point is on the line whose indentation you want to fix). You'll be prompted for which syntax entry you want to customize (defaults to c in this case b/c that's the current syntax), then you'll be prompted for what you want to change the syntax entry to (default is c-lineup-C-comments).
Now we can look at that function to see how we might customize it to meet your needs. M-x find-function c-lineup-C-comments.
That's where it gets more difficult. You can customize the way cc-mode handles comment indentation, but what it looks like you want it to do (in this case) is to recognize that the c-comment you're in is immediately preceded by another c-comment, and that comment is the one you want to align indentation to.
How do you do that? The easiest way I can think of is to advise 'c-lineup-C-comments to recognize this special case and change the value of its first argument to be what you want. My limited testing shows this works for your example:
(defadvice c-lineup-C-comments (before c-lineup-C-comments-handle-doxygen activate)
(let ((langelm (ad-get-arg 0)))
(save-excursion
(save-match-data
(goto-char (1+ (c-langelem-pos langelem)))
(if (progn
(beginning-of-line)
;; only when the langelm is of form (c . something)
;; and we're at a doxygen comment line
(and (eq 'c (car langelm))
(looking-at "^\\(\\s-*\\)/\\*+//\\*\\*$")))
;; set the goal position to what we want
(ad-set-arg 0 (cons 'c (match-end 1))))))))
The end result of this advice should be that the argument passed into c-lineup-C-comments should be transformed from (c . 61) to (c . 17) (or something like that), essentially fooling the routine into lining up with the comment at the beginning of the line, and not the comment which you're currently modifying.
Which version of emacs are you using? My emacs 22 has this problem, but on another machine with emacs 23 does not. This is probalby due to some "electric" indentation. Try M-x describe-key RET RET and also M-x describe-mode to get a nice place to start searching for clues. There is also http://doxymacs.sourceforge.net/ but I have not tesed it personally.