How to assign a string ending in <CR> to a vimscript variable without it adding a <LF>? - macros

I have been playing around with vim macros lately (in MacVim at the moment), and sometimes I like to explicitly assign a macro into a register using e.g. :let #a='(macro keystrokes)'. This is generally working fine, but I found a weird behavior in which anytime I assign a string value that ends in Carriage Return / ^M, vim automatically adds a Linefeed / ^J to the end before putting it in the register, which affects the execution of the macro!
Example: Let's say I record a simple macro that gets into insert mode, types "hey", escapes out of insert mode, and then hits Enter twice to go down 2 lines. I record this into register #a by typing qaihey<Escape><Enter><Enter>q, which stores the following in #a:
ihey^[^M^M
So far so good, and executing the macro by typing #a does just what it's supposed to. Another perfectly ok way I can get this same macro into register #a would be by typing the whole thing (ihey<Ctrl-V><Escape><Ctrl-V><Enter><Ctrl-V><Enter>) into a buffer and then yanking it with "ay -- the end result is just the same. But here's the weird thing -- suppose I just wanted to assign that string directly into #a using a let statement:
:let #a='ihey^[^M^M'
Now if I type :reg to look at the value it says there's an extra ^J on the end for some reason:
"8 ...
"9 ...
"a ihey^[^M^M^J
"b ...
Having the extra ^J causes it to go down an extra line when I execute the macro, so it's actually changing the behavior.
Anybody know why this extra character is being added? Anyone know how I can get a string value ending with ^M into a register (or any variable), without having an extra ^J get added?

Some quick checking the vim help files says this:
:let #{reg-name} = {expr1} *:let-register* *:let-#*
...
If the result of {expr1} ends in a <CR> or <NL>, the
register will be linewise, otherwise it will be set to
characterwise.
In other words, ending the string with a carriage return will make Vim interpret it as a line ending
Quick googling give this from the VimTips wiki:
Note however, that the above method using :let will not work as expected for any macros which you make ending in a < CR > or < NL > character (carriage return or newline). This is because, as documented in :help :let-#, Vim will treat the register as "linewise" under these conditions. The reason for this is to make registers set with :let act "the right way" when dealing with yanked/deleted text, but it can cause headaches when dealing with recorded macros. Possible workarounds include using the setreg() function or adding "no-op" commands to the end of the macro, such as a < ESC >. See the discussion on vim_dev about unexpected behavior of the :let command for details.
So you have a few options: use setreg() or add some kind of no-op sequence (< ESC >) to the string when you use let.

In order to insert special keys easily using let, just use double quotes:
:let #a="ihey\<Esc>\<Return>\<Return>"
If you use single quotes vim will insert:
\<Esc>\<Return>\<Return> instead of their functions

Related

Emacs semicolon presses indent to width of entire previous line, declaring private class variables. How to fix & stop? (c-electric-semi&comma?)

Everything is indented normally in my .cpp file until the moment I press the semicolon ; on the following lines --- at which point emacs indents all the way to the full length of the last line typed...
This oddly doesn't happen if I remove the access modifier and declare vars int x and int y for any class or struct..
class Blah {
private int x;
private int y;
private int z;
};
If I highlight the whole field and press < TAB >, Emacs views this as the proper indent for the region. Can't seem to find anything else related on this besides other qs on indent customization
Additional details:
C-h k ; yields this description, so it might have to do with this feature ---- though I don't understand because the indentation described appears to refer to the immediate next newline not the current the cursor is on.
; runs the command c-electric-semi&comma (found in c++-mode-map),
which is an interactive compiled Lisp function in ‘cc-cmds.el’.
It is bound to ,, ;.
(c-electric-semi&comma ARG)
Insert a comma or semicolon.
If ‘c-electric-flag’ is non-nil, point isn’t inside a literal and a
numeric ARG hasn’t been supplied, the command performs several electric
actions:
(a) When the auto-newline feature is turned on (indicated by "/la" on
the mode line) a newline might be inserted. See the variable
‘c-hanging-semi&comma-criteria’ for how newline insertion is determined.
(b) Any auto-newlines are indented. The original line is also
reindented unless ‘c-syntactic-indentation’ is nil.
(c) If auto-newline is turned on, a comma following a brace list or a
semicolon following a defun might be cleaned up, depending on the
settings of ‘c-cleanup-list’.
; is one of many keys that triggers the "correct this line's indentation" command. There's nothing special about ; here, it's just that Emacs normally keeps your indentation right according to the style defined for the file.
As 0x5453 says in a comment, your C++ file is syntactically invalid, and the indenter is trying its best to come up with a reasonable indentation for this incorrect file. If you fix your code to be legal, the indentation will also be resolved.

Emacs: abbrev-mode not expanding simple abbrev, possible causes?

I would like to assign the string 'target="_blank"' to the abbreviation 'tgt' as I use this a lot and it's annoying to have to type out each time.
The string above probably needs escapes and so on, so as a simpler starting point I have tried to assign 'target' to 'tgt'. Despite switching on abbrev-mode and defining this as a global abbrev, if I type 'tgt' and hit space, nothing happens. If I do M-x list-abbrevs I get this:
(global-abbrev-table)
"target" 1 "tgt"
So it seems to be recorded. I would have expected tgt to be expanded to target when I hit a space after tgt, but that doesn't happen. What am I missing? Have I completely misunderstood the nature of abbrevs? I have looked at the Emacs wiki page but like many Emacs pages it gives a number of complex solutions and annoyingly sparse coverage of the basics.
EDIT: embarassingly enough this looks like it was a combination of the wrong abbrev file and an assignment that was reversed, so that typing 'target' produced 'tgt'. I now have 'tgt' producing 'target="_blank"' as desired. Apologies everybody.
However, I now have a related question. This abbreviation expands when I hit space and typically I do not want a space after the 'target="_blank"' string. Is there a way to automatically remove the space?
You have to define the abbrev the other way around. The way you did it will expand "target" into "tgt".
To do the right thing, first type into a buffer what you want the abbrev to expand into. In your case that would be "target". Then, with the point right after the word, type C-x a g. This will prompt you for an abbrev for which you would type "tgt".
Et voilà: if abbrev-mode is turned on, typing tgt will now expand into "target".
There are other ways to define an abbrev, e.g. via M-x define-global-abbrev, thus it's best to check out the documentation.
The problem with removing the space after the abbrev is that Emacs will insert it after the abbrev has been expanded. So hitting space will basically two things: trigger the expansion of the abbrev and then run the normal self-insert command.
One simple way to avoid this is to type C-x ' or C-x a e to explicitly expand an abbrev rather then turning on abbrev-mode. Except, that's a bit annoying. If we look at the documentation again, however, we find:
Function: define-abbrev table name expansion &optional hook count
[...]
If hook is a non-nil symbol whose no-self-insert property is
non-nil, hook can explicitly control whether to insert the
self-inserting input character that triggered the expansion. If hook
returns non-nil in this case, that inhibits insertion of the
character. By contrast, if hook returns nil, expand-abbrev also
returns nil, as if expansion had not really occurred.
This means that if you put the following lines in, say, your ".emacs" file:
(defun my-after-abbrev-expand ()
(when (looking-back "\"\"\\|''\\|()\\|\\[\\]\\|{}")
(backward-char 1))
t)
(put 'my-after-abbrev-expand 'no-self-insert t)
then you can define an abbrev like so:
(define-abbrev global-abbrev-table "tgt" "target=\"\"" 'my-after-abbrev-expand)
to avoid the insertion of the space character. Also, the my-after-abbrev-expand function will move the point one position to the left if the expansion ends in two double quotes, two single quotes, or a pair of round, square or curly braces.

Retaining tab-to-tab-stop with Emacs replace-regexp

I have a very large text file with nearly 20 columns. Unfortunately the program which produced the file did not properly handle columns which began with a -10 (it only properly spaced data which had a total of 5 characters, not 6). Essentially I ended up with something that looks like this:
-10.072-10.179-10.2190.002
I want it to look like:
-10.072 -10.179 -10.219 0.002
and was almost able to do so with:
M-x replace-regexp RET -10\.... RET \&TAB RET
When I use TAB however, it only replaces with a space rather than tab- ideally a tab-to-tab-stop. If I manually go to one of these situations in the file and type TAB it properly does a tab-to-tab-stop to align the data with the proper column. How do I retain the tab-to-stop function within the replace-regexp?
The search and replace certainly ought to be inserting a tab. The apparent size of a tab can vary, of course, which is the only reason I can think of for it appearing to be a space. You could use whitespace-mode to make the difference more obvious.
As for tab-to-tab-stop, that's a dynamic function rather than a special kind of tab character, so you can't do that with a search and replace1. I would suggest using a keyboard macro instead, to get the same dynamic behaviour as manual typing.
F3
M-C-s -10.... RET
M-x tab-to-tab-stop RET
F4
or perhaps just: F3M-C-s -10.... RETTABF4
Then you can run the macro until it fails with C-0F4
(If you only want to run it on a portion of the buffer, you can simply narrow to the relevant region first.)
1 Not strictly true, as Emacs lets you evaluate arbitrary elisp as part of a replacement pattern; but it's not just a case of calling the tab-to-tab-stop function, so the macro is really much simpler.

How can I modify emacs' Search and Replace to perform a more complicated task?

total Emacs noob here. So right now I'm working on a fairly big LaTeX project in Emacs in which there are couple of places where I need to index some words, using the makeidx package. Because I also wanted indexed words to be bold, I created my own command \ind{} which would make the argument go bold and indexed. But right now I'm dissatisifed with this command so I'd like to change every instance of \ind{whatever} in my text by \textbf{whatever}\index{whatever by default}.
The thing is I know exactly what I want :
Go through the text, look for any instance of \ind{ and replace by \textbf{ using search-and-replace
Save the argument of \ind ("whatever" in this case) in memory
Ask me the user what should the argument of \index be. By default (by striking enter), it should be the first argument, but I can also change my mind and enter something different ("whatever by default" in this case). If there's no input (only a space " " for example) stop the program.
Write down \index{, the new argument and }.
Go to next occurance in the text.
But, alas!, I know not how to achieve this, so I need someone's help. If it should take too much time to explain how to do such a thing, would you please send me some tutorial about writing my own functions?
I hope I'm being clear, and thanks for your patience!
This approach seems vaguely unorthodox to me, but it works and seems sufficient for a one-off job...
In the replacement text for replace-regexp and query-replace-regexp (C-M-%), one newer escape sequence is \,(...), where ... can be any Lisp expression. There's a Lisp function read-from-minibuffer which reads arbitrary text typed by the user, with an optional default. Therefore:
C-M-%: Start query-replace-regexp.
\\ind{\([^}]+?\)}: The pattern to search for.
\\textbf{\1}\\index{\,(read-from-minibuffer "index content? " \1)}: The replacement text. The user will be prompted for the text to put in the braces following the \index{} element, using the original text between the braces following the \ind{} element as a default.
Note that when using query-replace-regexp, you'll have to confirm each choice by typing y after each. Use M-x replace-regexp if you want to avoid this step.
Vlad give you the LaTeX answer to your problem. An Emacs solution is the key-macro: start with
C-x (
to define a new macro, then do one step of your change, say:
C-s \ind{
<left>ex
Then copy and paste the argument in the \textbf macro... You have to be careful to move in a way that will be repeatable. Once the standard modification is done, you let the cursor after the whatever by default and end the definition by
C-x )
now C-x e will call the macro you just define, letting your cursor at the correct place to change the part you want to change You can also repeat the e to call the macro several time at once.
Why not just redefine the \ind so that it can get an optional argument?
For example:
\newcommand{\ind}[2][]{%
\def\first{#1}%
\ifx\first\empty
\textbf{#2}\index{#2}%
\else
\textbf{#2}\index{#1}%
\fi
}
This way you can use \ind{whatever} or \ind[whatever-else]{whatever}.

gnu screen - changing the default escape command key to ALT-X?

In GNU screen, I want to change the default command binding to Alt-s (by tweaking .screenrc) instead of the default C-a, the reason is I use emacs hence GNU screen binds the C-a key, sending "C-a" to the emacs becomes tedious (as #Nils said, to send "C-a" I should type "C-a a"), as well as "C-a" in bash shell, and I could change the escape to C- but some of them are already mapped in emacs and other combinations are not as easy as ALT-s . If anyone has already done a ALT key mapping, please do let me know.
It is possible to work around :escape command limitations using registers and :bindkey command. Just put this in .screenrc:
# reset escape key to the default
escape ^Aa
# auxiliary register
register S ^A
# Alt + x produces ^A and acts as an escape key
bindkey "^[x" process S
## Alt + space produces ^A and acts as an escape key
# bindkey "^[ " process S
See http://adb.cba.pl/gnu-screen-tips-page-my.html#howto-alt-key-as-escape
From my reading of man screen it seems like the only meta character that screen can use for the command binding is CTRL:
escape xy
Set the command character to x and the character generating a literal
command character (by triggering the "meta" command) to y (similar to
the -e option). Each argument is either a single character, a two-character
sequence of the form "^x" (meaning "C-x"), a backslash followed by an octal
number (specifying the ASCII code of the character), or a backslash followed
by a second character, such as "\^" or "\\". The default is "^Aa".
If there is some mapping that you don't use in emacs, even if it's inconvenient, like C-|, then you could use your terminal input manager to remap ALT-X to that, letting you use the ALT binding instead. That would be a little hackish though.
I'm an Emacs and screen user as well. Although I rarely use Emacs in a terminal -- and as such in a screen session -- I didn't want to give up C-a for the shell either (which uses Emacs key bindings). My solution was to use C-j as the prefix key for screen, which I was willing to sacrifice. In Emacs programming modes it is bound to (newline-and-indent) which I bound to RET as well, so I really don't miss it.
By the way: I know this is an advise rather than an answer, but I felt this would be valuable enough to post nevertheless.
To make Alt+X the default prefix for commands and free C-a, add the following lines to .screenrc:
escape ^||
bindkey "^[x" command
As a side effect C-| will be command prefix too. If you need this keys to be free too, then fix "escape ^||" accordingly.
Screen doesn't have any shorthand syntax for alt bindings, but you can give it the octal code directly. For instance on my machine, Alt-x has the hex code F8, or 370 octal, so putting
escape \370x
in my screenrc changed the escape code to alt-X
Tested and works with screen 4.00.03 on Linux.
You may have to change the escape, since I think this may depend on things like your language and codeset, etc: how I found out what my escape code was was to type
$ echo -n ^QM-x | perl -ne 'printf "%lo\n", ord($_)'
^Q is the quoted-insert command for readline (it inserts what you type directly without trying to interpret it) and M-x was a literal Alt-X.
Fellow emacs user here.
The best solution I've found is a ~/.screenrc file with the following:
# C-a :source .screenrc
escape ^gg
Live updated here: https://gist.github.com/1058111
See also: http://ubuntuforums.org/showthread.php?t=498675
Something I have had for years in my .screenrc:
escape ^Zz
which is now hardwired in muscle memory for me.
Somehow I ended up having to share a screen with someone else's config, and now I keep stopping processes all the time (bash ^Z)... Not funny...