I am writing a C++ program with Emacs CC-mode, When I write an expression that needs to wrap, how can I make the newline on the right side of the equal sign like this:
// Aligned
abc = longlonglong + longlonglong +
longlonglong;
// The actual situation
abc = longlonglong + longlonglong +
longlonglong;
With StackOverflow's hints, I tried several ways to customize the statement-cont variable, but only one method worked -- added the following code in ~/.emacs:
(c-add-style "Stroustrup"
'((c-basic-offset . 4)
(c-offsets-alist
(statement-cont . c-lineup-assignments))))
I found google-c-style.el's settings as follows:
(c-offsets-alist . ((arglist-intro google-c-lineup-expression-plus-4)
...
(statement-cont
.
(,(when (fboundp 'c-no-indent-after-java-annotations)
'c-no-indent-after-java-annotations)
,(when (fboundp 'c-lineup-assignments)
'c-lineup-assignments)
++))
...
(innamespace . 0))))
Who can tell me what this code means?
Because I only want to apply c-lineup-assignments to equations, I updated my settings reference to google-style code:
(c-add-style "Stroustrup"
'((c-basic-offset . 4)
(c-offsets-alist
(statement-cont . (when (looking-at "=")
'c-lineup-assignments
'+)))))
But when I run cc-mode the Emacs says Invalid indentation setting for symbol statement-cont: ...., so if I want only to apply the c-lineup-assignments to equations, how can I change this code ?
You're looking for c-lineup-assignments from cc-align. With your cursor on the continuation line, when you can type C-c C-o (or c-set-offset in case that key is modified) it should autofill with c-statement-cont. Hit return and set its value to c-lineup-assignments.
Related
Is it possible to configure vim and cindent to not alter indentation in c++ comments when reindenting the file (gg=G) ?
I have some formated lists in comments aligned with 4 spaces but vim interpret this as bad indent and realign everything.
For example:
/**
my list:
* item 1
* item 2
*/
becomes:
/**
my list:
* item 1
* item 2
*/
I want a way to tell vim: "Don't touch to comments content but indent everything else."
It is important because our project use doxygen with a markdown like parser to generate documentation and indentation is used by list levels.
How about writing like this so in-comment indentation is independent of comment indentation:
/**
* my list:
* * item 1
* * item 2
*/
As suggested by review, I repost an answer with answer from vi stackexchange community here:
I don't believe it's possible to achieve this with 'cinoptions'.
The correct solution is probably to write a new indentexpr that applies C-indenting (accessible via the cindent() function) only to lines that aren't within comments.
However, here's a couple of quick and dirty solutions:
I skipped first solution which I don't use and is therefore not the answer. You can still see it on the original post.
Using a Function
function! IndentIgnoringComments()
let in_comment = 0
for i in range(1, line('$'))
if !in_comment
" Check if this line starts a comment
if getline(i) =~# '^\s*/\*\*'
let in_comment = 1
else
" Indent line 'i'
execute i . "normal =="
endif
else
" Check if this line ends the comment
if getline(i) =~# '\*\/\s*$'
let in_comment = 0
endif
endif
endfor
endfunction
You can run this with :call IndentIgnoringComments() or you could set up a command or a mapping. e.g.:
nnoremap <leader>= :call IndentIgnoringComments()<CR>
I personaly defined a command which call this function and combine it with another reformating I apply often on files in this project (:%s/\s*$//g).
Thank to Rich on https://vi.stackexchange.com
Original post: https://vi.stackexchange.com/a/13962/13084
How would I go about setting up a hotkey (eg: CTRL+g) to perform a VIMGREP operation on the current visual selection in the current buffer? My intent is to show a line-numbered list in the "quickfix" window of all matching search results.
Right now, if I want to get a list of results for a regex search, I could do a command-mode query like so:
:vimgrep /foo/ %
However, there are two problems with this:
I don't want to have to type out the entire query. I could always do a visual selection, then use CTRL+r, CTRL+w, to paste the current visual selection into the command buffer, but I'd like something simpler than this.
The above approach requires that the current buffer is already saved to a file. I'd like to be able to work on a temporary buffer I've pasted into VIM rather than having to save a file buffer each time I want to do this.
Thank you.
A low-level solution
Try [I and the :ilist command:
[I " lists every occurrence of the word under the cursor
" in the current buffer (and includes)
:ilist /foo<CR> " lists every occurrence of foo in the current buffer
" (and includes)
Press : followed by a line number and <CR> to jump to that line.
You can use them on the visual selection with a simple mapping:
xnoremap <key> "vy:<C-u>ilist /<C-r>v<CR>:
You'll probably need to sanitize the register upon insertion, though.
See :help :ilist.
Another even lower-level solution
Since we are at it, let's dig even deeper and find the amazingly simple and elegant:
:g/foo/#
that you could use in the same way as :ilist above:
xnoremap <key> "vy:<C-u>g/<C-r>v/#<CR>:
Limitations
The solutions above don't use the quickfix window, obviously, but they allow you to:
see their result as a list,
use line numbers to actually get to where you want.
They have limitations, though:
the list is not cached so you must perform the search again if you want to get to a different occurrence,
the list is not transient like the quickfix list so you can't use navigation commands like :cnext or :clast to move around the result.
A higher-level solution
If those limitations are a showstopper, the function below, adapted from justinmk's answer in this /r/vim thread, gives you an almost complete solution:
press [I in normal mode to search for the word under the cursor in the whole buffer,
press ]I in normal mode to search for the word under the cursor after the current line,
press [I in visual mode to search for the selected text in the whole buffer,
press ]I in visual mode to search for the selected text after the current line.
The function below uses the quickfix list/window when the buffer is associated to a file and falls back to the regular behavior of [I and ]I otherwise. It could probably be modified to be used as part of an :Ilist command.
" Show ]I and [I results in the quickfix window.
" See :help include-search.
function! Ilist_qf(selection, start_at_cursor)
" there's a file associated with this buffer
if len(expand('%')) > 0
" we are working with visually selected text
if a:selection
" we build a clean search pattern from the visual selection
let old_reg = #v
normal! gv"vy
let search_pattern = substitute(escape(#v, '\/.*$^~[]'), '\\n', '\\n', 'g')
let #v = old_reg
" and we redirect the output of our command for later use
redir => output
silent! execute (a:start_at_cursor ? '+,$' : '') . 'ilist /' . search_pattern
redir END
" we are working with the word under the cursor
else
" we redirect the output of our command for later use
redir => output
silent! execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . "I"
redir END
endif
let lines = split(output, '\n')
" better safe than sorry
if lines[0] =~ '^Error detected'
echomsg 'Could not find "' . (a:selection ? search_pattern : expand("<cword>")) . '".'
return
endif
" we retrieve the filename
let [filename, line_info] = [lines[0], lines[1:-1]]
" we turn the :ilist output into a quickfix dictionary
let qf_entries = map(line_info, "{
\ 'filename': filename,
\ 'lnum': split(v:val)[1],
\ 'text': getline(split(v:val)[1])
\ }")
call setqflist(qf_entries)
" and we finally open the quickfix window if there's something to show
cwindow
" there's no file associated with this buffer
else
" we are working with visually selected text
if a:selection
" we build a clean search pattern from the visual selection
let old_reg = #v
normal! gv"vy
let search_pattern = substitute(escape(#v, '\/.*$^~[]'), '\\n', '\\n', 'g')
let #v = old_reg
" and we try to perform the search
try
execute (a:start_at_cursor ? '+,$' : '') . 'ilist /' . search_pattern . '<CR>:'
catch
echomsg 'Could not find "' . search_pattern . '".'
return
endtry
" we are working with the word under the cursor
else
" we try to perform the search
try
execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . "I"
catch
echomsg 'Could not find "' . expand("<cword>") . '".'
return
endtry
endif
endif
endfunction
nnoremap <silent> [I :call Ilist_qf(0, 0)<CR>
nnoremap <silent> ]I :call Ilist_qf(0, 1)<CR>
xnoremap <silent> [I :<C-u>call Ilist_qf(1, 0)<CR>
xnoremap <silent> ]I :<C-u>call Ilist_qf(1, 1)<CR>
NB: <C-r><C-w> inserts the word under the cursor, not the visual selection for which there's unfortunately no such shortcut. We have no choice but to yank.
Grepping a scratch buffer
You can use the :global command combined with :caddexpr to add entries to the current quickfix list. Here is the example from :h :caddexpr:
:g/mypattern/caddexpr expand("%") . ":" . line(".") . ":" . getline(".")
There are a few issues with this:
This approach only does one match per line
Does not start a new quickfix list
Really long to type out
Assumes the default global 'errorformat' hasn't been changed
To overcome these issues (all but the multiple matches per line) put the following command in your ~/.vimrc file:
command! -nargs=1 -bar Cgrep
\ let s:errorformat = &errorformat |
\ try |
\ let &errorformat='%f:%l:%m' |
\ cexpr [] |
\ execute 'g'.<q-args>.'caddexpr expand("%").":".line(".").":".getline(".")' |
\ cc |
\ finally |
\ let &errorformat = s:errorformat |
\ endtry
Now you can use :Cgrep/foo/ to grep the current buffer.
A visual mapping
To make it so you can do a visual version of this you need to yank in the selected text and pass it to our :Cgrep command via <c-r>. Here is an example visual mapping g/ to do just that:
xnoremap g/ y:<c-u>Cgrep/<c-r>"/<cr>
There are some issues with this mapping too:
This clobber the unnamed register, #"
This assumes the visually selected text will be a valid pattern
The following mapping fixes the mapping by using the expression register via <c-r>= and very no magic, \V:
xnoremap g/ :<c-u>let #/=#"<cr>gvy:let [#/,#"]=[#",#/]<cr>Cgrep/\V<cr>=substitute(escape(#/,'/\'),'\n','\\n','g')<cr>/<cr>
Conclusion
Personally I would forgo the mapping and get a visual star plugin (there are few out there). There is a nice Vimcast about this: Search for the selected text. I would then use that with the :Cgrep command we just created via :Cgrep// or better yet xmap g/ *:Cgrep//<cr>
For more help see:
:h :caddexpr
:h :cexpr
:h :g
:h 'efm
:h registers
:h /\V
To search for the visual selected text in files *.c via the hotkey CTRL+g do:
:vmap <silent> <unique> <c-g> y:vimgrep "<c-r>"" *.c<CR>
Two problems remain:
You want to search in a buffer, not in a file.
You want line numbers in the quickfix.
To 1:
As far as I know vimgrep can only search in files. The solution would be to write the buffer in a temporary file and search in this file and delete the temporary file when it is no longer needed. This solution requires a script which is called via the hotkey.
Just a hint: To get a suitable filename the VIM function tempname() can be used. Example:
let s:tmpfile = tempname()
(Sorry, I currently have no time to show a script solution here, maybe I add one later. Maybe somebody else has a better solution or can provide a script?)
To 2:
This command will enable line number in the current buffer:
:set number
I changed the coding style to BSD on emacs and now it look like this:
switch(a)
{
case TYPEvar:
return x(node);
}
I want to add a tab before case, like this:
switch(node->type)
{
case TYPEvar:
return walk(node);
}
What do I need change in .emacs? I tried (I don't do emacs lisp) change tab-width in:
(setq-default c-basic-offset 2
tab-width 2
indent-tabs-mode t)
But it changed nothing.
To do this only for the current buffer go to the line containing case and do C-cC-o, it will prompt you for syntactic symbol whose indentation you want to change enter/select case-label (this is selected by default). Then enter the value of indentation, enter your desired indentation.
The above sets the indentation for the current buffer. To set indentation for all the buffers you can use c-mode-common-hook as follows
(add-hook 'c-mode-common-hook (lambda ()
(add-to-list 'c-offsets-alist '(case-label . 2))))
I use the google-style file for emacs. It also looks like a good one to start learning some emacs lisp, not that long. However there is sth I am trying configure in that file, maybe some already did that before, for coding a class, I wrote,
namespace A
{
class A_A
{
public:
A_A();
private:
int a;
};
}
however public/private keywords are not at the right places, I did not understand why it places them like this out of the box, how can fix this? I am not good at emacs lisp yet unfortunately.
EDIT: I wanted to have sth like
namespace A
{
class A_A
{
public:
A_A();
private:
int a;
};
}
To get indent you like use such debug techniques:
(setq c-echo-syntactic-information-p t)
When you press TAB for indenting you will see something like:
syntax: ((inclass 33) (access-label 33))
As you can see access-label identify how indent priv/pub modifiers.
So change to what you want:
(defconst my-c-style
'(
(c-tab-always-indent . t)
(c-offsets-alist
. (
(access-label . /) ; XXXXXX LOOK HERE!!!!!!!
))
)
"My C Programming Style")
(defun my-c-mode-style-hook ()
(c-add-style "my" my-c-style t)
;; If set 'c-default-style' before 'c-add-style'
;; "Undefined style: my" error occured from 'c-get-style-variables'.
(setq c-default-style
'(
(java-mode . "my") (c-mode . "my") (csharp-mode . "my") (c++-mode . "my")
(other . "my")
))
)
(add-hook 'c-mode-common-hook 'my-c-mode-style-hook)
In example I remove half-level indent as inclass add one full indent (to get 1/2 of indent. For offset syntax read C-h v c-offsets-alist RET. For example:
If OFFSET is one of the symbols `+', `-', `++', `--', `*', or `/'
then a positive or negative multiple of `c-basic-offset' is added to
the base indentation; 1, -1, 2, -2, 0.5, and -0.5, respectively.
Probably nowadays a good solution is given by the config file provided in Github by Google.
In the repository styleguide
there is the config file google-c-style.el
that, as described in the file,
;; Provides the google C/C++ coding style. You may wish to add
;; `google-set-c-style' to your `c-mode-common-hook' after requiring this
;; file. For example:
;;
;; (add-hook 'c-mode-common-hook 'google-set-c-style)
;;
;; If you want the RETURN key to go to the next line and space over
;; to the right place, add this to your .emacs right after the load-file:
;;
;; (add-hook 'c-mode-common-hook 'google-make-newline-indent)
The file is also distributed via MELT package system as google-c-style.el.
I have a multiply nested namespace:
namespace first {namespace second {namespace third {
// emacs indents three times
// I want to intend here
} } }
so emacs indents to the third position. However I just want a single indentation.
Is it possible to accomplish this effect simply?
Use an an absolute indentation column inside namespace:
(defconst my-cc-style
'("gnu"
(c-offsets-alist . ((innamespace . [4])))))
(c-add-style "my-cc-style" my-cc-style)
Then use c-set-style to use your own style.
Note that this only works in c++-mode, c-mode doesn't know 'innamespace'.
With c++-mode in Emacs 23, I had to do like this:
(defun my-c-setup ()
(c-set-offset 'innamespace [4]))
(add-hook 'c++-mode-hook 'my-c-setup)
To disable the indentation in namespaces altogether, change [4] to 0.
OK so this seems to work in both emacs 21 and 22 at least:
(defun followed-by (cases)
(cond ((null cases) nil)
((assq (car cases)
(cdr (memq c-syntactic-element c-syntactic-context))) t)
(t (followed-by (cdr cases)))))
(c-add-style "foo"
`(( other . personalizations )
(c-offsets-alist
( more . stuff )
(innamespace
. (lambda (x)
(if (followed-by
'(innamespace namespace-close)) 0 '+))))))
(The first solution doesn't support constructs like
namespace X { namespace Y {
class A;
namespace Z {
class B;
}
}}
)
If you simply want to input a literal tab, rather than changing emacs' indentation scheme, C-q TAB should work.
Unfortunately, I don't think emacs has a separate style for a namespace inside another namespace. If you go to the inner line and do C-c, C-o, you can change the topmost-intro style, and if you run customize-variable c-offsets-alist you can edit all the different indentation options emacs has, but one doesn't exist for your specific use case. You would need to write it manually in elisp
This works for me, inherit from cc-mode and replace the name space indenting to 0, aka, disable it's indent.
(defconst my-cc-style
'("cc-mode"
(c-offsets-alist . ((innamespace . [0])))))
(c-add-style "my-cc-mode" my-cc-style)