Bash - expected file extension on tab - linux

I'm not sure if this is something that can be done in the Linux/Unix terminal, so I thought I'd ask.
For certain programs (unfortunately I can't think of any besides bibtex off the top of my head, which on tab auto-'extends' the .aux extension) when I'm finished typing out the file name (minus dot and extension) in front of it, I've noticed that if I hit tab it will 'auto-complete' the dot + file extension.
Is this something you can actually control somehow ? For example, if I wrote a bash script (we'll call it compile.sh) that only worked with *.tex files, I could do the following:
$ ./compile.sh nameOfProgram -- tab and autocomplete .tex extension --
Certainly it's not inherent to the bash script itself, but by some other means that recognizes I'm using said executable.
Sometimes, as is often the case while using LaTeX, there are multiple files with the same base name but different extensions in the same directory - I would like it to only accept that which has the predefined extension.

It is certainly possible to define a custom completion function for compile.sh which only matches *.tex files. Writing a good completion function is a broad task, but you can do something very simple with
# Add to your .bashrc file to enable in every shell, not just
# the current shell
complete -G '*.tex' compile.sh
which will only treat files matching *.tex as valid completions for any argument to compile.sh.

Related

In Vim how to know if function is defined

I am using Vim editor v7.4 .
I have a huge C Code library , and i make constant changes to it.
Is there a way ( before compilation) to know if a function i am adding to some file is defined for this file.
Thanks
I'm not sure to correctly understand your need. In my definition, when I add a function to a file, I add its definition, so it's defined. But when I'm using a function in a file, I only need its declaration. Then there is also the problem of being sure that a function defined in a translation unit is declared somewhere (privately in the same TU as a static function, or in a header file).
For the latter, I have a solution (that checks functions definitions and declarations are balanced in lh-cpp). For the case of being sure a function is declared in the UT it's used, it won't be that simple: we need to do the preprocessor work (and recursively follow includes) and search whether a function is indeed declared. It's not impossible, but it's best to have vim know the paths where header files are in order to look for them.
Look at a tool like exuberant ctags. It parses C-style files to find any identifier and store them in a tag file, so that each of them can be accessed quickly, inside Vim for example.
Once installed, in the shell command line, you have to create a tag file with this kind of command:
$ ctags *.c *.h
This will create an new file called tags, where all the c files and header files in the current directory are parsed. Please note that there are many options for this tool (like recursively include all lib headers, which can lead to a huge file, though), you may look at the doc for more details.
Once done, in Vim, there are several commands to use transparently the infos in this file. First check your current directory is the same as the tag file; then, to check if an identifier (like a function name) is already present in the tag file, you can use:
:ts myFunctionName
I don't think tag is a good enough solution to check whether function is defined. The flexibility of C syntax make it worse, because most tag tool is syntax-based other than semantics-based.
For example, at present, the most powerful code-completion plug-in for vim is
YouCompleteMe, which is semantic-based by virtue of Clang.
So IMHO, the answer to your question is: compile it!
In order to do compiling more convenience, you can add the following configuration in your .vimrc.
map <F6> :make install<CR>
After this, when you press F6, compiler will be launched to check your code.

How to associate specific files (NOT file types) with syntax highlighting in Sublime text 3?

I have build_config (and other *_config files), GdbRun and build.txt files which are basically bash shell scripts.
How could I associate these files with shell syntax ? To place a pattern like
'if filename is *_config or GdbRun or build.txt' somewhere.
BufferScroll plugin can remember most of view settings for a particular file including syntax.
Just install BufferScroll and change the syntax manually using the status bar or the command palette and it'll remember it next time you open that file.

How to tame vim's ":find" command

Say, I have files foo.js and bar.css in my project. There is a ":find" command in vim, which find files, matching string. But this command, alas, has some limitations. For example, if I launch this way - "vim", or even this way - "vim ." - there's nothing to be find in js subdirectory. But if I launch vim this way - "vim js/any_file_other_than_foo.js", then calling ":find foo.js" works pretty well.
Since it is not intuitive (i'm working in the same directory, "pwd" returns the same path), my first question is - can anybody explain how to circumvent this issue? And, even broader, is there any way to type something like find foo - and open first file, which name matches pattern foo.
thanks in advance.
You could try
:e[dit] **/*foo* and then press 'tab' to move to the first match.
the ** is a directory globbing pattern, while * is character matching.
If you were so inclined, you could write a simple fuzzy finder command, for more information you can check out the vim tips wiki: http://vim.wikia.com/wiki/Find_files_in_subdirectories
Vim's :find works by searching each directory in the path variable (and ignores pwd). By default, it does not search recursively. That's why find is only working for you when you open a js file. The '.' in path refers to the directory for the current file -- not pwd.
You can change path to include your desired directories:
set path+=$PROJECT/js
See :help path.
One of the magic bits to use is to add ** to a path to search that path recursively:
" search recursively in my project
set path+=$PROJECT/**
" search recursively from the current file's directory
set path+=./**
See :help file-searching for more magic.
A nice plugin that accomplishes a similar effect is Command-T.
The Command-T plug-in provides an
extremely fast, intuitive mechanism
for opening files with a minimal
number of keystrokes. It's named
"Command-T" because it is inspired by
the "Go to File" window bound to
Command-T in TextMate.
Files are selected by typing
characters that appear in their paths,
and are ordered by an algorithm which
knows that characters that appear in
certain locations (for example,
immediately after a path separator)
should be given more weight.should be given more weight.
Here is a screencast of Command-T in action.

Get the file name without file extension in a Vim function

I want to get the file name without the file extension in Vim.
I wrote the following function in my .vimrc file to compile and run the Java program:
:function! JAVA_RUN()
:!javac %^M
:endfunction
map <F3> :execute JAVA_RUN()<CR> :source $HOME/.vimrc<CR>
How can I get the file name without the extension inside the function?
:help expand() should give you the answer, see expand().
You should use the r modifier for %, with %:r instead of % to get the file name without extension.
If you want to write functions to build and execute files, you should also have a look at the documentation for shellescape, in order to prevent problems with spaces in file name or path.
If you want to expand a filename (other than % etc) take a look at fnamemodify()
fnamemodify({fname}, {mods}) *fnamemodify()*
Modify file name {fname} according to {mods}. {mods} is a
string of characters like it is used for file names on the
command line. See |filename-modifiers|.
fnamemodify("main.java", ":r") returns main.
I literally just read a similar question to this (in that someone else seemed to be trying to configure vim to build automagically for them with the F-key), and wrote an answer about how you can leverage the power of vim's :make command without even needing to write a Makefile. In your case, it's less directly related to the question, but I thought I'd mention it in case you were interested.
Furthermore, someone seems to have written something on Vim Tips Wiki about how to set up vim's :make command to specifically work with Java projects built with ant. I haven't worked with Java in a while myself, but in your case specifically it might be a good place to get started.
I came here looking for an answer for a similar question. I wanted to be able to extract the current class name from the java file being edited. I found a very neat way to do this in vim with an abbreviation:
ab xclass <C-R>=expand('%:t:r')<CR>
Place this line in your .vimrc (or similar) for this to work. An abbreviation will auto-trigger as soon as you press space, and so I usually prefix them with 'x' to avoid their accidental expansion.
The trick here is the combination of :t and :r in the argument to expand(). % is the "current file name", :t selects just the tail of the path ("last path component only") and :r selects just the root ("one extension removed"). (quoted parts are from the official expand() documentation.)
So when you are creating a new class in file /a/b/ClassIAmAboutToCreate.java you would type:
public class xclass {
the moment you press space after "xclass", the abbreviation will be expanded to public class ClassIAmAboutToCreate, which is exactly what you need.
Also, note that an abbreviation can be triggered by pressing Ctrl+] which avoids inserting a space after the class name.

How to switch between multiple vim configurations with a command or local vimrc files?

I work in several groups, each of which has its own tab/indentation/spacing standards in C.
Is there a way to have separate selectable VIM configurations for each so, when I edit a file, either:
I do something like set group=1 to select a configuration
a local .vimrc that lives in the working directory is used to set the configuration automatically
I have this in $HOME/.vimrc:
if filereadable(".vim.custom")
so .vim.custom
endif
This allows me to put a .vim.custom file in every directory to load commands and options specific to that directory. If you're working on multiple projects that have deep directory structures you might need something more sophisticated (e.g. walk up the directory tree until a .vim.custom is found), but the same basic idea will work.
UPDATE:
I now do something like this in order to read a .vim file from the same directory as the file I'm editing, regardless of what the current directory is.
let b:thisdir=expand("%:p:h")
let b:vim=b:thisdir."/.vim"
if (filereadable(b:vim))
execute "source ".b:vim
endif
In Summary
There are a few ways to do this, of which most have been suggested, but I thought I'd summarise them with two extra ones:
Per-directory vimrc - has the disadvantage that Vim must be started in the right directory: if your project is in ~/project1 and you have ~/project1/.vim.custom and do cd ~ ; vim project1/file.c, the custom settings won't be found.
Modelines - very effective, but has the disadvantage of needing to add them to all files (and remember to add them to new files)
Directory specific autocommands - this is very effective
Scan for a specific header in the file (see below) - this is the one I've used most in the past where working for different companies or on clearly named projects
Per-directory vimrc that's checked when the file is opened (see below). Another fairly easy one to implement, especially if your project code is all in one place.
Scanning for a Header
In a lot of organisations, there's a standard header (with a copyright notice and project name etc) at the top of every source file. If this is the case, you can get Vim to automatically scan the first (e.g.) 10 lines of the file looking for a keyword. If it finds it, it can change your settings. I've modified this to make it simpler than the form I use (which does lots of other things), but create a ~/.vim/after/filetype.vim (if you don't have one yet) and add something like this:
au FileType * call <SID>ConfigureFiletypes(expand("<amatch>"))
" List of file types to customise
let s:GROUPNAMETypes = ['c', 'cpp', 'vhdl', 'c.doxygen']
func! <SID>CheckForGROUPNAMECode()
" Check if any of the first ten lines contain "GROUPNAME".
" Read the first ten lines into a variable
let header = getline(1)
for i in range(2, 10)
let header = header . getline(i)
endfor
if header =~ '\<GROUPNAME\>'
" Change the status line to make it clear which
" group we're using
setlocal statusline=%<%f\ (GROUPNAME)\ %h%m%r%=%-14.(%l,%c%V%)\ %P
" Do other customisation here
setlocal et
" etc
endif
endfunc
func! <SID>ConfigureFiletypes(filetype)
if index(s:GROUPNAMETypes, a:filetype) != -1
call <SID>CheckForGROUPNAMECode()
endif
endfunc
Whenever a file of any type is opened and the file type is set (the au FileType * line), the ConfigureFiletypes function is called. This checks whether the file type is in the list of file types associated with the current group (GROUPNAME), in this case 'c', 'cpp', 'vhdl' or 'c.doxygen'. If it is, it calls CheckForGROUPNAMECode(), which reads the first 10 lines of the file and if they contain GROUPNAME, it does some customisation. As well as setting expandtabs or whatever, this also changes the status bar to show the group name clearly so you know it's worked at a glance.
Checking for Configuration When Opening
Much like JS Bangs' suggestion, having a custom configuration file can be useful. However, instead of loading it in vimrc, consider something like this, which will check when a .c file is opened for a .vim.custom in the same directory as the .c file.
au BufNewFile,BufRead *.c call CheckForCustomConfiguration()
function! CheckForCustomConfiguration()
" Check for .vim.custom in the directory containing the newly opened file
let custom_config_file = expand('%:p:h') . '/.vim.custom'
if filereadable(custom_config_file)
exe 'source' custom_config_file
endif
endfunction
You can also put autocommands in your .vimrc which set specific options on a per-path basis.
au BufRead,BufNewFile /path/to/project1/* setl sw=4 et
au BufRead,BufNewFile /path/to/project2/* setl sw=3 noet
Plugin doing the right thing:
http://www.vim.org/scripts/script.php?script_id=441
“This plugin searches for local vimrc files in the filesystem tree of the currently opened file. By default it searches for all ".lvimrc" files from the file's directory up to the root directory and loads them in reverse order. The filename and amount of loaded files is customizable through global variables.”
Assuming your fellow developers won't complain about it, you can always add vim settings to each file in the comments.
/*
* vim:ts=4:sw=4:expandtab:...
*/
int main(int argc, char **argv)
{
...
I created an open-sourced tool for just this purpose. Forget the headers, scanning, configurations, and local vimrc files.
Try swim.
Swim
swim is a quick tool for switching vimrc files and creating convenient aliases. Here's a short usage list. See the Github repo for a walkthrough gif and download instructions:
Usage
swim add ~/dotfiles/myVimrc favorite #Add new swim alias
swim ls #Show available swim aliases
swim add https://raw.githubusercontent.com/dawsonbotsford/swim/master/exampleVimrcs/vimrcWikia.vim example
swim with favorite #Set alias favorite as primary .vimrc
swim with main #Set alias main as primary .vimrc
Read More
https://github.com/dawsonbotsford/swim
After trying out the localvimrc plugin suggested by the previous poster, I very much like having non-futzy per-project control over vim settings.
It does ask confirmation before loading a .lvimrc file by default but there is a setting to automatically load .lvimrc files. Some might see this as a security hole, but it works as advertised.
I chose to .gitignore the .lvimrc files. Alternatively you can check them in as a form of shared settings (tab/space expansion, tabstops, other project-specific settings).
As mentioned by sledge the usage of that plug-in is the best option I have seen and use. jerseyboy commented that the utility recommended ask for confirmation before loading (ie. after opening every file). To avoid this just set at your main .vimrc the list of local .lvimrc files:
let g:localvimrc_whitelist='/development/kernel/.lvimrc'
Here's a variation on jamessan's
function! ConditionalLoad()
let cwd = getcwd()
if getcwd() =~ $HOME . "/src/mobile"
so $HOME/.vim.mobile
endif
endfunction
autocmd VimEnter * call ConditionalLoad()
I will frequently launch vi without a specific file that I'm jumping to so this enables loading config conditionally based on the current working directory. Downside is that the config isn't applied based on file but off of working directory.
I work in several groups, each of which has its own tab/indentation/spacing standards in C.
I work with all sorts of open source, all at the same time. It's not practical to be creating separate .vimrc files and reconfiguring the formatting standards. More than a decade ago, I finally got tired of dealing with the editor configuration and wrote a program called autotab to handle it.
When autotab is set up with Vim suggested, each time you load a file into Vim, autotab is invoked on it, and the Vim settings output autotab are passed to a :set command.
autotab reads several thousand lines from the file, analyzes them and determines the settings for the expandtab, tabstop and shiftwidth parameters.
It figures out whether the file uses hard tabs or just spaces for indentation, and it figures out the indentation size. If the file is indented with tabs, it figures out the right tab size, based on rendering the file sample using various tab sizes and judging it according to heuristics like line-over-line alignment of internal elements.
It works well enough that I stopped tweaking the algorithm years ago. If it gets confused, it's almost always because the file has formatting issues, such as the use of multiple conventions at the same time.
It is also "agnostic" of the file type and works well with a variety of different languages. I use it not only over C, but shell scripts, Lisp, Makefiles, HTML, and what have you.
Note that it doesn't handle other parameters of formatting that may be project-specific, like for instance, in C files, whether case labels in a switch statement are indented or not, or whether wrapped function argument lists are simply indented, or aligned to the opening parenthesis of the argument list. Vim does have settings for that sort of thing, and so the program could be plausibly extended to analyze the style and output those parameters.
Looking for mostly the same issue I also found the Sauce plug-in: http://www.vim.org/scripts/script.php?script_id=3992
It claims:
Sauce is a lightweight manager for multiple vimrc files, which can be used to load different settings for different environments. In short, you can maintain lots of different vim settings files and only load the one(s) you need when you need them.
I find it particularly interesting that it keeps it configuration all in its data directory instead of expecting the user to sprinkle dotfiles across the filesystem. This though often rather a metter of personal taste.
I have yet to test it though.
You can use stow for switching configuration (any dotfiles, not only .vimrc)
Install stow:
$ apt install stow
Create multiple directories for each configurations:
~$ ls -d ~/dotfiles/vim*
vim-all vim-webdev vim-go
Put different .vimrc's in them:
$ find ~/dotfiles -name .vimrc
/home/username/vim-golang/.vimrc
/home/username/vim-webdev/.vimrc
/home/username/vim-all/.vimrc
Now you can instantinate vim-golang config with this command (should be run inside dotfiles directory):
~$ cd ~/dotfiles
dotfiles$ stow -v vim-golang
LINK: .vimrc => dotfiles/vim-golang/.vimrc
Now it's linked:
$ cd ~ && ls -l .vimrc
.vimrc -> dotfiles/vim-golang/.vimrc
If you need to switch config, just re-stow it:
~$ cd dotfiles
dotfiles$ stow -v -D vim-golang
UNLINK: .vimrc
dotfiles$ stow -v vim-webdev
LINK: .vimrc => dotfiles/vim-webdev/.vimrc
$ cd ~ && ls -l .vimrc
.vimrc -> dotfiles/vim-webdev/.vimrc
More reading of it here: Managing dotfiles with GNU stow
Pros: pretty simple, no vim plugin dependencies, can be used for managing all dotfiles, not only .vimrc.
Cons: configs are independent of each other, you need to manage/update each of them separately (if you dont switch/update you configs too often - it'll not be the issue).

Resources