How to disable the auto comment in shell script vi editing? - shell

I'm using vi(m) to edit a shell script and when I insert a comment and type , the new line came with a comment already.
How can I disable it ?
Ex :
# When I type enter, the comment simbol # below is inserted automaticaly.
#

I was finding the same answer, try
:set paste
this may help

I found some links solving your issue:
http://www.linuxquestions.org/questions/linux-general-1/vim-auto-comment-696916/
You're probably looking for this command
:set paste
Or you can add this line to your ~/.vimrc (which will allow you to toggle between paste and nopaste with Ctrl+P)
nm <C-P> :se invpaste paste?<CR>
http://ubuntuforums.org/showthread.php?t=833353
to resolve problem with inserting some text/code in vim with comments you can just add in your .vimrc file this line:
set pastetoggle=
that will make set paste on pasting and set nopaste when it's done..
http://vim.wikia.com/wiki/Disable_automatic_comment_insertion
To disable it just once for the current session:
:set formatoptions-=cro
To disable for all files and sessions, use this:
autocmd FileType * setlocal formatoptions-=c formatoptions-=r formatoptions-=o
This sets up an auto command that fires after any filetype-specific plugin; the command removes the three flags from the 'formatoptions' option that control the automatic insertion of comments. With this in your vimrc, a comment character will not be automatically inserted in the next line under any situation.
Use this command to check your format options:
:set formatoptions?
Hope it's useful, let me know if you got it clear.
Bye

This feature is useful, how about just pressing Ctrl-u in insert mode?
it will delete everything until the beginning of the line. By doing that you do not lose auto comments.
See more here and here:

You're looking for the option:
:see paste
I have gone through many blogs where there was an option:
:see formatoptions-=cro
Which did not work!

The vi stack exchange documents another excellent option:
https://vi.stackexchange.com/a/1985/12256
You can add something like below to your .vimrc file to ensure shell scripts won't automatically insert the comment leader.
au FileType sh setlocal fo-=c fo-=r fo-=o
The vim documentation will tell you what each of the options (c, r, o) mean.
http://vimdoc.sourceforge.net/htmldoc/change.html#fo-table

Related

How do I edit current shell command without executing it?

