Separate srcdir and objdir with vim and gcc - vim

When I'm working in vim, my current working directory (./) contains all my source. I build in an objdir, let's call it ./builddir/. When I build from vim, using makeprg=make\ -C\ builddir, the compiler warnings and errors all have a prefix of ../, which means vim brings the cursor to a file which doesn't exist.
If I try a different tactic, launching vim from the objdir, then I can't do commands like gf or :e myfile.h simply.
Is there a middle ground where all of this will work, like giving vim a second directory to search from if it can't find files in the current working directory? Or maybe getting gcc to use a different prefix?

The most simple solution would be to filter make outputs with sed to replace the output pathnames. (I've implemented a very similar thing to convert cygwin pathnames into windows pathnames for the win32 flavour of vim).
Something like:
:let &makeprg .= '2>&1 | sed "s#^\.\./##g"'
(It may be \| and not |, I don't remember)

Related

How to get to long directory quickly when writting code in VIM

I am writing Bash script using VIM. I need to cd to a directory and run the command tool. The command tool is deep inside the directory. How do I quickly cd to that directory instead of manually typing the directory out in VIM ? In terminal prompt, I can get to the directory quickly using tab. It does not work in VIM.
Thanks
ffl3883
You can change to the currently edited file's directory with :cd %:h; see :help filename-modifiers. Likewise, if you trigger the tool from Vim :! % can do this quickly (and repeat with :!!). Or just :set autochdir, so that the current directory within Vim always follows the currently edited file (and you can then just reference the file via ./).
When typing file paths in vim (as I often do for shell scripts), I find filename-complete invaluable. Simply type <C-X><C-F> in insert mode.
N.B. It does not work in all cases (generally vim prefers the path to be a separate WORD), but a quick edit-complete-fixup isn’t terrible.

Opening file present in another folder which has same relative path as current opened file in vim using vertical diffsplit?

Say I have following 2 similar files in 2 different workspace on same linux machine.
/user1/ws1/ip/src/ip_main.c
/user1/ws2/ip/src/ip_main.c
Now I did,
cd user1/ws1/
vim ip/src/ip_main.c
then I press ESC then executed
:cd ../ws2
which shows my pwd as "user1/ws2"
Now I want to open ip/src/ip_main.c in pwd i.e "user1/ws2"
using ESC
:vertical diffsplit "some logic to get to ws2/ip/src/ip_main.c"
note after :cd ../ws2
:pwd command show "user1/ws2" but :echo $PWD command still show "user1/ws1"
How can i do it,Can anyone help ?
Diffing both files is easily done via shell globbing, e.g. in Bash:
$ vimdiff -O /user1/ws{1,2}/ip/src/ip_main.c
Withing Vim, you have to use relative paths (i.e. prepend ../.., then go down into the other hierarchy). <C-R>% on the command-line (cp. :help c_CTRL-R) inserts the current path; this may avoid retyping much of the similar path, especially when used with the command-line window (:help c_CTRL-F).
With my EditSimilar plugin, you can use this:
:DiffSplitSubstitute 1=2

Vim quickfix double path to file with Ghc-mod

I use Ghc-mod Vim for Haskell source file check. I run it on Windows with gvim. Run :GhcModCheck it passes file for Ghc-mod utility and outputs in a quickfix error like:
G:\Haskell\G:\Haskell\huffman.hs|5 col 1 warning| The import of foldl' from module `Data.List' is redundant
As you can see, it includes path to file two times. Of course I can't jump in that location.
It looks like Ghc-mod itself doesn't output any paths at all, then it ether vim's errorformat or Ghc-mod for Vim plugin. Strangely enough, I haven't found such cases anywhere, so it maybe my _vimrc
Could anyone kindly point me out where to search for clues?
I've checked standard quickfix window after :vimgrep and it appeared allright. It left me only ghcmod-vim as main suspect. I've carefully traced all paths manipulation and have found that utils use some function, which reads a path and searches [a-z] regexp in it.
The problem was that my drive letters were uppercase, so plugin treated it like a usual filename.
I've commited a pull request to ghcmod-vim repo. Hope it'll help.
Thanks you for a concearn.

VIM - Sourcing tags from multiple locations in project

Good day,
I typically work on relatively small (less than 20,000 lines of code) projects that are all self contained within a single directory, have their own Makefile, and are fairly easy to work with.
VIM is my preferred editor, and when I open a project, I typically build the ctags list via a mapping to the F10 key:
map <F10> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .<CR>
This allows me to jump to the definition of a variable/struct/etc via moving the cursor over the text, and hitting CTRL+], as well as using code completion with a drop-down list via OmniCppComplete.
However, I am now working on a slightly larger project which makes use of LOTS of structures. Furthermore, many of these structures have arrays of other custom structures as members, so code completion is a very useful and important tool for me right now.
I have two paths that include a lot of .C files and .h files, and they may change from machine to machine. On each machine, however, we have an environment variable in our .bashrc file that points to them like so:
SDK_SRC_PLUS_HEADERS=/public/sdk
THIRD_PARTY_SDK=/private/sdk
I would like to be able to have VIM automatically refer to the contents of these additional paths when I attempt to do code completion (via VIM's built-in OmniCppComplete feature), or to jump to the files in these locations when I use CTRL+] in VIM to jump to the definition of a struct, function, variable, etc.
So, for both of the above paths, I cd into them, and generate the tags via ctags -R. Then, I modified my ~/.vimrc file to include additional tags paths, like so:
tags=./tags
tags+=$SDK_SRC_PLUS_HEADERS/tags
tags+=$THIRD_PARTY_SDK/tags
I then cd into my project at /home/user1/projects/test, start VIM, and hit F10 in VIM to index it. However, this does not work at all. In fact, it breaks my ability to even use tags just for the project itself (ie: CTRL+] now does nothing).
Does anyone have any suggestions on how I could have code completion source tags and jump-to-definitions using multiple source directories via environment variables?
Thank you all in advance for your time and assistance!
I wanted to add to the solution provided by #sehe.
This is the final set of changes I made to my .vimrc. The first lines are for adding expanded environment variable paths to my tags variable. The other is for auto-updating tags in the event that I have to update my SDK and don't want to be able to accidentally use out-of-date tags:
" CTAGS tag generation for OmniCppComplete
set tags+=./tags
exec expand("set tags+=$SDK_SRC_PLUS_HEADERS/tags")
exec expand("set tags+=$THIRD_PARTY_SDK/tags")
" Can verify taglist is correct via ":set verbose tags?" command
" Create a mapping to delete the old tags, re-generate them, and use them
map <F10> :!ctags -R --c++-kinds=+p --fields=+iaS --extra=+q . \| rm -f $SDK_SRC_PLUS_HEADERS/tags \| ctags -R -f $SDK_SRC_PLUS_HEADERS/tags $SDK_SRC_PLUS_HEADERS/tags \| rm -f $THIRD_PARTY_SDK/tags \| ctags -R -f $THIRD_PARTY_SDK/tags $THIRD_PARTY_SDK/tags \| echo "Done re-generating tags."<CR>
It indeed appears to be the problem that you can't use environment variables inside the tags setting.
I came up with this as a workaround:
:let &tags.=expand(",$SDK_SRC_PLUS_HEADERS/tags")
This might be slightly more friendly:
:exec expand("set tags+=$SDK_SRC_PLUS_HEADERS/tags")

Indenting in VIM with all the files in Folder

I have a folder containing hundreds of TTL (TeraTermLanguage) files.
Now I wanted indent all these files.
I have created teraterm.vim for indentation and I open a file using VIM and do "gg=G" and whole file gets indented properly.
But is there any way, where I can indent all the files in folder.
I wanted to do with help of Shell. But in VIM I couldnt pass file indent command as the argument to VIM.
Please suggest which is the best way I can do indentation to all the files in VIM.
Much simpler than scripting vim from the bash command line is to use vimscript from inside of vim (or perhaps a much simpler one-liner for scripting vim from the command line). I personally prefer using the arg list for all multi-file manipulation. For example:
:args ~/src/myproject/**/*.ttl | argdo execute "normal gg=G" | update
args sets the arglist, using wildcards (** will match the current directory as well as subdirectories)
| lets us run multiple commands on one line
argdo runs the following commands on each arg (it will swallow up the second |)
execute prevents normal from swallowing up the next pipe.
normal runs the following normal mode commands (what you were working with in the first place)
update is like :w, but only saves when the buffer is modified.
This :args ... | argdo ... | update pattern is very useful for any sort of project wide file manipulation (e.g. search and replace via %s/foo/bar/ge or setting uniform fileformat or fileencoding).
(other people prefer a similar pattern using the buffer list and :bufdo, but with the arg list I don't need to worry about closing current buffers or opening up new vim session.)
Open up a terminal. Type:
$ vim -w indentme.scr foo.c
Then, type this exactly (in command mode):
gg=G:wq
This will close vim, saving the process of indenting all lines in the file to a Vim script called indentme.scr.
Note: indentme.scr will contain a record of all key commands typed, so when you are done indenting the file, don't spend a lot of time using the arrow keys to look around the file, because this will lead to a much larger script and will severely slow down batch operations.
Now, in order to indent all the lines in a file, just type the following command:
$ vim -s indentme.scr unindented-file.c
Vim will flash open-shut (if you're on a fast computer and not editing a huge file), indenting all lines, then saving the file in-place.
Unfortunately, this will only work on one file at a time, but you can scale the functionality easily using sh's for loop:
for filename in *.ttl ; do
vim -s indentme.scr "$filename"
done
Note: This will save-over any file. Unless set bk is in your ~/.vimrc, don't expect a backup to be saved.
I went off of amphetamachine's solution. However, I needed to recursively search through multiple directories. Here's the solution that I used:
$ find . -type f -name '*.ttl' -exec vim -s indentme.scr "{}" \;
Taking reference from the above answers I would like to make this complete.
I will start from the scratch so that a beginner can understand.
Step-1
Install astyle (tool used for formatting ) by using the following command
Open up a terminal. Type:
sudo apt-get install astyle
Step-2 Make sure you have vim installed on your system.Run the below commands from the directory in which your code files are.The below command will create a script that we intend to run recursively so as to beautify each and every file in our directory.(as mentioned in the above answer)
vim -w indentme.scr foo.c
Step-3 Then, type this exactly (in command mode) and press enter
:%!astyle
Step-4Then type this exactly (in command mode) and press enter
:wq
Step-5 Last run this recursively by the following command:
find . -type f -name '*.cpp' -exec vim -s indentme.scr "{}" \;
All your cpp files will be formatted properly.

Resources