BASH file name completion - bash

In BASH I can normally start typing a file name, then type TAB and it will give me some suggestions.
I have a list of files that look like this:
20130519114000_add_hstore.rb
20130615125517_create_sites.rb
20130616112833_create_delayed_jobs.rb
....
Is there a way I could type something like "*delayed" and then TAB (or something) to find "20130616112833_create_delayed_jobs.rb".
At the moment, sifting through those numbers at the start of the filenames is too much cognitive load :)

Yes. The details can vary depending on your keyboard, and your Readline command bindings, and how you're logged into the system, and so on, but typically you can do this by typing *delayed, and then hitting Alt+g instead of TAB. (Search for glob-complete-word in §8.4.8 "Some Miscellaneous [Readline] Commands" in The Bash Reference Manual.)

You can use either:
ls *delayed*
or
ls | grep delayed
to filter list of files to what you want.

Related

Bash completion using output from script

I know there are a lot of tutorials on bash completion, but I just can't figure this out.
All I want is this. If I type myscript[tab][tab], then "myscript list-commands" is run. It will output a space delimited list of available commands (but I can output it however is appropriate). That output list is used for tab completion.
What do I put it my .bashrc to make that happen?
The easiest way is using a list of words/commands that your script supports:
Put the following into your .bashrc to have your script myscript support the commands add, list, delete:
complete -W "add list delete" myscript
This will leads to
> myscript [tab][tab]
add list delete
Hope this help. For further, more dynamic options than a simple wordlist have a look at the manpage of the complete command: https://ss64.com/osx/complete.html

How can I make shell autocomplete the beginning of a filepath?

I have a project with a deeply nested folder structure. Most of the time I know the name of the file I want to work with, but the folder path is too long/complicated to type when I want to edit it, like:
vim folder/is/deep/down/there/myfile.js
Is there a way to make the shell auto populate the path for me if the filename is unique, with something like:
vim *myfile.js
press TAB -->
vim folder/is/deep/down/there/myfile.js
I mostly use bash, but I'm fine with zsh if it can solve the problem.
I think this is what you're looking for, vim will open all instances of myfile.js in the directory. Fish shell will allow me to tab through the different matching files but I'm not sure it that works with bash.
vim **/myfile.js
What could be a good idea would be to use locate utility in a bash script.
Calling your bash script passing filename as argument would be a smart move, and then using the previously named utility to find it.
Having done that you could simply find if there was 1 or more matches, and if there's just a match you can just use vim [match].
And obviously, the script could be called like ./openinvim.sh myfile.js

Vim open a file found through grep