There seems to be quite a lot of information on how to edit and execute a command using your editor using "edit-and-execute-command (C-x C-e)", but what I would like to achieve is take the current shell command, apply certain filtering (using a script) and then return it to prompt for further approval/manual changes before execution. Is this possible with bash?
Latest update based on my experience
The part 0"+y$dd in the following mapping is really something that you should carefully think about and tailor it to your taste/workflow/experience.
For instance, very frequently I've found myself ending up with multiple lines in the buffer, where I only want to execute the one the cursor is on; in this case I can use 0"+y$dd:%d<CR> instead of 0"+y$dd.
And this is just one of the possible scenarios.
Final answer for those who like vim
Set vim as your EDITOR/VISUAL, so that when editing a command line, you will use vim to edit it.
Put au BufEnter /tmp/bash-fc.* nn <Leader>d 0"+y$dd:wq<CR> in your ~/.vimrc file to map Leaderd (which you will rarely use when editing a command) to the action "delete the current line into the + register without the trailing EOL".
you can use either the + or the * register in the mapping above; the ways to paste into the terminal will likely differ; you need the +clipboard option for these registers to be available.
When finished editing a command in the vim editor, hit EscapeLeaderd.
Paste the clipboard into the terminal (this is terminal-dependent).
Original answer
I often need to do the same, and I do it as follows. (I normally use the set -o vi in bash, so points 1 and 2 in the following are different if you use set -o emacs, the default; based on your question it looks like points 1 and 2 are unified in Ctrl+x followed by Ctrl+e, which is harder to type, imho.)
hit Escape to be in normal mode,
hit v to enter the editor to edit the command,
edit the command as I like,
(This is where you ask the question.)
hit Escape0"+y$dd:wq,
Note: 0"+y$, not simply "+yy, as the latter would copy the newline too, and this would result in executing the command upon pasting it in the command line,
paste the clipboard on the command line
how to do this depends on the terminal you are using, I guess; I hit Ctrl+Alt+v in URxvt.
proceed to approval/manual edit.
Clearly this is just a workaround, consisting in copying the edited command into the clipboard before deleting the whole command, so that nothing gets executed upon exiting the editor; however it's the best I can get for myself.
Update
As my EDITOR (and VISUAL) is equal to vim, when I edit the command, I edit it in vim.
In this respect, I have noticed that the buffer is named /tmp/bash-fc.random, where random is a 6-characters alphanumeric random string.
This gives space to a lot of possiblities, if you use vim as your editor, as you can define some mapping in your .vimrc to execute the whole sequence Escape0"+y$dd:wq. For instance, one command that you'd rarely use when editing a command line is Leaderd; therefore you can put the following mapping in your .vimrc file
au BufEnter /tmp/bash-fc.* nn <Leader>d 0"+y$dd:wq<CR>
so that step 4 in the above recipe becomes
hit EscapeLeaderd
It's not possible to do that in Bash/readline but it's possible in zsh
using edit-command-line command:
darkstar% autoload edit-command-line; zle -N edit-command-line
darkstar% bindkey "^X^E" edit-command-line
Now press Control-x Control-e to open your editor, edit line, leave the editor - you will see the updated command line but it will not be executed automatically.
Now that I think about it, maybe a variation of what #kenorb suggested in a comment is the best workaround (as it seems no solution exists), if we want to stick to bash.
What you can do is prepend a # (the comment character in bash) to the command, rather than echo. Then when you exit the editor, the command will be ineffective, and you will only have to press arrow up (or k, if you use set -o vi), remove the # and confirming.
Note that this strategy adds just a few keystrokes, so it can be fairly efficient, depending on your typing level.
These pieces might get you closer:
a) replace the the normal binding for newline newline (ctrl-M)
bind -x '"\C-M":date"
b) grab the current line from the history using !#
replace date with whatever script you want.
c) edit manually
d) if necessary, somehow tie in !!:p which prints the new command to the command line but does not execute it, thus letting you manually edit it.
e) using ctrl-J submit edited command rather than a newline
or they might not ....
There is an option in bash to modify command from history without executing it. I'm not sure it it's possible to use script for this, doesn't seem to be likely. Although, you can make modifications using history modifiers.
Enable option histverify to prevent execution of modified command
Use chain of modifiers to change last command
Use "!!" to put your result to command line for final edit
Here is how it looks:
$ shopt -s histverify
$ ls *.sh
script1.sh script2.sh script3.sh script-return.sh
$ !!:s/*/script1/:p
ls script1.sh
$ !!:s/1/2/:p
ls script2.sh
$ !!
$ ls script2.sh
script2.sh
I'd like to point you to the Composure framework for Bash (I'm not affiliated with it): https://github.com/erichs/composure
It provides draft and revise functions that sound like they could help with what you're trying to do. Here's a (long) quote from the project's readme file:
Composure helps by letting you quickly draft simple shell functions,
breaking down your long pipe filters and complex commands into
readable and reusable chunks.
Draft first, ask questions later
Once you've crafted your gem of a command, don't throw it away! Use
draft () and give it a good name. This stores your last command as a
function you can reuse later. Think of it like a rough draft.
$ cat servers.txt
bashful: up
doc: down
up-arrow
$ cat servers.txt | grep down
doc: down
$ draft finddown
$ finddown | mail -s "down server(s)" admin#here.com
Revise, revise, revise!
Now that you've got a minimal shell function, you may want to make it
better through refactoring and revision. Use the revise () command
to revise your shell function in your favorite editor.
generalize functions with input parameters
add or remove functionality
add supporting metadata for documentation
$ revise finddown
finddown ()
{
about finds servers marked 'down' in text file
group admin
cat $1 | grep down
}
$ finddown servers.txt
doc: down
It does not seem possible with a keyboard shortcut, at least:
$ bind -P | grep -e command -e edit
complete-command can be found on "\e!".
edit-and-execute-command can be found on "\C-x\C-e".
emacs-editing-mode is not bound to any keys
possible-command-completions can be found on "\C-x!".
vi-editing-mode is not bound to any keys
This can be done in native bash using readline specifically READLINE_LINE and READLINE_POINT variables. I use this functionality all the time though not through vim, you would need to get the value of $selected from your vim command and if not empty it takes your original line + your input and replaces your original line with the combination without executing. output as a variable
_main() {
selected="$(__coms_select__ "$#")"
origonal_text=$READLINE_LINE READLINE_LINE="${READLINE_LINE:0:$READLINE_POINT}$selected${READLINE_LINE:$READLINE_POINT}"
READLINE_POINT=$(( READLINE_POINT + ${#selected} ))
}
bind -m emacs-standard -x '"\C-e": _main '
bind -m vi-command -x '"\C-e": _main '
bind -m vi-insert -x '"\C-e": _main '
Edit
Just remembered these two utilities that will let you do this as well.
Vipe allows you to run your editor in the middle of a unix pipeline and edit the data that is being piped between programs.
vp, up, vipe, Neomux (upgrade of nvim terminal) you can do some pretty neat throwing buffers between the terminal and split window.
and Athame (full vim on the command line)
https://github.com/ardagnir/athame
careful with that one though plugins work on the cli and it can get funky if you got tons of plugins

Using VIM command on all open files

I have a list of files i've opened in VIM using this command:
vim `cat list.txt`
I'm looking to run this command on all open files:
:99,104 norm i#
(from lines 99 to 104, insert a comment "#") <--simple, works
When I run the above command to insert it works as expected on the current file. How do I get VIM to run the exact same command on all open files? I tried :argdo, :windo, :bufdo but didn't have any luck.
Any suggestions?
I guess bufdo would work, if you have set hidden (to allow bufdo to change buffers without saving) before:
:set hidden
:bufdo 99,104 norm i#
Then save all files with :bufdo! w or :wa.
(Note: set hidden could be replaced with set autowrite as well.)
I think sed would be a better option if you can use it. sed is a command line editor rather than an interactive editor like vim.
sed -i '99,104s/^/#/' list of files
Because you've supplied all files as arguments, :argdo is the correct command. (Unless you open other files, :bufdo would work, too.) If you don't want to :set hidden (as indicated in the other answer), you have to immediately persist the buffer via :update. Because you're using a :normal command, you have to enclose it in :execute to be able to concatenate another Ex command:
:argdo 99,104 execute 'norm i#' | update

Save file In a different folder in vim

I'm working with several files in gvim in Windows 7. I need to test the files (Python scripts) in linux. So apart from their original location I want to also save the files in a folder called linux. I want to do this with new files that I will be creating/modifying. That's why I want to use a mapping with the % sign to get the name of the current file Into the new path.
The problem I'm having is that the % sign is escaped with a backslash, so this doesn't work :
:w C:\projects\linux\%:t
Being the original location:
C:\projects\foo\
Is there a simple way to just save the current file in a different folder? (I have read that the % sign is a filename character, so I could erase it from the string isfname and it should work but I think I am making it more complicated than what it really is.)
Sorry, late to the party, but you could also use the workaround
:exe 'w C:\projects\linux\' . expand('%:t')
My recollection is that you can escape the backslash by doubling it (but I'm not on Windows at present so I can't confirm it immediately). You don't need to escape them all, just the one which is causing trouble:
:w C:\projects\linux\\%:t
You might be able to do this sort of thing fairly automatically using the autocmd feature.
The following (untested) line in your platform's equivalent of ~/.vimrc will update a copy of a file when gvim makes modifications:
" clear commands
autocmd!
" when writing buffers, save a copy -- see :help filename-modifiers
autocmd BufWritePost c:/path/to/source/directory w %:t
The :t will take just the tail of the pathname; if you're working with multi-level directories, perhaps :p:. would be better. See the documentation for more details.
If you change the last backslash to a forward slash it will work:
:w C:\projects\linux/%:t

Syntax highlighting in Bash vi-input mode

If I enable bash's input mode using set -o vi, then press Esc followed by v, I get a vi window which allows me to edit a temporary file which is executed once I leave. In that window I would like to enjoy Vim syntax highlighting for Bash scripts. It doesn't suffice to execute :syntax enable. The problem might be related to the fact that the temporary file has no .sh ending nor a #!/bin/bash head which could be used to determine the filetype.
I'd use the shorter formulation:
au BufRead,BufNewFile bash-fc-* set filetype=sh
I believe this type of autocmd is the canonical way to handle filetype assignments (at least, my .vimrc has a number of them).
#Eric Fortis, please chime in or correct me if there's a reason you did it differently.
Add this to your .vimrc
if expand('%:t') =~?'bash-fc-\d\+'
setfiletype sh
endif
the temporary files are of the form bash-fc-3537253897, so the regex matches if the file begins with bash-fc- and applies the filetype.

How do I select the line in bash terminal

Is it possible to select part of a string in the bash terminal and delete it at once, rather than navigating to a point in the command and backspacing it all??
thanks!
I'm not 100% sure I understand your question.
If you are at the interactive command line:
ctrl-u: Deletes everything to the left of your cursor
ctrl-k: Deletes everything to the right of your cursor
I'm using emacs bindings and my favourite command line shortcuts, which were not included in the previously linked tutorial, are the following:
^W - delete last word
meta-b - move cursor back one word
^R - find a previously used command
!$ - last attribute of the last command
!! - last command
You can also manipulate the history with regexps, although that could quickly get quite messy. See "man zshexpn" for reference, mostly the same regexp syntax works for bash also.
Example:
1) If you execute the following command:
echo first second third fourth fifth
2) Then you could execute the same command and remove "first" by:
!!:s/first//
If this was not what you were after, please clarify on your question! :)
See this. Alternatively, set -o vi to have vim-like key bindings.
Note that the list given in the link is not full. You might read man bash for a good reference. Usually, ALT-x might be replaced by ESC, x if you run bash inside a terminal that uses Alt-letter shortcuts for windowing system.

Resources