Running shell commands in GVim without echoing the Vim command - shell

When I use :! to run shell commands, like:
!echo hi
It prints both the VimScript command and it's output, so I get:
:!echo hi
hi
This is OK when I do it in command line mode, but when I run it via a .vim file I don't want to see it - I just want to see the result of the command.
Is there a way to disable the echoing of the VimScript command?
I know I can use
echo system('echo hi')
But that would prevent me from using it with interactive shell programs...
BTW, I'm using Linux - in windows this is not really a problem since shell commands run on a new console window anyways...
edit:
This is my small working example:
function! RunShellTask(cmd)
execute '!'.a:cmd
return v:shell_error
endfunction
call RunShellTask('echo hi')
I run it with :source %

You could try the :redir command:
*:redi* *:redir*
:redi[r][!] > {file} Redirect messages to file {file}. The messages which
are the output of commands are written to that file,
until redirection ends. The messages are also still
shown on the screen. When [!] is included, an
:
:
To stop the messages and commands from being echoed to
the screen, put the commands in a function and call it
with ":silent call Function()".
An alternative is to use the 'verbosefile' option,
this can be used in combination with ":redir".
I haven't tested, but you could try :redir #b, execute the shell commands from a function called with :silent call, read the output (from register b), filter out the vimscript commands, display it on the screen and then :redir end.
Another option is to try some plugins that provide similar functionality:
shellasync.vim : shellasync.vim plugin for asynchronously executing shell commands in vim
Conque Shell : Run interactive commands inside a Vim buffer
Screen (vim + gnu screen/tmux) : Simulate a split shell, using gnu screen or tmux, that you can send commands to.
Vicle : Vim - Interpreter Command Line Editor. Like Chimp or Slimv.

Related

ITerm: Is there a way to reprint output of previous command without running it?

Of course, we can feed the output of any command to a file. Using command > /tmp/filename
Or even better use command | tee /tmp/filename to have the standard output be fed onto the terminal as well as the file name.
However, If I just executed command is there a way for ITerm to reprint the output that command already fed to console without re-running the command (example use case: command is not idempotent and I want to grep something without having to touch the mouse)
You could use the script command, which records your input + the output your commands generate.
To use it, just run script at the beginning, before you start any execution, and this will throw you in a new shell. which gets recorded in a file called typescript in your HOME folder.
Once you are done, you can exit, and then have all of the input + output in that typescript log file.

How to test external tab completion script in Ruby

So say I have an external command, fart, that supports tab completion for its subcommands. When you type fart <\tab><\tab> in the command line, it prints out something like
$ > fart █
do some things here
or other stuff there
however, if you type fart <\enter>, it prints the help text
fart is a tool for doing things and stuff
Usage: fart <command>
Commands:
init Initialize a new something or other
status Report the status of the thing
version Show the fart version information
I want to test that the tab completion works via an integration test suite in Ruby. When I tell exec to execute fart \t\t, I get the help output, not the autocomplete output. How can I get exec to not terminate the shell command with a newline so that I can assert the autocompletion output?
You shouldn't fa^M^M exec the thing. It doesn't work like this. You need to interact with a PTY. Basically spawn a shell in a PTY, then send keys like you would do interactively.
Alternatively you could write expect scripts and use the expect utility found in most linux distros.
Auto-completion is a shell function, not a program function. When you hit tab, bash or some other shell is looking for completion definitions and uses them to show you the available options. It is not executing the program in any way.

How can I visually select, then execute shell commands directly in vim? [duplicate]