So I'm browsing a file in vim. I realize the function I am looking for is another file. So I do :! ack-grep "function tracking" ../ to look for it, and I see I need to examine file "../../tracking/api/ etc etc" some really long file name. what I'm doing now is trying to remember this file, type fg to get back into vim, and then :e "that really long file name". I'm wondering if there's an easier way to do this?
For instance, can I do something like vim -addtab <some file> from the command line once I've used ack-grep to find what I'm looking for, and then when I do fg to get back to vim, the file will be open in one a tab?
Awesome, lots of suggestions. I'll try them all out and in comments as I do. Then I'll pick what worked best for me once I've tried them all.
So this is the function that I settled on:
function! s:NewTabGrep(...)
let args=split(a:1)
if len(args) == 2
let dir=args[1]
else
let dir='.'
endif
echom args[0] . " " . shellescape(dir)
tabnew | execute "r ! ack-grep ". shellescape(args[0]) ." ". shellescape(dir)
endfunction
com! -nargs=? GrepTab call s:NewTabGrep('<args>')
This performs the search, and opens the results in a new vim tab. Then I can use CtrlP to open whichever file seems most interesting. Thanks to Merlin2011 for inspiration.
You can do :r ! ack-grep "function tracking" ../ to pull the output directly into the vim buffer, and then use gf to navigate to the file under the cursor.
If you want to open the file in a new tab instead, you can do Control-W, gf in normal mode.
Update: If you want the output of the command to appear in a new tab, you can do the following, which opens a new tab, and then immediately pulls the output of the command into it.
:tabnew | r!ack-grep "function tracking" ../
:vimgrep does this by default! it's the best! in fact, it's so cool, that you can even use :vim to invoke it hahaha
e.g. search all python files for "function tracking" (works best if you keep your vim working directory in your source code's root folder)
:vim /function tracking/ **/*.py
^ this will go to the first search result, and then open the quickfix window with a list of search results. I use a binding like nmap <silent> \` :QFix<CR> to quickly toggle it open and off. See... http://vim.wikia.com/wiki/Toggle_to_open_or_close_the_quickfix_window
--
however, there's a better way for navigating to the function: using CTRL-] which does an instant jump to the definition! Combined with CTRL-O and CTRL-I (jump backwards/forwards), you have an unstoppable move-around files-efficiently combo which will make you forget why you ever used IDE's =D
I googled this wiki page: http://vim.wikia.com/wiki/Browsing_programs_with_tags. One other thing you have to do is download Exuberant Ctags and build a tags file in your working directory: ctags -R ...then you're all set! (note that on Macs/BSD, it has its own ctags which wont work, you gotta use the exuberant one)
Vim has the :grep command that runs grep and stores the results into the quickfix list(you can also use :lgrep to load them to the location list). :grep also jumps to the first result, but if you don't want that you can use :grep! to just load the results to the quickfix list.
Once the results are loaded, you can use :copen to open the quickfix list(or :lopen to open the location list) and navigate between the results, or use :cfirst, :cnext, :cprevious and :clast(or :lnext, :lfirst, :lprevious and :llast) for navigation.
So, if you want to open the result in a new file, you have three options:
:grep! "function tracking" ../**/*, :copen to open the quickfix list, put cursor on the first result, ctrl-W Enter to open the result in a new window, ctrl-W T to move the window to a new tab.
:grep! "function tracking" ../**/*, :tabnew to open a new tab, :cfirst to jump to first result.
:tabnew to open a new tab, :grep "function tracking" ../**/* to perform the search and open the first result automatically.
You might find it easier to just use the quickfix list for navigation instead of opening new tabs.
:grep uses grep by default, but you can set the grepprg option to make it use ack-grep instead(you might also need to set grepformat to recognize the output). You can also use :vimgrep to do a search with Vim's regular expression without using an external program, but it will be slower.
:exec 'tab split '.fnameescape(system('ack-grep "function tracking" ../'))
should do the trick. (Make it into a function!)
I recommend you to use the ack plugin., Note that if you have vim-dispatch installed, you can search with ack.vim asynchronously(You need to write: let g:ack_use_dispatch=1 in your vimrc file). Also I recommend ag to replace ack since it's really fast.

bash completion directory style partial suggestion printing

I am working on a script called to that bookmarks file system locations in bash (with limited support for zsh). You can find the source here: https://github.com/resultsreturned/to
The script supports tab completion for all operations.
Say you have "bookmarked" the location of a folder:
mara#andromeda:~/bin/android-sdk-linux$ to -b android
The script then allows you to access subfolders of the bookmark, like so:
mara#andromeda:~$ to android/docs/
mara#andromeda:~/bin/android-sdk-linux/docs$
Pressing tab twice will give suggestions:
mara#andromeda:~$ to android/s<TAB><TAB>
android/samples/ android/sd-card/ android/sources/ android/system-images/
However, I would rather that the suggestions print only the portion of the path that is not currently input into the buffer. For example, the cd command:
mara#andromeda:~/bin$ cd android-sdk-linux/s<TAB><TAB>
samples/ sd-card/ sources/ system-images/
Note how the suggestions only contain the directory level that is currently being input.
So the question is, how do you control the way bash prints suggestions? Is it possible to do this independently of the completion wordlist (for compgen/complete)? Is there some way to define a regex that would process the completion wordlist for printing as suggestions?
Since feature requests to mark a comment as an answer remain declined, I copy the above solution here.
So the solution turns out to be using -o filenames when invoking complete. Showing only the substrings of COMPREPLY bash completion options to the user – resultsreturned

bash tab completion filter out options

I would like to make tab completion in bash a bit more intelligent.
Let's say I have a folder with a src file .lisp, and a compiled version of that file .fasl. I would like to type vi filename [tab tab], and the .lisp autocompletes as the only option. That is, it's not likely that I want vim to open a compiled binary, so don't have it in the list of autocomplete options to cycle through.
Is there a way that I can keep a flat list of extensions that autocomplete ignores, or somehow customize it for vim, so that autocomplete ignores only particular file extensions when a bash command starts with vi ...
Any ideas are appreciated.
Thanks!
From man bash:
FIGNORE
A colon-separated list of suffixes to ignore when performing
filename completion. A filename whose suffix matches one of the entries in FIGNORE is excluded from the
list of matched filenames. A sample value is ".o:~" (Quoting is
needed when assigning a value to this variable, which contains
tildes).
So, for your example this can be set in your .bashrc file with
FIGNORE=".o:~:.fasl"
or, if you want to keep any other site-wide settings:
FIGNORE=".o:~:.fasl:$FIGNORE"
The bash complete command seems to be what you want.
Here is a Linux Journal link to 'complete' command video. and here is the follow-up page More on Using the Bash Complete Command
The links explain it quite well, and here is a related SO Question/Answer: Bash autocompletion across a symbolic link

Resources