This question already has answers here:
Execute current line in Bash from Vim
(7 answers)
Closed 7 years ago.
When writing bash scripts in vim, it would be useful to be able to selectively run only a few lines from the script, e.g. if I have some script
#! /bin/bash
# more commands
mkdir /tmp/test_dir
echo "some output to STDOUT"
touch /tmp/test_dir/new_file
# more commands
say I just want to execute this part of the script
mkdir /tmp/test_dir
echo "some output to STDOUT"
touch /tmp/test_dir/new_file
how can I highlight and execute it in vim?
I have tried
v, select target text, :
which gives a prompt with :'<, '>
then tried :! w
but its not working properly.
I dont need to write the STDOUT of the shell commands to a file or anything, but I would like to be able to at least see the output.
From the answer of pacholik, you can extrapolate:
in visual mode, hit : and write w !bash
so that your whole command is :'<,'>w !bash
You will get the output as a result (but it won't change the file
If you remove the w , it will instead replace the line by the output of the buffer.
I have for example mapped r to "run command" in visual mode.
Like this:
vnoremap r :w !bash<cr>
I also have this in normal mode (to run the current line), with yr (you run)
nnoremap yr :.w !bash<cr>
You can use Quickrun plugin : http://vimawesome.com/plugin/quickrun-vim
It can run many languages on the fly (bash, python, c++...), and you can run only a selected area.
Everything you need is :
Set the filetype of your file (normally it's automatically detected, unless you created a new file, in this case just do for example : :set ft=sh for bash)
Select a part of your file with V.
Run :'<,'>QuickRun
The output opens in a new window.
You can tweak the plugin on many points, see the help.

Open Vim from a Rakefile?

I am creating a journal application for personal notes and have the following in my Rakefile:
task :new do
entry_name = "Entries/#{Time.now.to_s.gsub(/[-\ :]+/, '.').gsub(/.0500+/,'')}.md"
`touch #{entry_name}`
`echo "# $(date)" >> #{entry_name}`
end
The last part I would like to include is the opening of the Vim text editor but I am unable to figure out how to open it as if I called it directly from the bash terminal.
I have tried:
vim #{entry_name}
but unfortunately I think both of those open it as a background process.
I have been referencing "6 Ways to Run Shell Commands in Ruby".
As in the article you referenced, `s run the command in a subshell within the current process, but the real problem is that it's trying to take the output from the command run as well, which doesn't play nice with Vim.
You can either:
Use exec to replace the current process with the new one (note that the Ruby/Rake process will end once you've called exec, and nothing after it will run).
Use system to create a subshell like `s, but avoids the problem of trying to grab Vim's stdout. Unlike exec, after Vim terminates, Ruby will continue.
you need to pass the tty as standard input for backspaces etc. to work well in vim:
exec("</dev/tty vim a b")
obviously the backtick (`) didn't work but I was having issues with system/exec from a script.
first I get Vim: Warning: Input is not from a terminal, and then I see ^? when I use backspace.

Terminal emulator implementation - problems with repeated input

I am trying to implement a terminal emulator in Java. It is supposed to be able to host both cmd.exe on Windows and bash on Unix-like systems (I would like to support at least Linux and Mac OS X). The problem I have is that both cmd.exe and bash repeat on their standard output whatever I send to their standard input.
For example, in bash, I type "ls", hit enter, at which point the terminal emulator sends the input line to bash's stdin and flushes the stream. The process then outputs the input line again "ls\n" and then the output of the ls command.
This is a problem, because other programs apart from bash and cmd.exe don't do that. If I run, inside either bash, or cmd.exe, the command "python -i", the python interactive shell does not repeat the input in the way bash and cmd.exe does. This means a workaround would have to know what process the actual output came from. I doubt that's what actual terminal emulators do.
Running "bash -i" doesn't change this behaviour. As far as I know, cmd.exe doesn't have distinct "interactive" and "noninteractive" modes.
EDIT: I am creating the host process using the ProcessBuilder class. I am reading the stdout and stderr and writing to the stdin of the process using a technique similar to the stream gobbler. I don't set any environment variables before I start the host process. The exact commands I use to start the processes are bash -i for bash and cmd for cmd.exe. I'll try to post minimal code example as soon as I manage to create one.
On Unix, run stty -echo to disable "local echo" (i.e. the shell repeating everything that you type). This is usually enabled so a user can edit what she types.
In your case, BASH must somehow allocate a pseudo TTY; otherwise, it would not echo every command. set +x would have a similar effect but then, you'd see + ls instead of ls in the output.
With cmd.exe the command #ECHO OFF should achieve the same effect.
Just execute those after the process has been created and it should work.

Resources